Skip to content

Commit 1311cab

Browse files
Merge pull request #279 from wttech/pw-screenshots
Playwright screenshots
2 parents 24231d1 + 6ce3f15 commit 1311cab

File tree

12 files changed

+152
-72
lines changed

12 files changed

+152
-72
lines changed

Taskfile.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,12 +327,25 @@ tasks:
327327
328328
test:e2e:
329329
dir: test/e2e
330-
desc: Test tool using end-to-end tests using Playwright
330+
desc: Test tool using end-to-end tests
331331
cmd: |
332332
set -e
333333
sh nw npm install
334334
sh nw npx playwright {{.CLI_ARGS | default "test"}}
335335
336+
test:e2e:codegen:
337+
dir: test/e2e
338+
desc: Generate end-to-end test code from recording
339+
cmd: |
340+
sh nw npm install
341+
sh nw npx playwright codegen --target=ts {{.AEM_AUTHOR_HTTP_URL}}
342+
343+
test:e2e:report:
344+
dir: test/e2e
345+
desc: Show end-to-end test report
346+
cmd: |
347+
sh nw npx playwright show-report
348+
336349
rde:setup:
337350
desc: setup access to RDE
338351
cmds:

core/src/main/java/dev/vml/es/acm/core/script/ScriptScheduler.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ public void onEvent(Event event) {
177177

178178
public void bootOnDemand() {
179179
LOG.info("Automatic scripts booting on demand - job scheduling");
180+
bootedScripts.clear();
180181
unscheduleBoot();
181182
scheduleBoot();
182183
LOG.info("Automatic scripts booting on demand - job scheduled");
@@ -319,8 +320,10 @@ private void queueBootScript(Script script, ResourceResolver resourceResolver) {
319320
bootedScripts.put(script.getId(), checksum);
320321
LOG.info("Boot script '{}' queued", script.getId());
321322
} else {
322-
LOG.info("Boot script '{}' not eligible for queueing!", script.getId());
323+
LOG.info("Boot script '{}' not queued - check failed", script.getId());
323324
}
325+
} else {
326+
LOG.info("Boot script '{}' not queued - checksum unchanged", script.getId());
324327
}
325328
}
326329

test/e2e/001-general.spec.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,44 @@
11
import { test, expect } from '@playwright/test';
22
import { expectCodeExecutorStatus, expectHealthyStatus } from './utils/expect';
3+
import { testOnEnv, apiHeaders } from './utils/env';
4+
import { attachScreenshot } from './utils/page';
35

46
test.describe('General', () => {
5-
test('Tool is accessible', async ({ page }) => {
7+
test('Tool is accessible', async ({ page }, testInfo) => {
68
await page.goto('/acm');
79

810
const title = page.locator('.granite-title', { hasText: 'Content Manager' });
911
await expect(title).toBeVisible();
12+
13+
await attachScreenshot(page, testInfo, 'Dashboard Page');
14+
});
15+
16+
testOnEnv('local')('Tool state is reset', async ({ page }) => {
17+
const clearResponse = await page.request.post('/apps/acm/api/event.json?name=HISTORY_CLEAR', { headers: await apiHeaders(page) });
18+
expect(clearResponse.ok()).toBeTruthy();
19+
const clearJson = await clearResponse.json();
20+
expect(clearJson).toEqual({ status: 200, message: "Event 'HISTORY_CLEAR' dispatched successfully!", data: null });
21+
await page.waitForTimeout(3000);
22+
23+
const bootResponse = await page.request.post('/apps/acm/api/event.json?name=SCRIPT_SCHEDULER_BOOT', { headers: await apiHeaders(page) });
24+
expect(bootResponse.ok()).toBeTruthy();
25+
const bootJson = await bootResponse.json();
26+
expect(bootJson).toEqual({ status: 200, message: "Event 'SCRIPT_SCHEDULER_BOOT' dispatched successfully!", data: null });
27+
await page.waitForTimeout(10000);
1028
});
1129

12-
test('System is healthy', async ({ page }) => {
30+
test('System is healthy', async ({ page }, testInfo) => {
1331
await page.goto('/acm#/maintenance?tab=health-checker');
1432

1533
await expectHealthyStatus(page);
34+
await attachScreenshot(page, testInfo, 'Health Checker');
1635
});
1736

18-
test('Code executor is idle', async ({ page }) => {
37+
test('Code executor is idle', async ({ page }, testInfo) => {
1938
await page.goto('/acm#/maintenance?tab=code-executor');
2039

2140
await expectCodeExecutorStatus(page);
41+
await attachScreenshot(page, testInfo, 'Code Executor');
2242
});
2343

2444
});

test/e2e/002-console.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { test, expect } from '@playwright/test';
22
import { expectCompilationSucceeded, expectExecutionProgressBarSucceeded, expectToHaveMultilineText } from './utils/expect'
33
import { readFromCodeEditor, writeToCodeEditor } from './utils/editor';
4+
import { attachScreenshot } from './utils/page';
45

56
test.describe('Console', () => {
6-
test('Executes script', async ({ page }) => {
7+
test('Executes script', async ({ page }, testInfo) => {
78
await page.goto('/acm#/console');
89

910
await expectCompilationSucceeded(page);
@@ -22,13 +23,14 @@ test.describe('Console', () => {
2223
await expect(page.getByRole('button', { name: 'Execute' })).toBeEnabled();
2324
await page.getByRole('button', { name: 'Execute' }).click();
2425

25-
await page.getByRole('tab', { name: 'Output' }).click();
26+
await expect(page.getByRole('tab', { name: 'Output' })).toHaveAttribute('aria-selected', 'true');
2627
await expectExecutionProgressBarSucceeded(page);
2728

2829
const output = await readFromCodeEditor(page, 'Console Output');
2930
expectToHaveMultilineText(output, `
3031
Hello World!
3132
`);
33+
await attachScreenshot(page, testInfo, 'Console Output');
3234
});
3335
});
3436

test/e2e/003-tool-access.spec.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { test, expect } from '@playwright/test';
22
import { expectCompilationSucceeded, expectExecutionProgressBarSucceeded } from './utils/expect';
33
import { readFromCodeEditor, writeToCodeEditor } from './utils/editor';
44
import { newAemContext } from './utils/context';
5+
import { attachScreenshot } from './utils/page';
56

67
test.describe('Tool Access', () => {
7-
test('Admin user has full access', async ({ page }) => {
8+
test('Admin user has full access', async ({ page }, testInfo) => {
89
await page.goto('/acm');
910

1011
await expect(page.getByRole('button', { name: 'Console' })).toBeVisible();
@@ -18,9 +19,11 @@ test.describe('Tool Access', () => {
1819
await page.goto('/acm#/console');
1920
await expectCompilationSucceeded(page);
2021
await expect(page.getByRole('button', { name: 'Execute' })).toBeEnabled();
22+
23+
await attachScreenshot(page, testInfo, 'Admin Full Access');
2124
});
2225

23-
test('Setup test user and verify limited access', async ({ page, browser }) => {
26+
test('Setup test user and verify limited access', async ({ page, browser }, testInfo) => {
2427
await page.goto('/acm#/console');
2528

2629
await expectCompilationSucceeded(page);
@@ -59,8 +62,7 @@ test.describe('Tool Access', () => {
5962

6063
await expect(page.getByRole('button', { name: 'Execute' })).toBeEnabled();
6164
await page.getByRole('button', { name: 'Execute' }).click();
62-
63-
await page.getByRole('tab', { name: 'Output' }).click();
65+
await expect(page.getByRole('tab', { name: 'Output' })).toHaveAttribute('aria-selected', 'true');
6466
await expectExecutionProgressBarSucceeded(page);
6567

6668
const output = await readFromCodeEditor(page, 'Console Output');
@@ -77,6 +79,8 @@ test.describe('Tool Access', () => {
7779
await expect(testUserPage.getByRole('button', { name: 'Snippets' })).not.toBeVisible();
7880
await expect(testUserPage.getByRole('button', { name: 'History' })).not.toBeVisible();
7981
await expect(testUserPage.getByRole('button', { name: 'Maintenance' })).not.toBeVisible();
82+
83+
await attachScreenshot(testUserPage, testInfo, 'Test User Access - Dashboard');
8084

8185
await testUserPage.getByRole('button', { name: 'Scripts' }).click();
8286
await expect(testUserPage).toHaveURL(/\/acm#\/scripts/);
@@ -90,6 +94,9 @@ test.describe('Tool Access', () => {
9094
const scriptRow = rows.nth(1);
9195
await expect(scriptRow.locator('[role="rowheader"]')).toContainText('example/ACME-200_hello-world');
9296

97+
await attachScreenshot(testUserPage, testInfo, 'Test User Access - Script List');
98+
99+
// Check if routing blocks access to other tools
93100
await testUserPage.goto('/acm#/console');
94101
await expect(testUserPage.getByRole('button', { name: 'Console' })).not.toBeVisible();
95102

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { test, expect } from '@playwright/test';
2+
import { attachScreenshot } from './utils/page';
3+
4+
test.describe('Automatic Scripts', () => {
5+
6+
test('Executions saved in history', async ({ page }, testInfo) => {
7+
await page.goto('/acm');
8+
await page.getByRole('button', { name: 'History' }).click();
9+
10+
const grid = page.locator('[role="grid"][aria-label="Executions table"]');
11+
await expect(grid).toBeVisible();
12+
const rows = grid.locator('[role="row"]');
13+
14+
await page.getByRole('searchbox', { name: 'Executable' }).fill('example/ACME-20_once');
15+
await expect(rows.nth(1)).toContainText('Script \'example/ACME-20_once\'');
16+
await expect(rows.nth(1)).toContainText('succeeded');
17+
await attachScreenshot(page, testInfo, `Script List filtered by 'ACME-20_once'`);
18+
19+
await page.getByRole('searchbox', { name: 'Executable' }).fill('example/ACME-21_changed');
20+
await expect(rows.nth(1)).toContainText('Script \'example/ACME-21_changed\'');
21+
await expect(rows.nth(1)).toContainText('succeeded');
22+
await attachScreenshot(page, testInfo, `Script List filtered by 'ACME-21_changed'`);
23+
});
24+
});

test/e2e/004-history.spec.ts

Lines changed: 0 additions & 50 deletions
This file was deleted.

test/e2e/005-manual-scripts.spec.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,38 @@ import {
99
expectOutputFileDownload,
1010
} from './utils/expect';
1111
import { readFromCodeEditor } from './utils/editor';
12+
import { attachScreenshot } from './utils/page';
1213

1314
test.describe('Manual Scripts', () => {
14-
test('Execute CSV Generation With I/O', async ({ page }) => {
15+
test('Execute CSV Generation', async ({ page }, testInfo) => {
1516
await page.goto('/acm');
1617
await page.getByRole('button', { name: 'Scripts' }).click();
18+
await expect(page.locator('[role="grid"][aria-label="Script list (manual)"]')).toBeVisible();
19+
1720
await page.getByText('example/ACME-203_output-csv').click();
21+
await expect(page).toHaveURL(/\/acm#\/scripts\/view\/%2Fconf%2Facm%2Fsettings%2Fscript%2Fmanual%2Fexample%2FACME-203_output-csv\.groovy/);
22+
await page.waitForTimeout(1000);
23+
await attachScreenshot(page, testInfo, 'Script Details');
24+
1825
await page.getByRole('button', { name: 'Execute' }).click();
1926

2027
await page.getByRole('textbox', { name: 'Users to' }).fill('5000');
2128
await page.getByRole('textbox', { name: 'First names' }).fill('John\nJane\nJack\nAlice\nBob\nRobert');
2229
await page.getByRole('textbox', { name: 'Last names' }).fill('Doe\nSmith\nBrown\nJohnson\nWhite\nJordan');
2330

31+
// TODO await attachScreenshot(page, testInfo, 'Inputs Dialog');
32+
2433
await page.getByRole('button', { name: 'Start' }).click();
2534
await expectExecutionProgressBarSucceeded(page);
2635

2736
const output = await readFromCodeEditor(page, 'Execution Output');
2837
expect(output).toContain('[SUCCESS] Users CSV report generation ended successfully');
38+
await attachScreenshot(page, testInfo, 'Execution Console Output');
2939

3040
await page.getByRole('tab', { name: 'Details' }).click();
3141

3242
await page.waitForTimeout(1000);
33-
await page.screenshot();
43+
await attachScreenshot(page, testInfo, 'Execution Details');
3444

3545
await expectExecutionDetails(page);
3646
await expectExecutionTimings(page);
@@ -56,14 +66,16 @@ test.describe('Manual Scripts', () => {
5666
]);
5767

5868
await page.getByRole('tab', { name: 'Output' }).click();
59-
6069
await page.getByRole('button', { name: 'Review' }).click();
70+
6171
await page.getByRole('tab', { name: 'Texts' }).click();
6272
await expectOutputTexts(page, ['Processed 5000 user(s)']);
73+
// TODO await attachScreenshot(page, testInfo, 'Outputs Review - Texts');
6374
await page.getByTestId('modal').getByRole('button', { name: 'Close' }).click();
6475

6576
await page.getByRole('button', { name: 'Review' }).click();
6677
await page.getByRole('tab', { name: 'Files' }).click();
78+
// TODO await attachScreenshot(page, testInfo, 'Outputs Review - Files');
6779
await expectOutputFileDownload(page, 'Download Archive', /\.(zip)$/);
6880

6981
await page.getByRole('button', { name: 'Review' }).click();

test/e2e/playwright.config.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { defineConfig, devices } from '@playwright/test';
2+
import { authHeader, BASE_URL } from './utils/env';
23

34
/**
45
* Read environment variables from file.
@@ -26,21 +27,22 @@ export default defineConfig({
2627
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
2728
use: {
2829
/* Base URL to use in actions like `await page.goto('')`. */
29-
baseURL: 'http://localhost:5502',
30+
baseURL: BASE_URL,
3031

3132
/* Action timeout (e.g. toBeEnabled, toBeVisible) */
3233
actionTimeout: 10000,
3334

3435
/* Basic Auth for AEM */
3536
extraHTTPHeaders: {
36-
'Authorization': 'Basic ' + Buffer.from('admin:admin').toString('base64'),
37+
...authHeader(),
38+
'Origin': BASE_URL,
3739
},
3840

3941
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
4042
trace: 'on-first-retry',
4143

42-
/* Screenshots on failure */
43-
screenshot: 'on',
44+
/* Screenshots only on failure (manual screenshots still work) */
45+
screenshot: 'only-on-failure',
4446

4547
/* Videos on failure */
4648
video: 'retain-on-failure',

test/e2e/utils/context.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Browser, Page } from '@playwright/test';
2+
import { authHeader, BASE_URL } from './env';
23

34
export async function newAemContext(
45
browser: Browser,
@@ -7,10 +8,8 @@ export async function newAemContext(
78
callback: (page: Page) => Promise<void>
89
): Promise<void> {
910
const context = await browser.newContext({
10-
baseURL: 'http://localhost:5502',
11-
extraHTTPHeaders: {
12-
'Authorization': 'Basic ' + btoa(`${user}:${password}`),
13-
},
11+
baseURL: BASE_URL,
12+
extraHTTPHeaders: authHeader(user, password),
1413
});
1514

1615
const page = await context.newPage();

0 commit comments

Comments
 (0)