Skip to content

Commit

Permalink
test(devtools): add e2e tests for devtools
Browse files Browse the repository at this point in the history
  • Loading branch information
rainerhahnekamp authored Jan 5, 2025
1 parent 6759f9d commit 76665f3
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 37 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
- run: pnpm install --frozen-lockfile
- run: pnpm run lint:all
- run: pnpm run test:all
- run: pnpm run test:e2e
- run: pnpm run build:all
- run: ./integration-tests.sh

62 changes: 62 additions & 0 deletions apps/demo/e2e/devtools.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { test, expect } from '@playwright/test';
import { Action } from '@ngrx/store';

test('has title', async ({ page }) => {
await page.goto('');

await page.evaluate(() => {
window['devtoolsSpy'] = [];

window['__REDUX_DEVTOOLS_EXTENSION__'] = {
connect: () => {
return {
send: (data: Action) => {
window['devtoolsSpy'].push(data);
},
};
},
};
});
await page.getByRole('link', { name: 'DevTools' }).click();
await page
.getByRole('row', { name: 'Go for a walk' })
.getByRole('checkbox')
.click();
await page
.getByRole('row', { name: 'Exercise' })
.getByRole('checkbox')
.click();

await expect(
page.getByRole('region', { name: 'Go for a walk' })
).toBeVisible();
await expect(page.getByRole('region', { name: 'Exercise' })).toBeVisible();

await page
.getByRole('row', { name: 'Go for a walk' })
.getByRole('checkbox')
.click();
await page
.getByRole('row', { name: 'Exercise' })
.getByRole('checkbox')
.click();

await expect(
page.getByRole('region', { name: 'Go for a walk' })
).toBeHidden();
await expect(page.getByRole('region', { name: 'Exercise' })).toBeHidden();

const devtoolsActions = await page.evaluate(() => window['devtoolsSpy']);

expect(devtoolsActions).toEqual([
{ type: 'add todo' },
{ type: 'select todo 1' },
{ type: 'Store Update' },
{ type: 'select todo 4' },
{ type: 'Store Update' },
{ type: 'select todo 1' },
{ type: 'Store Update' },
{ type: 'select todo 4' },
{ type: 'Store Update' },
]);
});
10 changes: 9 additions & 1 deletion apps/demo/eslint.config.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
const playwright = require('eslint-plugin-playwright');
const nx = require('@nx/eslint-plugin');
const baseConfig = require('../../eslint.config.cjs');

module.exports = [
playwright.configs['flat/recommended'],

...baseConfig,
...nx.configs['flat/angular'],
...nx.configs['flat/angular-template'],
Expand All @@ -25,5 +28,10 @@ module.exports = [
},
],
},
}
},
{
files: ['**/*.ts', '**/*.js'],
// Override or add rules here
rules: {},
},
];
2 changes: 1 addition & 1 deletion apps/demo/jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

export default {
displayName: 'demo',
preset: '../../jest.preset.js',
Expand All @@ -13,6 +12,7 @@ export default {
},
],
},
testPathIgnorePatterns: ['e2e'],
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
Expand Down
35 changes: 35 additions & 0 deletions apps/demo/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { defineConfig, devices } from '@playwright/test';
import * as path from 'node:path';

// For CI, you may want to set BASE_URL to the deployed application.
const baseURL = process.env['BASE_URL'] || 'http://localhost:4200';

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
use: {
baseURL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Run your local dev server before starting the tests */
webServer: {
command: 'pnpm start',
url: 'http://localhost:4200',
reuseExistingServer: true,
cwd: path.join(__dirname, '../..'),
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
28 changes: 12 additions & 16 deletions apps/demo/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,14 @@
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": [
"{options.outputPath}"
],
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/demo",
"index": "apps/demo/src/index.html",
"browser": "apps/demo/src/main.ts",
"polyfills": [
"zone.js"
],
"polyfills": ["zone.js"],
"tsConfig": "apps/demo/tsconfig.app.json",
"assets": [
"apps/demo/src/favicon.ico",
"apps/demo/src/assets"
],
"assets": ["apps/demo/src/favicon.ico", "apps/demo/src/assets"],
"styles": [
"@angular/material/prebuilt-themes/deeppurple-amber.css",
"apps/demo/src/styles.css"
Expand Down Expand Up @@ -73,18 +66,21 @@
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
"outputs": ["{options.outputFile}"]
},
"test": {
"executor": "@nx/jest:jest",
"outputs": [
"{workspaceRoot}/coverage/{projectRoot}"
],
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/demo/jest.config.ts"
}
},
"e2e": {
"executor": "@nx/playwright:playwright",
"outputs": ["{workspaceRoot}/dist/.playwright/apps/demo"],
"options": {
"config": "apps/demo/playwright.config.ts"
}
}
}
}
23 changes: 11 additions & 12 deletions apps/demo/src/app/devtools/todo-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ const TodoDetailStore = signalStore(

@Component({
selector: 'demo-todo-detail',
template: ` <mat-card>
<mat-card-title>{{ todo().name }}</mat-card-title>
<mat-card-content>
<textarea>{{ todo().description }}</textarea>
</mat-card-content>
</mat-card>`,
template: ` <section [attr.aria-label]="todo().name">
<mat-card>
<mat-card-title>{{ todo().name }}</mat-card-title>
<mat-card-content>
<textarea>{{ todo().description }}</textarea>
</mat-card-content>
</mat-card>
</section>`,
imports: [MatCardModule],
providers: [TodoDetailStore],
styles: `
Expand All @@ -42,11 +44,8 @@ export class TodoDetailComponent {
todo = input.required<Todo>();

constructor() {
effect(
() => {
renameDevtoolsName(this.#todoDetailStore, `todo-${this.todo().id}`);
},
{ allowSignalWrites: true }
);
effect(() => {
renameDevtoolsName(this.#todoDetailStore, `todo-${this.todo().id}`);
});
}
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"start": "nx serve demo",
"lint:all": "nx run-many --targets=lint",
"test:all": "nx run-many --targets=test",
"test:e2e": "nx e2e demo",
"build:all": "nx run-many --targets=build",
"verify:all": "nx run-many --targets=lint,test,build"
},
Expand Down Expand Up @@ -63,7 +64,7 @@
"autoprefixer": "^10.4.19",
"eslint": "^9.8.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-playwright": "^0.15.3",
"eslint-plugin-playwright": "^1.6.2",
"eslint-plugin-unused-imports": "^4.1.4",
"husky": "^9.0.11",
"jest": "^29.7.0",
Expand Down
14 changes: 8 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 76665f3

Please sign in to comment.