Skip to content

Commit

Permalink
feat: e2e coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
quentinderoubaix committed Jul 28, 2023
1 parent 4d77a19 commit 9e5d633
Show file tree
Hide file tree
Showing 29 changed files with 1,323 additions and 533 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ jobs:
- run: npm run build:ci
- run: npm run format:check
- run: npm run lint
- run: npx playwright install --with-deps
- run: npm run test
- run: npm run e2e
- run: npm run test:coverage
- uses: codecov/codecov-action@v3
with:
file: core/coverage/lcov.info
flags: unit
- if: inputs.docPublish
uses: actions/checkout@v3
with:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ on:
jobs:
build:
uses: './.github/workflows/build.yml'
e2e-tests:
uses: './.github/workflows/e2e-tests.yml'
25 changes: 25 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: e2e-tests
on:
workflow_call:
jobs:
e2e-tests:
runs-on: ubuntu-latest
name: Test (${{ matrix.shard }}/${{ strategy.job-total}})
strategy:
matrix:
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18.x'
cache: 'npm'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run build:coverage
- run: npm run e2e -- --shard=${{ matrix.shard }}/${{ strategy.job-total}}
- uses: codecov/codecov-action@v3
with:
file: e2e/coverage/lcov.info
flags: e2e-${{ matrix.shard }}
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ on:
description: Version number (x.y.z)

jobs:
e2e-tests:
uses: './.github/workflows/e2e-tests.yml'
build:
needs: e2e-tests
uses: './.github/workflows/build.yml'
with:
version: ${{ inputs.version }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ playwright-report/
test-results/
.svelte-kit/
dist.tar.gz
.nyc_output/
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ node_modules
dist
.angular
coverage/
.nyc_output/
playwright-report/
test-results/
.svelte-kit/
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# AgnosUI: A Versatile Frontend Widget Library for CSS Bootstrap Design

[![Build Status](https://github.com/AmadeusITGroup/AgnosUI/workflows/ci/badge.svg?branch=main)](https://github.com/AmadeusITGroup/AgnosUI/actions)
[![codecov](https://codecov.io/gh/AmadeusITGroup/AgnosUI/branch/main/graph/badge.svg)](https://codecov.io/gh/AmadeusITGroup/AgnosUI)

## Introduction

AgnosUI is a powerful library of widgets designed specifically for the [CSS Bootstrap design](https://getbootstrap.com/). Inspired by the success of [ng-bootstrap](https://ng-bootstrap.github.io/#/home), AgnosUI takes the concept a step further by offering widgets that can seamlessly integrate with any front-end framework of your choice. With support for popular frameworks like [Angular](https://angular.io/), [React](https://react.dev/), and [Svelte](https://svelte.dev/), AgnosUI allows you to effortlessly create consistent and visually appealing UI components across your projects.
Expand Down
13 changes: 11 additions & 2 deletions angular/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"builder": "ngx-build-plus:browser",
"options": {
"outputPath": "dist/demo",
"index": "demo/src/index.html",
Expand Down Expand Up @@ -55,12 +55,16 @@
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
},
"coverage": {
"sourceMap": true,
"extraWebpackConfig": "./demo/coverage.webpack.js"
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"builder": "ngx-build-plus:dev-server",
"configurations": {
"production": {
"servePath": "/angular/samples",
Expand All @@ -69,6 +73,11 @@
"development": {
"servePath": "/angular/samples",
"browserTarget": "demo:build:development"
},
"coverage": {
"servePath": "/angular/samples",
"browserTarget": "demo:build:coverage",
"extraWebpackConfig": "./demo/coverage.webpack.js"
}
},
"defaultConfiguration": "development"
Expand Down
15 changes: 15 additions & 0 deletions angular/demo/coverage.webpack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
module: {
rules: [
{
test: /\.(js|ts)$/,
loader: 'coverage-istanbul-loader',
options: {esModules: true},
enforce: 'post',
// eslint-disable-next-line @typescript-eslint/no-var-requires
include: [require('path').join(__dirname, '..', 'lib', 'src'), require('path').join(__dirname, '..', '..', 'core')],
exclude: [/\.(e2e|spec|po)\.ts$/, /node_modules/, /(ngfactory|ngstyle)\.js/],
},
],
},
};
4 changes: 4 additions & 0 deletions angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
"scripts": {
"ng": "ng",
"dev": "ng serve",
"dev:coverage": "ng serve --configuration coverage",
"build": "npm run build:lib && npm run build:demo",
"build:lib": "ng build lib",
"build:demo": "ng build demo",
"build:copy": "node ../demo/scripts/copy.mjs angular",
"build:coverage": "ng build demo --configuration coverage",
"watch": "ng build --watch --configuration development",
"preview": "node ./scripts/preview.cjs dist/demo --port 4200 --single",
"tdd": "npm run test:lib --watch",
Expand Down Expand Up @@ -37,13 +39,15 @@
"@angular/compiler-cli": "^16.1.3",
"@types/jasmine": "^4.3.5",
"@types/webpack-env": "^1.18.1",
"coverage-istanbul-loader": "^3.0.5",
"jasmine-core": "^5.0.1",
"karma": "^6.4.2",
"karma-chrome-launcher": "^3.2.0",
"karma-coverage": "^2.2.1",
"karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^2.1.0",
"ng-packagr": "^16.1.0",
"ngx-build-plus": "^16.0.0",
"raw-loader": "^4.0.2",
"sirv-cli": "^2.0.2",
"typescript": "~5.1.6"
Expand Down
2 changes: 1 addition & 1 deletion core/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export default defineConfig({
test: {
include: ['./**/*.spec.ts'],
coverage: {
provider: 'istanbul',
reporter: ['text', 'json', 'html', 'lcov'],
src: ['.'],
exclude: ['**/*.spec.ts', '**/__mocks__/**'],
},
environment: 'happy-dom',
Expand Down
1 change: 1 addition & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"scripts": {
"dev": "vite dev -c vite.config.ts",
"build": "npm run build:demo && npm run svelte-check",
"build:coverage": "npm run build",
"build:demo": "vite build -c vite.config.ts",
"preview": "vite preview -c vite.config.ts",
"svelte-check": "svelte-check"
Expand Down
3 changes: 2 additions & 1 deletion e2e/alert/alert.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {AlertPO} from '@agnos-ui/page-objects';
import {expect, test} from '@playwright/test';
import {expect, getTest} from '../fixture';
import {AlertDemoPO} from '../demo-po/alert.po';

const test = getTest();
test.describe(`Alert tests`, () => {
test(`Config alert`, async ({page}) => {
const alertDemoPO = new AlertDemoPO(page);
Expand Down
20 changes: 20 additions & 0 deletions e2e/fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type {Page} from '@playwright/test';
import {test as base} from '@playwright/test';
import {promises as fs} from 'fs';
import path from 'path';
import {v4 as uuidv4} from 'uuid';

async function afterEach({page}: {page: Page}) {
const coverage: string = await page.evaluate(() => {
return JSON.stringify((window as any).__coverage__);
});
if (coverage) {
await fs.writeFile(path.join(__dirname, '.nyc_output', `${uuidv4()}.json`), coverage);
}
}
export {expect} from '@playwright/test';
export function getTest() {
const test = base.extend({});
test.afterEach(afterEach);
return test;
}
3 changes: 2 additions & 1 deletion e2e/focustrack/focustrack.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {test, expect} from '@playwright/test';
import {expect, getTest} from '../fixture';
import {FocusTrackPO} from '../demo-po/focustrack.po';

type PromiseValue<T> = T extends Promise<infer U> ? U : never;
type State = PromiseValue<ReturnType<FocusTrackPO['getState']>>;

const test = getTest();
test.describe(`Select tests`, () => {
test.beforeEach(async ({page}) => {
await page.goto('#/focustrack/focustrack');
Expand Down
28 changes: 28 additions & 0 deletions e2e/global-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import NYC from 'nyc';
import {promises as fs} from 'fs';
import {rm} from 'fs/promises';
import path from 'path';

async function globalSetup() {
console.log('Cleaning up coverage folders...');
const nycDir = path.join('e2e', '.nyc_output');
const reportDir = path.join('e2e', 'coverage');
await rm(nycDir, {recursive: true, force: true});
await fs.mkdir(nycDir);
await rm(reportDir, {recursive: true, force: true});
await fs.mkdir(reportDir);
console.log('Coverage setup ready !');
const nycInstance = new NYC({
cwd: __dirname,
['report-dir']: reportDir,
reporter: ['lcov', 'json', 'text-summary'],
extension: ['.ts', '.tsx', '.svelte'],
});
return async () => {
console.log('Saving coverage report...');
await nycInstance.report();
console.log('Coverage report saved !');
};
}

export default globalSetup;
53 changes: 34 additions & 19 deletions e2e/modal/modal.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
import {expect, test} from '@playwright/test';
import {expect, getTest} from '../fixture';
import {ModalDefaultDemoModalPO, ModalDemoPO, ModalStackDemoModalPO} from '../demo-po/modal.po';

const test = getTest();
test.describe.parallel(`Modal tests`, () => {
test(`Default modal`, async ({page}) => {
const modalDemoPO = new ModalDemoPO(page);
const modalPO = new ModalDefaultDemoModalPO(page, 0);
await page.goto('#/modal/default');
await modalDemoPO.locatorRoot.waitFor();
await modalDemoPO.locatorLaunchDemoModalButton().click();
expect(modalPO.locatorTitle()).toContainText('Save changes');
expect(modalPO.locatorBody()).toContainText('Do you want to save your changes?');
await modalPO.locatorCloseButton().click();
await modalPO.locatorRoot.waitFor({state: 'hidden'});
await expect(modalDemoPO.locatorMessage()).toContainText('You clicked on the close button');
await modalDemoPO.locatorLaunchDemoModalButton().click();
expect(modalPO.locatorTitle()).toContainText('Save changes');
expect(modalPO.locatorBody()).toContainText('Do you want to save your changes?');
await modalPO.locatorYesButton().click();
await modalPO.locatorRoot.waitFor({state: 'hidden'});
await expect(modalDemoPO.locatorMessage()).toContainText('You answered the question with "Yes"');
await modalDemoPO.locatorLaunchDemoModalButton().click();
expect(modalPO.locatorTitle()).toContainText('Save changes');
expect(modalPO.locatorBody()).toContainText('Do you want to save your changes?');
await modalPO.locatorNoButton().click();
await modalPO.locatorRoot.waitFor({state: 'hidden'});
await expect(modalDemoPO.locatorMessage()).toContainText('You answered the question with "No"');
await test.step('open modal and click on close', async () => {
await modalDemoPO.locatorLaunchDemoModalButton().click();
expect(modalPO.locatorTitle()).toContainText('Save changes');
expect(modalPO.locatorBody()).toContainText('Do you want to save your changes?');
await modalPO.locatorCloseButton().click();
await modalPO.locatorRoot.waitFor({state: 'hidden'});
await expect(modalDemoPO.locatorMessage()).toContainText('You clicked on the close button');
});
await test.step('open modal and click on yes', async () => {
await modalDemoPO.locatorLaunchDemoModalButton().click();
expect(modalPO.locatorTitle()).toContainText('Save changes');
expect(modalPO.locatorBody()).toContainText('Do you want to save your changes?');
await modalPO.locatorYesButton().click();
await modalPO.locatorRoot.waitFor({state: 'hidden'});
await expect(modalDemoPO.locatorMessage()).toContainText('You answered the question with "Yes"');
});
await test.step('open modal and click on no', async () => {
await modalDemoPO.locatorLaunchDemoModalButton().click();
expect(modalPO.locatorTitle()).toContainText('Save changes');
expect(modalPO.locatorBody()).toContainText('Do you want to save your changes?');
await modalPO.locatorNoButton().click();
await modalPO.locatorRoot.waitFor({state: 'hidden'});
await expect(modalDemoPO.locatorMessage()).toContainText('You answered the question with "No"');
});
await test.step('open modal and click on backdrop', async () => {
await modalDemoPO.locatorLaunchDemoModalButton().click();
expect(modalPO.locatorTitle()).toContainText('Save changes');
expect(modalPO.locatorBody()).toContainText('Do you want to save your changes?');
await modalPO.locatorRoot.click();
await modalPO.locatorRoot.waitFor({state: 'hidden'});
await expect(modalDemoPO.locatorMessage()).toContainText('You clicked outside the modal');
});
});

test(`Modal stack`, async ({page}) => {
Expand Down
3 changes: 2 additions & 1 deletion e2e/pagination/pagination.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {expect, test} from '@playwright/test';
import {expect, getTest} from '../fixture';
import {PaginationPO} from '@agnos-ui/page-objects';
import {PaginationDemoPO} from '../demo-po/pagination.po';

const test = getTest();
async function paginationState(paginationPO: PaginationPO) {
return paginationPO.locatorRoot.evaluate((rootNode: HTMLElement) => {
const pagesElements = [...rootNode.querySelectorAll('.au-page')] as HTMLLinkElement[];
Expand Down
Loading

0 comments on commit 9e5d633

Please sign in to comment.