Skip to content

Commit

Permalink
test: lighthouse checks on e2e (AmadeusITGroup#1425)
Browse files Browse the repository at this point in the history
## Proposed change

The goal is to prevent regressions regarding accessibility on the
showcase app

![image](https://github.com/AmadeusITGroup/otter/assets/110407799/84430541-7e98-43c0-93cb-e2f6e69621ff)

## Related issues

- 🐛 Fixes #(issue)
- 🚀 Feature #(issue)

<!-- Please make sure to follow the contributing guidelines on
https://github.com/amadeus-digital/Otter/blob/main/CONTRIBUTING.md -->
  • Loading branch information
fpaul-1A authored Mar 6, 2024
2 parents 19b8889 + aebb78c commit a9e7643
Show file tree
Hide file tree
Showing 13 changed files with 600 additions and 100 deletions.
6 changes: 4 additions & 2 deletions apps/showcase/e2e-playwright/playwright-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ const config = defineConfig({
screenshot: 'only-on-failure',
trace: 'retain-on-failure',
...process.env.USE_MOCKS ? {
launchOptions: { proxy: {server: 'per-context'}},
launchOptions: { proxy: {server: 'per-context'}, args: ['--remote-debugging-port=9222']},
proxy: {server: 'http://localhost:4200'},
serviceWorkers: 'block',
ignoreHTTPSErrors: true
} : {}
} : {
launchOptions: { args: ['--remote-debugging-port=9222']}
}
},
expect: {
toHaveScreenshot: {
Expand Down
115 changes: 115 additions & 0 deletions apps/showcase/e2e-playwright/sanity/lighthouse-sanity.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { O3rElement } from '@o3r/testing/core';
import { type Page, test } from '@playwright/test';
import { AppFixtureComponent } from '../../src/app/app.fixture';

async function performAudit(name: string, page: Page) {
const { playAudit } = await import('playwright-lighthouse');
await playAudit({
page,
thresholds: {
performance: 50,
accessibility: 100,
// eslint-disable-next-line @typescript-eslint/naming-convention
'best-practices': 90
},
reports: {
formats: {
html: true
},
directory: 'playwright-reports/lighthouse',
name: name
},
port: 9222
});
}

const baseUrl = process.env.PLAYWRIGHT_TARGET_URL || 'http://localhost:4200/';

test.describe('Lighthouse tests', () => {
test('home', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
await performAudit('home', page);
await page.close();
});

test('run-app-locally', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToRunAppLocally();
await page.waitForURL('**/run-app-locally');
await performAudit('run-app-locally', page);
await page.close();
});

test('configuration', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToConfiguration();
await page.waitForURL('**/configuration');
await performAudit('configuration', page);
await page.close();
});

test('localization', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToLocalization();
await page.waitForURL('**/localization');
await performAudit('localization', page);
await page.close();
});

test('dynamic-content', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToDynamicContent();
await page.waitForURL('**/dynamic-content');
await performAudit('dynamic-content', page);
await page.close();
});

test('rules-engine', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToRulesEngine();
await page.waitForURL('**/rules-engine');
await performAudit('rules-engine', page);
await page.close();
});

test('component-replacement', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToComponentReplacement();
await page.waitForURL('**/component-replacement');
await performAudit('component-replacement', page);
await page.close();
});

test('design-token', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToDesignToken();
await page.waitForURL('**/design-token');
await performAudit('design-token', page);
await page.close();
});

test('sdk-generator', async ({context}) => {
const page = await context.newPage();
await page.goto(baseUrl);
const appFixture = new AppFixtureComponent(new O3rElement({element: page.locator('app-root'), page}));
await appFixture.navigateToSDKGenerator();
await page.waitForURL('**/sdk');
await performAudit('sdk-generator', page);
await page.close();
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions apps/showcase/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@
"jest-junit": "~16.0.0",
"jest-preset-angular": "~14.0.0",
"jsonc-eslint-parser": "~2.4.0",
"lighthouse": "9.6.8",
"playwright-lighthouse": "2.2.2",
"rimraf": "^5.0.1",
"ts-jest": "~29.1.1",
"typescript": "~5.3.3",
Expand Down
6 changes: 2 additions & 4 deletions apps/showcase/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,7 @@
"executor": "@o3r/design:generate-css",
"outputs": [
"{options.defaultStyleFile}",
"{options.metadataOutput}",
"{projectRoot}/src/**/*.scss"
"{options.metadataOutput}"
],
"inputs": [
"global",
Expand Down Expand Up @@ -242,8 +241,7 @@
"executor": "@o3r/design:generate-css",
"outputs": [
"{options.defaultStyleFile}",
"{options.metadataOutput}",
"{projectRoot}/src/**/*.scss"
"{options.metadataOutput}"
],
"inputs": [
"global",
Expand Down
85 changes: 37 additions & 48 deletions apps/showcase/src/app/rules-engine/rules-engine.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,65 +30,54 @@ <h2 id="rules-engine-example">Example</h2>
Do not hesitate to run the application locally, if not installed yet, follow the <a routerLink="/run-app-locally">instructions</a>.
</p>
<a href="https://github.com/AmadeusITGroup/otter/blob/main/apps/showcase/src/components/showcase/rules-engine" target="_blank" rel="noopener">Source code</a>
<ul ngbNav class="nav nav-tabs mt-3">
<ul ngbNav #nav="ngbNav" class="nav nav-tabs mt-3">
<li ngbNavItem class="nav-item" role="presentation">
<a ngbNavLink class="nav-link" [class.active]="activeRuleTab === 'configuration'" (click)="activateRuleTab('configuration')">Configuration rule</a>
</li>
<li ngbNavItem class="nav-item" role="presentation">
<a ngbNavLink class="nav-link" [class.active]="activeRuleTab === 'localization'" (click)="activateRuleTab('localization')">Localization rule</a>
</li>
<li ngbNavItem class="nav-item" role="presentation">
<a ngbNavLink class="nav-link" [class.active]="activeRuleTab === 'dynamic-content'" (click)="activateRuleTab('dynamic-content')">Dynamic content rule</a>
</li>
<li class="nav-item">
<a class="nav-link" [class.active]="activeRuleTab === 'operator-fact'" (click)="activateRuleTab('operator-fact')">Operator fact</a>
</li>
</ul>
<div class="p-3">
@switch (activeRuleTab) {
@case ('configuration') {
<div>
<p>
<ng-template ngbNavContent>
<p>
By default, New-York is not selectable and we want to make it available only during the summer.
<br>
So we have created facts for the trip information and a new operator to evaluate the selected date.
After that we set the following rule to make New-York available during the summer.
<br>
You can check that New-York will be available if you select dates during the summer (between June 21st and September 21st).
</p>
<o3r-copy-text-pres language="json" [text]="newYorkAvailableRule"></o3r-copy-text-pres>
</div>
}
@case ('dynamic-content') {
<div>
<p>
</p>
<o3r-copy-text-pres language="json" [text]="newYorkAvailableRule"></o3r-copy-text-pres>
</ng-template>
</li>
<li ngbNavItem class="nav-item" role="presentation">
<a ngbNavLink class="nav-link" [class.active]="activeRuleTab === 'localization'" (click)="activateRuleTab('localization')">Localization rule</a>
<ng-template ngbNavContent>
<p>
When a destination is selected, the text will change from "Where do you want to go?" to "When do you want to go?". We have created the following rule to change the localization key.
</p>
<o3r-copy-text-pres language="json" [text]="helloNewYorkRule"></o3r-copy-text-pres>
</ng-template>
</li>
<li ngbNavItem class="nav-item" role="presentation">
<a ngbNavLink class="nav-link" [class.active]="activeRuleTab === 'dynamic-content'" (click)="activateRuleTab('dynamic-content')">Dynamic content rule</a>
<ng-template ngbNavContent>
<p>
When selecting a date during the summer, the otter picture changes. We have created the following rule to change the targeted asset.
<br>
You can check that the image changes if you select dates during the summer (between June 21st and September 21st).
</p>
<o3r-copy-text-pres language="json" [text]="summerOtterRule"></o3r-copy-text-pres>
</div>
}
@case ('localization') {
<div>
<p>
When a destination is selected, the text will change from "Where do you want to go?" to "When do you want to go?". We have created the following rule to change the localization key.
</p>
<o3r-copy-text-pres language="json" [text]="helloNewYorkRule"></o3r-copy-text-pres>
</div>
}
@case ('operator-fact') {
<div>
<p>
When selecting a departure date in less than 2 days, the otter picture changes. We have created the following rule to change the targeted asset.
<br>
It is using the `inNextMinutes` operator which is based on the current time.
</p>
<o3r-copy-text-pres language="json" [text]="lateOtterRule"></o3r-copy-text-pres>
</div>
}
}
</div>
</p>
<o3r-copy-text-pres language="json" [text]="summerOtterRule"></o3r-copy-text-pres>
</ng-template>
</li>
<li ngbNavItem class="nav-item" role="presentation">
<a ngbNavLink class="nav-link" [class.active]="activeRuleTab === 'operator-fact'" (click)="activateRuleTab('operator-fact')">Operator fact</a>
<ng-template ngbNavContent>
<p>
When selecting a departure date in less than 2 days, the otter picture changes. We have created the following rule to change the targeted asset.
<br>
It is using the `inNextMinutes` operator which is based on the current time.
</p>
<o3r-copy-text-pres language="json" [text]="lateOtterRule"></o3r-copy-text-pres>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="nav"></div>
</div>
<h2 id="rules-engine-install">How to install</h2>
<div>
Expand Down
3 changes: 3 additions & 0 deletions apps/showcase/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ h1, h2 {
.hljs-built_in, .hljs-symbol {
color: #cb3544;
}
.hljs-doctag, .hljs-keyword, .hljs-meta .hljs-keyword, .hljs-template-tag, .hljs-template-variable, .hljs-type, .hljs-variable.language_ {
color: #cb3544;
}
.hljs-name, .hljs-quote, .hljs-selector-tag, .hljs-selector-pseudo {
color: #1f7e36;
}
Expand Down
11 changes: 7 additions & 4 deletions apps/showcase/update-screenshots.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
* Generate the screenshots for the E2E tests of the showcase app using a docker image running on ubuntu
* The goal is to make sure everybody generate the screenshots using the same platform to prevent mismatches
*/
const os = require('node:os');
const childProcess = require('node:child_process');
const playwrightVersion = require('@playwright/test/package.json').version;
const childProcess = require('node:child_process');
const os = require('node:os');
const path = require('node:path');

const relativeRoot = path.relative(process.cwd(), path.resolve(__dirname, '..', '..')) || '.';

// We should be able to use `host.docker.internal` but it seems to fail depending on the network configuration
const ipAddresses = [
Expand Down Expand Up @@ -42,14 +45,14 @@ const containerScript = [
'yarn install --mode=skip-build',

// Run the tests
'yarn test-e2e -u',
'yarn workspace @o3r/showcase run test:playwright:sanity -g \\"Visual comparison\\" -u',

// Copy the newly generated screenshots outside the container
'cp -r apps/showcase/e2e-playwright/sanity/screenshots ../tests/apps/showcase/e2e-playwright/sanity'
].join(' && ');

// Command to create the docker container and run the script
const script = `docker run -it --rm --ipc=host -v "../../":/tests mcr.microsoft.com/playwright:v${playwrightVersion}-jammy /bin/bash -c "${containerScript}"`;
const script = `docker run -it --rm --ipc=host -v "${relativeRoot}/":/tests mcr.microsoft.com/playwright:v${playwrightVersion}-jammy /bin/bash -c "${containerScript}"`;

// Execute the script
childProcess.execSync(script, {stdio: 'inherit'});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,14 @@
"js-yaml": "^4.1.0",
"jsonc-eslint-parser": "~2.4.0",
"jsonpath-plus": "^8.0.0",
"lighthouse": "9.6.8",
"lint-staged": "^15.0.0",
"minimist": "^1.2.6",
"ng-packagr": "~17.2.0",
"ngx-highlightjs": "^10.0.0",
"npm-run-all2": "^6.0.0",
"nx": "~18.0.2",
"playwright-lighthouse": "2.2.2",
"postcss": "~8.4.31",
"postcss-scss": "~4.0.9",
"react": "^18.0.0",
Expand Down
Loading

0 comments on commit a9e7643

Please sign in to comment.