Skip to content

Commit

Permalink
feat: add videos to e2e tests (#671)
Browse files Browse the repository at this point in the history
Add video generation to e2e tests
Enable headless mode for local run
Cleanup screenshots & videos before local execution
Increase timeouts for login and text check

---------

Co-authored-by: Hristo Iliev <[email protected]>
  • Loading branch information
hsiliev and Hristo Iliev authored Mar 4, 2024
1 parent 2356298 commit cf662ff
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 37 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ tasks {
delete("$rootDir/src/main/app/dist")
delete("$rootDir/src/main/app/reports")
delete("$rootDir/src/generated")
delete("$rootDir/src/e2e/reports")
}

build {
Expand Down
4 changes: 2 additions & 2 deletions src/e2e/features/1-authentication.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Feature: Login

Scenario: Bob wants to log out of the application after being logged in
Given "Bob" navigates to "zac" with path "/"
When "Bob" clicks on element with accessabillity label: "Gebruikers profiel"
When "Bob" clicks on element with accessibility label: "Gebruikers profiel"
When "Bob" clicks on element with text: "Uitloggen"
Then "Bob" sees the text: "Sign in to your account"

Expand All @@ -19,7 +19,7 @@ Feature: Login

Scenario: Bob wants to log out of the application after being logged in
Given "Bob" navigates to "zac" with path "/"
When "Bob" clicks on element with accessabillity label: "Gebruikers profiel"
When "Bob" clicks on element with accessibility label: "Gebruikers profiel"
When "Bob" clicks on element with text: "Uitloggen"
Then "Bob" sees the text: "Sign in to your account"

Expand Down
6 changes: 3 additions & 3 deletions src/e2e/features/5-external-systems.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ Feature: External Systems

Scenario: Employee wants to create a new document for a zaak
Given Employee "Oscar" is on the newly created zaak with status "Intake"
And "Oscar" clicks on Create Document for zaak
And "Oscar" closes the SmartDocuments tab
Then "Oscar" should not get an error
And Employee "Oscar" clicks on Create Document for zaak
And Employee "Oscar" closes the SmartDocuments tab
Then Employee "Oscar" should not get an error
18 changes: 9 additions & 9 deletions src/e2e/step-definitions/authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { When } from "@cucumber/cucumber";
import { CustomWorld, authFile } from "../support/worlds/world";
import { worldUsers } from "../utils/schemes";

const LOGIN_TIMEOUT_MS = 20000;

export async function login(world: CustomWorld, username: string, password: string) {
await world.page.getByLabel("Username or email").click();
Expand All @@ -16,24 +17,23 @@ export async function login(world: CustomWorld, username: string, password: stri
await world.page.getByRole("button", { name: "Sign In" }).click();
}

When("Employee {string} logs in to zac", async function (this: CustomWorld, user) {
async function loginToZac(this: CustomWorld, user: string) {
const parsedUser = worldUsers.parse(user)
const {username, password} = this.worldParameters.users[parsedUser]

await login(this, username, password);
});
}

When("Employee {string} logs out of zac", async function (this: CustomWorld, user) {
const parsedUser = worldUsers.parse(user)
When("Employee {string} logs in to zac", { timeout: LOGIN_TIMEOUT_MS }, async function (this: CustomWorld, user: string) {
await loginToZac.call(this, user);
});

When("Employee {string} logs out of zac", async function (this: CustomWorld, user: string) {
await this.page.getByText("account_circle").first().click();
await this.page.getByText("Uitloggen").first().click();
});

// @deprecated
When("{string} logs in", async function (this: CustomWorld, user) {
const parsedUser = worldUsers.parse(user)
const {username, password} = this.worldParameters.users[parsedUser]

await login(this, username, password);
When("{string} logs in", { timeout: LOGIN_TIMEOUT_MS }, async function (this: CustomWorld, user: string) {
await loginToZac.call(this, user);
});
18 changes: 10 additions & 8 deletions src/e2e/step-definitions/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,27 @@ import { CustomWorld } from "../support/worlds/world";
import { worldPossibleZacUrls, worldUsers } from "../utils/schemes";
import { login } from "./authentication";

When("Employee {string} opens zac", { timeout: 60 * 1000 }, async function (this: CustomWorld, user) {
const ONE_MINUTE_IN_MS = 60 * 1000;

When("Employee {string} opens zac", { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user) {
const expectedUrl = this.worldParameters.urls[worldPossibleZacUrls.Values.zac];
await this.openUrl(expectedUrl);
})

When("Employee {string} navigates to {string}", { timeout: 60 * 1000 }, async function (this: CustomWorld, user, path) {
When("Employee {string} navigates to {string}", { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user, path) {
const expectedUrl = this.worldParameters.urls[worldPossibleZacUrls.Values.zac] + path;

await this.openUrl(expectedUrl);
});

Given("{string} navigates to {string} with path {string}", { timeout: 60 * 1000 }, async function (this: CustomWorld, user, urlKey, path) {
Given("{string} navigates to {string} with path {string}", { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user, urlKey, path) {
const res = worldPossibleZacUrls.parse(urlKey);
const expectedUrl = this.worldParameters.urls[res] + path;

await this.openUrl(expectedUrl);
});

Given("{string} navigates to {string} with path {string} with delay after of {int} ms", { timeout: 60 * 1000 }, async function (this: CustomWorld, user, urlKey, path, delay) {
Given("{string} navigates to {string} with path {string} with delay after of {int} ms", { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user, urlKey, path, delay) {
const res = worldPossibleZacUrls.parse(urlKey);
const expectedUrl = this.worldParameters.urls[res] + path;

Expand All @@ -43,11 +45,11 @@ Given("{string} navigates to {string} with path {string} with delay after of {in
});


Then("{string} sees the text: {string}", async function (this: CustomWorld, user, text) {
await this.page.waitForSelector(`text=${text}`, {'timeout': 10000 });
Then("{string} sees the text: {string}", { timeout: 10000 }, async function (this: CustomWorld, user, text) {
await this.page.waitForSelector(`text=${text}`, { timeout: 10000 });
});

Then("{string} clicks on element with accessabillity label: {string}" , async function (this: CustomWorld, user, text) {
Then("{string} clicks on element with accessibility label: {string}" , async function (this: CustomWorld, user, text) {
await this.page.getByLabel(text).click()
})

Expand All @@ -57,4 +59,4 @@ Then("{string} clicks on element with id: {string}", async function (this: Custo

Then("{string} clicks on element with text: {string}", async function (this: CustomWorld, user, text) {
await this.page.getByText(text).click()
})
})
11 changes: 6 additions & 5 deletions src/e2e/step-definitions/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Before(async function (this: CustomWorld) {
})

After(async function (this: CustomWorld) {
fs.writeFileSync(authFile, JSON.stringify(await this.context.storageState()));
const storageState = await this.context.storageState();
fs.writeFileSync(authFile, JSON.stringify(storageState));
await this.stop();
})

Expand All @@ -18,22 +19,22 @@ AfterAll(async function (this: CustomWorld) {
if (err) {
throw err;
}

console.log("Deleted test storage file successfully.");
});
fs.unlink(authFile, (err) => {
if (err) {
throw err;
}

console.log("Deleted auth file successfully.");
});
return
})
})

AfterStep(async function (this: CustomWorld, { result }) {
if (result.status === Status.FAILED) {
const screenshot = await this.page.screenshot({ path: `./reports/screenshots/${uuidv4()}.png` });
this.attach(screenshot, "image/png");
}
})
})
6 changes: 3 additions & 3 deletions src/e2e/step-definitions/zaak.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,19 @@ Then("{string} sees the created zaak with a delay", { timeout: ONE_MINUTE_IN_MS
await this.page.getByText(caseNumber);
});

When('{string} clicks on Create Document for zaak', { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user) {
When('Employee {string} clicks on Create Document for zaak', { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user) {
await this.page.getByText('note_addDocument maken').click();

const smartDocumentsPage = await this.page.waitForEvent('popup');
await this.expect(smartDocumentsPage.getByRole('link', { name: 'SmartDocuments' })).toBeVisible();
})

Then('{string} closes the SmartDocuments tab', { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user) {
Then('Employee {string} closes the SmartDocuments tab', { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user) {
const allPages = this.page.context().pages();
await allPages[1].close();
});

Then('{string} should not get an error', { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user) {
Then('Employee {string} should not get an error', { timeout: ONE_MINUTE_IN_MS }, async function (this: CustomWorld, user) {
const caseNumber = this.testStorage.get('caseNumber');
await this.page.getByText(caseNumber);
});
Expand Down
1 change: 1 addition & 0 deletions src/e2e/support/worlds/world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class CustomWorld extends World {
this.context = await this.browser.newContext({
storageState: authFile,
locale: 'nl-NL',
recordVideo: { dir: 'reports/videos/' }
});
this.page = await this.context.newPage();
this.initialized = true;
Expand Down
18 changes: 11 additions & 7 deletions start-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@
# SPDX-License-Identifier: EUPL-1.2+
#

# Change Directory to your test directory
set -e

echo "Change Directory to e2e test directory .."
cd ./src/e2e
# Install dependencies
echo "Install dependencies ..."
npm ci

# Install Playwright Browsers
echo "Install Playwright Browsers ..."
npx playwright install --with-deps

# Define world-parameters JSON
world_params='{"urls": { "zac": "'$ZAC_URL'", "openForms": "'$OPEN_FORMS_URL'"}, "headless": false, "users": {"Bob": {"username": "'$E2E_TEST_USER_1_USERNAME'", "password": "'$E2E_TEST_USER_1_PASSWORD'"}, "Oscar": {"username": "'$E2E_TEST_USER_2_USERNAME'", "password": "'$E2E_TEST_USER_2_PASSWORD'"}}}'
echo "Cleanup screenshots ..."
rm -rf reports/*

# Run your Playwright tests
echo "Define world-parameters JSON ..."
world_params='{"urls": { "zac": "'$ZAC_URL'", "openForms": "'$OPEN_FORMS_URL'"}, "headless": '${HEADLESS:-false}', "users": {"Bob": {"username": "'$E2E_TEST_USER_1_USERNAME'", "password": "'$E2E_TEST_USER_1_PASSWORD'"}, "Oscar": {"username": "'$E2E_TEST_USER_2_USERNAME'", "password": "'$E2E_TEST_USER_2_PASSWORD'"}}}'

echo "Run your Playwright tests ..."
if [ "$EXCLUDE_LIVE_SCENARIO_TAGS" = "true" ]; then
npm run e2e:run -- --world-parameters "$world_params" --tags "not @live-env-only"
else
npm run e2e:run -- --world-parameters "$world_params"
fi
fi

0 comments on commit cf662ff

Please sign in to comment.