Skip to content

Commit f0ece41

Browse files
committed
wip
1 parent 031a115 commit f0ece41

5 files changed

Lines changed: 87 additions & 34 deletions

File tree

.github/workflows/e2e_recordings.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ name: e2e recordings
22

33
on:
44
push:
5-
branches:
6-
- main
5+
#branches:
6+
# - main
77
workflow_dispatch:
88

99
permissions:

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ services:
1313
- ./frontend/src:/usr/src/app/frontend/src
1414
- ./frontend/theme:/usr/src/app/frontend/theme
1515
- ./frontend/index.html:/usr/src/app/frontend/index.html
16+
- ./frontend/tsconfig.json:/usr/src/app/frontend/tsconfig.json
17+
- ./frontend/tsconfig.node.json:/usr/src/app/frontend/tsconfig.node.json
1618

1719
backend-primary:
1820
build:

frontend/tests/README.md

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -56,47 +56,29 @@ npx playwright codegen http://localhost:8080
5656

5757
Read more: https://playwright.dev/docs/codegen-intro
5858

59-
### Recording new stories with codegen (incl. GitHub Codespaces)
59+
### Recording new stories with codegen
6060

61-
Stories live in `tests/e2e/stories/` and are recorded walkthroughs: they import `test` from
62-
`support/recordingFixtures` and use the `support/walkthroughHelpers` (`smoothClick`, `narrate`,
63-
pacing) so the same test doubles as a tutorial video when run with `RECORD=1`.
64-
65-
To author a new story starting from `codegen`:
66-
67-
1. Start the full docker stack (`docker compose up`) so the app is served on
68-
`http://localhost:8080` and the backend is available for session seeding.
69-
2. Give the backend access to real Sumo data. The seeded session authenticates with a testing
70-
sentinel token, so the backend falls back to a Sumo **shared key** that is not present outside
71-
CI. Add the prod key as a Codespace secret named `SHARED_KEY_DROGON_READ_PROD`, then install it
72-
into the running `backend-primary` container:
61+
Stories live in `tests/e2e/stories/`. To create a new story using Playwright Codegen:
7362

63+
1. Start the full docker development stack:
64+
`docker-compose -f docker-compose.yml -f docker-compose-cosmos-db.yml up`
65+
2. Give the backend access to Drogon Sumo data using the test user. You can do this by first ensuring
66+
the environment variable `SHARED_KEY_DROGON_READ_PROD` is set and then run
7467
```bash
75-
npm run test:e2e:sumo-key
68+
npm run test:e2e:sumo-key --prefix ./frontend
7669
```
77-
78-
Re-run this whenever the stack is recreated (the key lives inside the container). Without it,
79-
backend fetches to Sumo fail.
80-
3. In a Codespace, `codegen` needs a display for its headed browser. This repo's dev container
81-
ships the `desktop-lite` feature, which serves a lightweight desktop over the forwarded
82-
**port 6080** (noVNC) — open it in a browser tab to watch/drive the recorded browser.
83-
4. Seed an authenticated session and launch codegen (it starts logged in via the seeded
84-
`storageState.json`, so no interactive login is needed):
85-
70+
Re-run this whenever the docker stack is recreated (the key lives inside the container).
71+
4. Launch codegen
8672
```bash
87-
npm run test:e2e:codegen
73+
npm run test:e2e:codegen --prefix ./frontend
8874
```
89-
90-
This runs `npm run test:e2e:seed` first (writes `tests/e2e/setup/storageState.json`) and then
91-
opens `playwright codegen`, saving the captured actions to `tests/e2e/stories/_recorded.gen.ts`
92-
(git-ignored). If you only need to refresh the session, run `npm run test:e2e:seed` on its own.
75+
If you are in GitHub codespace you can view the application on port XXX.
76+
77+
Captured actions are stored to `tests/e2e/stories/_recorded.gen.ts`
9378
5. Copy `tests/e2e/stories/_story.template.ts` to `<yourStory>.test.ts` and port the captured
9479
selectors/actions into it, wrapping interactions in `smoothClick`/`smoothFill` and adding
9580
`narrate(...)` lines. `codegen` emits plain Playwright calls, so this adaptation is manual.
96-
6. Verify with `npm run test:e2e` (fast regression run) or `npm run test:e2e:record` (produces the
97-
narrated video).
98-
5. Verify with `npm run test:e2e` (fast regression run) or `npm run test:e2e:record` (produces the
99-
narrated video).
81+
6. Verify with `npm run test:e2e:record`
10082

10183
## TODO: Do we need to run sudo iptables-legacy -P FORWARD ACCEPT ?
10284

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Template for a recorded-walkthrough e2e story.
3+
*
4+
* How to use:
5+
* 1. Copy this file to `<yourStory>.test.ts` in this folder (the `.test.ts` suffix is what makes
6+
* Playwright pick it up; this template is deliberately named so it is ignored).
7+
* 2. Capture the raw clicks/fills with `npm run test:e2e:codegen` (see tests/README.md). Codegen
8+
* writes plain Playwright calls to `_recorded.gen.ts` — a starting point for the selectors.
9+
* 3. Port those actions into the body below, wrapping interactions in `smoothClick`/`smoothFill`
10+
* and adding `narrate(...)` lines. These are no-ops unless RECORD=1, so the story still runs as
11+
* a fast regression check with `npm run test:e2e`.
12+
*
13+
* Requires the full docker stack running; the `authenticated-*` project loads the seeded session so
14+
* the app starts logged in.
15+
*/
16+
import { expect } from "@playwright/test";
17+
18+
import { test } from "../support/recordingFixtures";
19+
import {
20+
dragModuleOntoLayout,
21+
hideDevOverlays,
22+
installFakeCursor,
23+
smoothClick,
24+
} from "../support/walkthroughHelpers";
25+
26+
test.describe("My module", () => {
27+
test("does the thing", async ({ page, narrate }) => {
28+
test.setTimeout(180_000);
29+
30+
// Render a visible cursor and hide dev-only overlays so the recorded video stays clean.
31+
await installFakeCursor(page);
32+
await hideDevOverlays(page);
33+
34+
await page.goto("/");
35+
await expect(page.getByText("FMU Analysis").first()).toBeVisible();
36+
37+
await narrate("Describe what this walkthrough will show.");
38+
39+
40+
await page.goto('/');
41+
await smoothClick(page, page.getByRole("button", { name: "New session" }));
42+
43+
await smoothClick(page, page.getByRole('button', { name: 'New session' }));
44+
await smoothClick(page, page.getByTestId('add-regular-ensemble-button'));
45+
await smoothClick(page, page.locator('[id="base-ui-:rbn:"]'));
46+
await page.locator('[id="base-ui-:rbn:"]').fill('My description');
47+
await smoothClick(page, page.getByText('My description').first());
48+
await smoothClick(page, page.getByText('iter-0 (100 realizations)'));
49+
await smoothClick(page, page.getByRole('button', { name: 'Apply' }));
50+
await smoothClick(page, page.getByRole('button', { name: 'Apply' }));
51+
52+
const dragNarration = narrate(
53+
"Now we drag the 3D Viewer module from the list onto the dashboard and wait for the relevant data and settings to load.",
54+
);
55+
await dragModuleOntoLayout(page, "3D Viewer");
56+
await dragNarration;
57+
58+
await smoothClick(page, page.getByText('3D Viewer'));
59+
await smoothClick(page, page.getByTestId('module-layout').getByTestId('WebAssetIcon'));
60+
await expect(page.getByRole('button', { name: 'Add first view' })).toBeVisible();
61+
await smoothClick(page, page.getByRole('button', { name: 'Add first view' }));
62+
await smoothClick(page, page.getByRole('button', { name: 'Add' }).nth(1));
63+
await smoothClick(page, page.getByRole('menuitem', { name: 'Layers' }));
64+
await smoothClick(page, page.getByRole('menuitem', { name: 'Grid Model' }));
65+
await smoothClick(page, page.getByRole('menuitem', { name: 'Grid Model 3D' }));
66+
67+
});
68+
});

frontend/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"forceConsistentCasingInFileNames": true,
1212
"module": "ESNext",
1313
"moduleResolution": "bundler",
14+
"allowImportingTsExtensions": true,
1415
"resolveJsonModule": true,
1516
"isolatedModules": true,
1617
"noEmit": true,

0 commit comments

Comments
 (0)