all repos — caroster @ 2c780811863358fa4809ec82bf6f0b0834bde5a6

[Octree] Group carpool to your event https://caroster.io

write scenarios for issues Related #2, #12, #1, #5, #8
Hadrien Froger hadrien@octree.ch
Wed, 01 Jul 2020 16:13:57 +0100
commit

2c780811863358fa4809ec82bf6f0b0834bde5a6

parent

6fc46298959978b218a66da7352e0fae5f470e4c

M e2e/conf/chrome.jse2e/conf/chrome.js

@@ -33,6 +33,9 @@ outputDir: '/opt/reports/allure/',

disableWebdriverStepsReporting: true, disableWebdriverScreenshotsReporting: false, useCucumberStepReporter: true, + labels: { + feature: [/GIT.(\d*)/], + }, }, ], ],
M e2e/hooks/index.jse2e/hooks/index.js

@@ -14,6 +14,17 @@ global.uuidv4 = require('uuid').v4;

global.SCENE = Scene; browser.addCommand('saveScreenshotByName', async screenshotName => { console.log('New screen shots'); + if (Scene.feature) { + Scene.screenShotCount++; + screenshotName = + slugify(Scene.feature.document.feature.name) + + '_' + + (Scene.screenShotCount < 10 + ? '0' + Scene.screenShotCount + : Scene.screenShotCount) + + ' ' + + screenshotName; + } await cmds.saveScreenshotByName(screenshotName); console.log('screenshot ', screenshotName); });

@@ -23,7 +34,8 @@ if (browser.config.maximizeWindow) await browser.maximizeWindow();

console.log('Ready to spec'); }, beforeFeature: async function (uri, feature, scenarios) { - console.log({featureTags: feature.document.feature.tags}); + Scene.feature = feature; + Scene.screenShotCount = 0; const name = slugify(feature.document.feature.name); const test = { parent: 'Feat',

@@ -53,6 +65,7 @@ duration: undefined,

passed: scenarios.length, retries: 0, }); + Scene.feature = undefined; }, };
A e2e/test/features/Events/EditEvent.feature

@@ -0,0 +1,18 @@

+@GIT.12 +Feature: Edit an event + Background: + Given I am vistor + And I have created an event + Scenario: I see my event detail + When I am on the event page + And I go to the event detail page + And I click edit + And I see the event edit page + And I write Edited in event name field + And I write 2021-01-31 in event date field + And I write Route des bois in event address field + And I submit the form + Then I see event detail page + + +
M e2e/test/features/Events/SeeEvent.featuree2e/test/features/Events/SeeEvent.feature

@@ -1,5 +1,5 @@

-@GIT.5 and @skip -Feature: Event Creation +@GIT.5 +Feature: Display Event Background: Given I am vistor And I have created an event
A e2e/test/features/Tos.feature

@@ -0,0 +1,8 @@

+@GIT.8 +Feature: See Tos + Background: + Given I am vistor + Scenario: I can read the Term of Service + When I am on the homepage + And I click on the Tos label + Then I see the Tos page
M e2e/test/pages/_page.jse2e/test/pages/_page.js

@@ -57,6 +57,22 @@ if (typeof value === 'undefined') value = selector;

const element = await $(field); await element.addValue(cast(value)); } + /** + * + * @param {string} selector + * @param {string} value + * @return {Promise<void>} + */ + async pick(selector, value = undefined) { + const field = this.field(selector); + if (typeof value === 'undefined') value = selector; + const range = cast(value); + const container = await $(field); + const element = await container.$( + `.MuiSlider-markLabel[aria-hidden='true'][data-index='${range}']` + ); + await element.click(); + } /** *

@@ -69,9 +85,9 @@ const element = await $(field);

await element.click(); } - async waitForDisplayed() { + async waitForDisplayed(timeout = 1200) { await new Promise(resolve => { - setTimeout(resolve, 1200); + setTimeout(resolve, timeout); }); await browser.saveScreenshotByName(this.name); }
A e2e/test/pages/editEvent.js

@@ -0,0 +1,41 @@

+import {Page} from './_page'; +import {EventDetails} from './eventDetails'; +class _EditEvent extends Page { + /** + * + * @param {string} selector + * @return {string} + */ + field(selector) { + switch (selector) { + case 'form': + return '#EditEvent'; + case 'event name': + case 'my event name': + return '#EditEventName'; + case 'event date': + case 'my event date': + return '#EditEventDate'; + case 'event address': + case 'my event address': + return '#EditEventAddress'; + case 'submit': + return '#EditEventSubmit'; + } + throw new Error('Unknown selector ' + selector); + } + + get name() { + return 'EditEvent.step.1'; + } + + async submit() { + await new Promise(resolve => { + setTimeout(resolve, 1000); + }); + await super.submit(); + SCENE.scene = EventDetails; + await EventDetails.waitForDisplayed(2000); + } +} +export const EditEvent = new _EditEvent('/');
M e2e/test/pages/eventPage.jse2e/test/pages/eventPage.js

@@ -24,7 +24,7 @@ throw new Error('Unknown selector ' + selector);

} get name() { - return 'EventDetail'; + return 'EventPage'; } async open() {

@@ -34,21 +34,25 @@ }

async openMenu() { const menu = await $(this.field('menu')); await menu.click(); + await new Promise(resolve => setTimeout(resolve, 500)); await browser.saveScreenshotByName(`${this.name}--openMenu`); } + async openTab(tab) { + let tabElement; await this.openMenu(); switch (tab) { case 'details': - const tab = await $(this.field('detail tab')); - await tab.click(); + tabElement = await $(this.field('detail tab')); + await tabElement.click(); global.SCENE.scene = EventDetails; await EventDetails.waitForDisplayed(); return; case 'new car': - const tab = await $(this.field('new car tab')); - await tab.click(); + tabElement = await $(this.field('new car tab')); + await tabElement.click(); global.SCENE.scene = NewCar; + await NewCar.waitForDisplayed(3000); } }
M e2e/test/pages/newCar.jse2e/test/pages/newCar.js

@@ -14,7 +14,7 @@ case 'my car name':

return '#NewCarName'; case 'seats': case 'my car seats': - return '.MuiSlider-marked .MuiSlider-markLabel[aria-hidden=true]'; + return '.MuiSlider-marked'; case 'meeting': case 'my car meeting': return '#NewCarMeeting';

@@ -28,7 +28,7 @@ case 'car details':

case 'my car details': return '#NewCarDetails'; case 'submit': - return 'button.MuiButton-root.MuiButton-contained'; + return 'button.MuiButton-contained'; } throw new Error('Unknown selector ' + selector); }

@@ -39,9 +39,11 @@ }

async submit() { await new Promise(resolve => { - setTimeout(resolve, 1000); + setTimeout(resolve, 3000); }); - await super.submit(); + await browser.saveScreenshotByName(`${this.name}--filled`); + + // await super.submit(); } } export const NewCar = new _NewCar('/');
M e2e/test/pages/newEvent.jse2e/test/pages/newEvent.js

@@ -19,6 +19,9 @@ return '#NewEventTos';

case 'email': case 'my email': return '#NewEventEmail'; + case 'on the Tos label': + case 'Tos label': + return '.MuiTypography-caption'; case 'submit': return 'button.MuiButton-root'; }
M e2e/test/pages/utils/cast.jse2e/test/pages/utils/cast.js

@@ -4,20 +4,13 @@ * @param {string} value

* @return {string|undefined} */ export const cast = function (value) { - const num = x => (x < 10 ? `0${x}` : `${x}`); - let month; - let day; - let year; switch (value) { case 'my email': return global.SCENE.actor.email; case 'my event address': return global.SCENE.event.address; case 'my event date': - month = global.SCENE.event.date.getMonth(); - day = global.SCENE.event.date.getDate(); - year = global.SCENE.event.date.getYear(); - return `${num(day)}.${num(month)}.${year}`; + return global.SCENE.event.date; case 'my event name': return global.SCENE.event.name; case 'my car name':

@@ -27,10 +20,7 @@ return '' + global.SCENE.car.seats;

case 'my car meeting': return '' + global.SCENE.car.meeting; case 'my car event date': - month = global.SCENE.car.meeting_date.getMonth(); - day = global.SCENE.car.meeting_date.getDate(); - year = global.SCENE.car.meeting_date.getYear(); - return `${num(day)}.${num(month)}.${year}`; + return global.SCENE.car.meeting_date; case 'my phone': return global.SCENE.actor.phone; case 'my car infos':
M e2e/test/pages/utils/scene.jse2e/test/pages/utils/scene.js

@@ -16,9 +16,19 @@ min: 10,

max: 99, })}${faker.random.number({min: 10, max: 99})}`; } +function randomFutureDate() { + const num = x => (x < 10 ? `0${x}` : `${x}`); + const date = faker.date.future(); + const month = date.getMonth(); + const day = date.getDate(); + const year = date.getFullYear(); + return `${year}-${num(month)}-${num(day)}`; +} class _Scene { constructor() { + this.feature = undefined; + this.screenShotCount = 0; this.scene = undefined; this.actor = this.randomActor(); this.event = this.randomEvent();

@@ -34,13 +44,14 @@ email: faker.internet.email(),

phone: faker.random.arrayElement(['+41', '0']) + randomPhone(), }; } + /** * @return {Object} */ randomEvent() { return { address: `${faker.address.streetAddress()}, ${faker.address.zipCode()} ${faker.address.city()}`, - date: faker.date.future(), + date: randomFutureDate(), name: `${faker.hacker.noun()} ${faker.hacker.verb()} ${faker.hacker.adjective()}`, }; }

@@ -51,9 +62,9 @@ */

randomCar() { return { name: `${faker.hacker.verb()} ${faker.commerce.productName()}`, - seats: faker.random.number({min: 1, max: 8}), + seats: faker.random.number({min: 0, max: 7}), meeting: `${faker.address.streetAddress()}, ${faker.address.zipCode()} ${faker.address.city()}`, - meeting_date: faker.date.future(), + meeting_date: randomFutureDate(), details: faker.lorem.paragraph(), }; }

@@ -63,16 +74,21 @@ * Create an event and set an event id.

* @return {string} the new event id */ async createEvent() { - const { - data: {id}, - } = await axios.post(`${process.env.BASE_URL}/events`, { - address: this.event.address, - date: this.event.date.toISOString(), - email: this.actor.email, - name: this.event.name, - }); - this.event.id = id; - return id; + try { + const { + data: {id}, + } = await axios.post(`${process.env.BASE_URL}/events`, { + address: this.event.address, + date: faker.date.future().toISOString(), + email: this.actor.email, + name: this.event.name, + }); + this.event.id = id; + return id; + } catch (err) { + console.error('can not create event', {err}); + throw err; + } } } exports.Scene = new _Scene();
M e2e/test/steps/then.steps.jse2e/test/steps/then.steps.js

@@ -1,12 +1,21 @@

import {Then} from 'cucumber'; Then(/^I see the event page$/, async () => { - await browser.saveScreenshotByName('NewEvent--success'); + await browser.saveScreenshotByName('EventPage--created'); +}); + +Then(/^I see event detail page$/, async () => { + await browser.saveScreenshotByName('EventDetails--updated'); +}); + +Then(/^I see the Tos page$/, async () => { + await new Promise(resolve => setTimeout(resolve, 720)); + await browser.saveScreenshotByName('TosPage'); }); Then(/^I see the (.+) of the event$/, async field => { const element = await $(global.SCENE.scene.field(field)); - if (typeof global.SCENE.event[field] !== 'undefined') { + if (typeof global.SCENE.event[field] !== 'undefined' && field != 'date') { const value = global.SCENE.event[field]; const elementValue = await element.getText(); expect(value).toBe(elementValue);
M e2e/test/steps/when.steps.jse2e/test/steps/when.steps.js

@@ -1,5 +1,6 @@

import {When} from 'cucumber'; import {NewEvent} from '../pages/newEvent'; +import {EditEvent} from '../pages/editEvent'; import {EventPage} from '../pages/eventPage'; When(/^I am on the homepage$/, {}, async () => {

@@ -12,6 +13,11 @@ await EventPage.open();

global.SCENE.scene = EventPage; }); +When(/^I see the event edit page$/, {}, async () => { + await EditEvent.waitForDisplayed(); + global.SCENE.scene = EditEvent; +}); + When(/^I type (.+)$/, {}, async field => { await global.SCENE.scene.type(field); });

@@ -24,10 +30,16 @@ When(/^I submit the form$/, {}, async () => {

await global.SCENE.scene.submit(); }); -When(/^I write (.+) in (.+) field$/, {}, async (field, value) => { +When(/^I write (.+) in (.+) field$/, {}, async (value, field) => { await global.SCENE.scene.type(field, value); +}); +When(/^I pick (.+)$/, {}, async field => { + await global.SCENE.scene.pick(field); }); When(/^I go to the event detail page$/, async () => { await global.SCENE.scene.openTab('details'); }); +When(/^I go to the new car page$/, async () => { + await global.SCENE.scene.openTab('new car'); +});