Repository navigation
Conversation
Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…to the app Six @GUI tests in their own Playwright project (video and trace always on): mock editor body edit, field override on the Overrides page, status override 503, Settings client lane select, header Scenario picker with strict lane default and lane global fallback, and the Network trace after an app load. Each asserts the new value on screen in the app. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…artifacts Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
… drop fixed known gaps Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…tests step by step Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
… the GUI videos npm run artifacts (scripts/build-run-artifacts.ts) now also writes gui-videos/<name>.md next to each side-by-side clip, other-tests/<name>.md for the rest and e2e-run-summary.md (also the job summary): test command from config.argv, cwd and env from report metadata, the annotated steps and assertions, the workflow steps (job API with statuses, else the YAML) and local reproduce commands. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Docs prefix tests path twice
- Removed duplicate tests/ prefix from four locations in run-docs.ts since Playwright JSON reporter already includes it in spec.file relative to e2e/.
You can send follow-ups to the cloud agent here.
Playwright JSON reporter already includes tests/ in spec.file (relative to e2e/), so prepending tests/ again created invalid paths like tests/tests/... in reproduce commands and spec links. Updated run-docs.ts to use test.file directly without the extra prefix.
Outline the element being changed, hold 2.5 s before and after the edit / save / toast, type values key by key and hold on each new app value. Off (default) keeps the current timing. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…the run docs Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
Playwright's JSON report gives spec.file relative to rootDir (e2e/tests), without a tests/ prefix, so the previous commit produced e2e/<spec> and an unscoped test filter. TestRun.file is now the path relative to e2e/, which works whatever the reporter's base is. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
… tests Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
apt mirrors were slow enough on the runners that the capped install gave up and no clip was composed. The static binary (with libx264) comes with npm ci in e2e/; FFMPEG_PATH overrides it. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…ter in-app navigation When the dashboard's mock list was already loaded, it filled the picker while the picker's own fetch was running; the effect was cancelled and pickerLoading never reset, so the picker stayed disabled until a full page reload. Reset it in the effect cleanup. chore(release): bump @sgedda/mockifyer-dashboard 1.5.94 -> 1.5.95 Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…rough to each page The only direct load is /; the mock editor, Overrides, Settings > Client lanes and Network are reached via sidebar links, mock search, Expand all, the mock card and the Overrides picker. In presentation mode each navigation click is outlined with 1 s holds. Steps are listed in the docs. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…olds in presentation mode Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…ings start together beforeEach requests the dashboard fixture first, so the dashboard waits on its start screen while the app (fresh context) types the demo credentials, clicks Sign in and the Discover tab. The same openDiscover flow takes presentation-aware clicks and typing for GUI tests only; other tests keep plain fill/click. Login and app navigation are listed as WanderWeird app steps in the docs. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…ER_RECORD is unset mock-bootstrap passed recordOnMiss: MOCKIFYER_RECORD === 'true', so an unset env became an explicit record=false on every /api/proxy request and the dashboard's Record switch never applied to the services. Pass recordOnMiss only when the env is set (core then omits `record`, as documented). Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…estarts ww-service.sh stops/starts the gateway or wander-api against any dashboard, optionally without the record env (wander.sh now wraps it); scratch-dashboard.sh runs an empty branch-build dashboard on :3022 with a fresh sqlite dir. lib/stack.ts gets scratchStack.start/stop. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…then create and switch scenarios Empty dashboard, app all live and nothing stored; lane added, one load with Record On (request-only placeholders), Record Off; Hops: expand GET /api/discover -> GET /discover, Open-Meteo hop -> Use saved mock; the next load captures only that endpoint (Hops Replay, Network Mock, others live). Scenario A from default and B from A with their own values; switching the lane moves the app each time. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
… dashboard logs on failure Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
- Explicitly unset MOCKIFYER_RECORD env vars when WW_RECORD=off - Allow whitespace in domain folder name regex - Fix hop expand toggle xpath to find sibling button
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: env -u flags after assignments fail
- Moved record_env array to the beginning of the env command so -u options appear before NAME=VALUE assignments, fixing the command syntax error.
You can send follow-ups to the cloud agent here.
Move record_env array to the beginning of the env command to ensure -u flags appear before NAME=VALUE assignments. GNU and BSD env require options before assignments; placing -u after assignments caused env to treat -u as the command to execute, failing with 'No such file or directory'.
…r a mock hit, a lane switch and a 503 fallback Network: Bodies on, Clear, Paused; Trace: expand GET /api/discover -> GET /discover -> Open-Meteo hop; Details show Source Mock/Upstream, Status, Duration, Lane, request headers and response bodies with the value the app shows (99, heatwave 44, 503 + wander-api fallback 18); Client connections shows the lane's last resolved scenario. afterEach turns body capture off again. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
The lane title also appears on the Network Details pane, so the row matched two elements in presentation mode (scrollIntoView is strict). Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit b972be4. Configure here.
… 503 step too Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…he 503 test) Mock editor on the Open-Meteo mock only: Response Delay 2500 ms -> the app's Discover request takes >= 2.5 s (browser timing) and still shows 99; + Status Override 503 -> 18 (wander-api fallback) after >= 2.5 s; clear each -> fast again, 99. Network trace: the Open-Meteo hop's status/duration change while the countries hop stays 200 and fast; only that mock stores the settings. Shared traceAppLoad and setResponseSimulation (set or Clear) for this and the tracing walkthrough. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
…of reading it once The header panel stays mounted and only calls getClientLanes on mount and every 15 s; opening it does not refetch, so right after a lane switch it can still show the previous scenario. The Scenario (lane) / Last resolved assertions now retry for one poll interval plus margin (20 s). Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
cursor Bot
pushed a commit
that referenced
this pull request
Oct 28, 2026
…ack walkthrough - Create new /e2e-tutorial page with complete tutorial from PR #487 - Add route, navigation item, SEO metadata, sitemap entry - Include all 9 scenario walkthroughs with neutral terminal prompts - Add branch note callout for PR #487 dependency (easy to remove after merge) - Wire into llms.txt and llms-full.txt for AI discoverability - Add comprehensive e2e test covering page sections and navigation - Frontend build passes (ESLint config not present as noted in AGENTS.md) No product package versions changed (website-only change). Tutorial covers proxy runtime, client lanes, scenarios, network trace, per-endpoint control, failure injection, and dashboard GUI tests. Co-authored-by: Sebastian Gedda <sebastian.gedda@gmail.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Adds eight Playwright GUI tests (tag
@gui) that drive the real Mockifyer dashboard UI in a second, desktop-sized browser context while the WanderWeird app runs in the first:e2e/tests/dashboard-gui.spec.ts, on the demo stack (including a tracing walkthrough and a per-endpoint delay/status test);e2e/tests/dashboard-gui-scratch.spec.ts, a from-scratch flow on an empty dashboard.Every test ends by asserting the changed value on screen in the app. CI records both pages on every run and composes one side-by-side mp4 per test (app on the left, dashboard on the right) with ffmpeg. Each mp4 has a generated Markdown description with the same base name, and the run gets a summary (
e2e-run-summary.md, also written to the job summary). An opt-in presentation mode (E2E_PRESENTATION=1) slows the GUI tests down at each value change so the clips are readable.Both panes start at their entry screen, and the two recordings start together. The GUI
beforeEachopens the dashboard first, so the dashboard waits on its start screen while the app signs in. The app opens at its login screen in a fresh browser context (no stored session), types the demo user and password into the form, clicks Sign in, then clicks the Discover tab to reach the Atlantis Temperature tile. Login is not interleaved with dashboard steps.The dashboard starts on its start screen (
/), its only direct URL load. It then reaches each page by visible clicks:latitude=37.9838→ Expand all → the "forecast" card;The selectors are existing labels, placeholders,
aria-labels and the twodata-testids from #484.One dashboard fix (
@sgedda/mockifyer-dashboard1.5.94 → 1.5.95). Reaching Overrides by in-app navigation exposed a bug inOverridesView.tsx: the "Open mock for overlays" picker stayed disabled on "Loading mocks…" until a full reload. The already-loaded mock list filled the picker while the picker's own fetch ran; the effect was cancelled, andpickerLoadingwas never reset. The effect cleanup now resets it (a two-line change).current→temperature_2m= 37, Save Changescurrent.temperature_2m= 61, Save overlays, Open mockMockhop under wander-apiGET /discoverGET /api/discover→GET /discover→ Open-Meteo hop; Details and Client connections, then a heatwave lane switch and a 503 override"temperature_2m": 99) → 44° (Last resolved heatwave) → 18° (hop 503, wander-api body"source": "fallback")The optional date-override test (f) is not included. The app renders no date taken from the mocks, so it could not show a change on screen, which is a hard requirement. Dates remain covered at API level in
dates.spec.ts.Delay and status override on one endpoint
This extends the former "503 status override" test instead of adding a second one; its 503 → 18° assertion is still part of it. It uses the per-endpoint Response Simulation fields in the mock editor (Request tab: Status Override and Response Delay (ms), served through the proxy since #485) on the Athens Open-Meteo mock only:
POST /api/proxyfor/api/discover), takes ≥ 2500 ms and the tile still shows 99°. The app has no loading indicator on a refetch (the old card stays until the answer arrives), so the clip shows the delay as the hop's Duration in the Network trace: the Open-Meteo hop is Mock, Status 200, Duration ≥ 2500 ms, whileGET /countries/name/greecestays Upstream, Status 200, under 2500 ms.if (!response.ok)→ fallback), so 404 or 500 would show the same 18°; only 503 is tested.statusOverride503 /responseDelayMs2500. Every other mock ofguide-demo-2, and the heatwave copy of the same endpoint, keeps the settings it had before the test.afterEachalso resetsresponseDelayMs.Tracing walkthrough
Tracing views that exist in the dashboard UI:
/network): List / Trace / Waterfall / Gantt / Journey views. The Details pane shows URL, Method, Source (Mock / Upstream / Error), Transport, Request id, Triggered by, Status, Duration, Lane, a Call chain strip and Request/Response headers. With Bodies on for that scenario it also shows "Request body" and "Response body" (new traffic only)./hops): stored chains. A hop opens its mock editor, whose Request / Response / Metadata tabs are the closest thing to "Req / Res".There is no separate Atlas trace page (
/atlasredirects to Network). The walkthrough uses the Network trace, because the demo's Athens forecast mock is stored without a parent link, so Hops does not nest it underGET /discover; the live trace does.The test generates traffic through the app UI only. For each case it clears the lane's log, reloads Discover, waits for the fresh hop, clicks Live → Paused, then Collapse all and expands
GET /api/discover→GET /discover→ the Open-Meteo hop:wanderweird-demo, a request headerx-mockifyer-client-id: wanderweird-demo, and a response body with"temperature_2m": 99. wander-apiGET /discover: Source Upstream, and a response body with 99. The app shows 99°."temperature_2m": 44, and Client connections shows Scenario (lane) heatwave and Last resolved heatwave. The app shows 44°."source": "fallback","temperature_2m": 18and"Upstream 503 for …". The app shows 18°.afterEachturns body capture off again for both scenarios.From-scratch test (
dashboard-gui-scratch.spec.ts)The from-scratch test starts with completely empty data, on a throw-away branch-built dashboard at
:3022with a fresh sqlite dir (scripts/scratch-dashboard.sh). For this file only, the gateway and wander-api are restarted to proxy through it without the record env (scripts/ww-service.sh <service> startwithMOCKIFYER_DASHBOARD_URL=http://127.0.0.1:3022 WW_RECORD=off). The app and the other services stay on the demo dashboard.afterAllrestores the gateway and wander-api and deletes the scratch data, so the test is idempotent; two back-to-back runs both passed.Flow, all through the UI with the same start-screen navigation and presentation holds:
GET /discoverand Open-Meteo hops as "Upstream", and Hops is empty.wanderweird-demo. One app load runs with the header Record: On (the default), which stores one request-only placeholder per called endpoint: no response body, served live. Then Record: Off.GET /api/discover→GET /discover. The Open-Meteo hop appears only after expanding, with a "Pending" badge. Click it → its mock editor → Use saved mock./discoverand countries as "Upstream"; the Mocks › Domains tree showsapi.open-meteo.com"1 mocked" and every other host "0 mocked". The API check confirms that only the forecast has a stored body, and the app tile matches it.defaultand B from A, each with Use saved mock and its own value (55°, 66°). Switching the lane A ↔ B moves the app each time.What the dashboard offers for "mock one endpoint". The per-endpoint controls are a mock's replay mode (mock editor, reached from a hop) and a path folder's Record response rule (Mocks › Domains tree; the server rule is
recordResponses+autoMockper host/path). Both need the endpoint to be stored first, and the Hops page lists stored entries only. The Network page shows live hops but has no per-endpoint toggle. Hence the one placeholder load (Record On, no bodies) before switching Record off. A product option that would remove that step: a "Record response for this path" action in the Network view's Details pane (not built here).Demo fix (WanderWeird, not a published package).
packages/mock-bootstrappassedrecordOnMiss: MOCKIFYER_RECORD === 'true', so an unset env became an explicitrecord: falseon every/api/proxyrequest and the dashboard's Record switch never applied to the services. It now passesrecordOnMissonly when the env is set; core then omitsrecord, as documented. The CI stack setsMOCKIFYER_RECORD=true, so its behavior is unchanged.How it works
The
dashfixture opens the dashboard in its own context with its ownrecordVideo(URL from thedashboardUrloption), loads the start screen, then attaches that video to the result. Playwright's ownvideoattachment is the app page:The GUI specs'
beforeEach({ page, dash })requestsdashfirst, so both recordings start together, then signs in through the app's login screen (openAppFromLogin).The GUI tests run in their own project (
dashboard-gui*.spec.ts), which always records and traces. The existingchromiumproject ignores them and keepsretain-on-failure, oronwhenE2E_VIDEO=on.Each test carries its own description as annotations, so the description reaches the JSON report. Login and navigation steps are listed too:
The 33 existing API and app tests get a one-line
documented('asserts …')annotation.npm run artifacts(scripts/build-run-artifacts.ts) readstest-results/results.jsonand writes everything intogui-videos/:scale=-2:800on each video and thenhstack, giving<spec>--<title>.mp4at 1662×800. The two sources are copied toindividual/<name>.{app,dashboard}.webm.<name>.mdsits next to each mp4, andother-tests/<name>.mdcovers every other test. Each file has:file:line, project and tags, plus where the videos and trace are in the artifacts;scripts/scratch-dashboard.sh,scripts/ww-service.sh);config.argvfrom the report, e.g.npx playwright test), the working directory (e2e) and env (CI,E2E_VIDEO,E2E_PRESENTATION,MAIN_*, URL overrides), recorded in config metadata with repo paths as<repo>;e2e.ymlin order, each tagged Mockifyer, Demo app (WanderWeird), Test run or Helper, with its command;npx playwright test tests/<file>:<line> --project=<project>.e2e-run-summary.mdhas the run link, presentation mode, passed/failed/flaky/skipped counts, every test with its "asserts" line, the artifacts, the workflow steps and the reproduce commands. In CI it is also appended to$GITHUB_STEP_SUMMARY.GITHUB_TOKEN, job permissionscontents: read,actions: read), with each step's status. Elsewhere, or if that call fails, it comes from the workflow YAML (parsed withyaml, a new devDependency).<host>in the generated files. Recordings contain only the two browser pages.Last frames of two local clips:
Field override: app 61°, editor shows stored 99
Network view: Open-Meteo Mock hop under wander-api GET /discover
Presentation mode (
E2E_PRESENTATION=1)Off by default, and off for pull requests: normal runs keep exactly the current timing and assertions. When it is on, only the GUI tests slow down:
pressSequentially, 120 ms per key);Page loads keep their normal speed. It is implemented as one small helper set in
lib/gui.ts:The workflow turns it on for
scheduleruns andworkflow_dispatchruns; the newpresentationinput defaults to true and can be unticked. Pull requests keep it off. The run summary and each test's Markdown file show a "Presentation mode" row, andE2E_PRESENTATIONappears in the env and reproduce commands.Local GUI project timings, off vs on:
CI (
.github/workflows/e2e.yml)npm run artifactsafter the tests, also when tests fail. ffmpeg comes from theffmpeg-staticdevDependency, a static build with libx264. There is no apt step: slow apt mirrors made an earlier run's capped install give up.FFMPEG_PATHoverrides the binary.e2e-gui-videos.mdper GUI test,e2e-run-summary.md,other-tests/*.mde2e-videos*.app.webm/*.dashboard.webm, plus other tests' videos (failures, or all withE2E_VIDEO=on)e2e-reporte2e-tracestrace.zipper GUI test plus traces of failed testse2e-logstest-results/and service logs, including the gateway and the scratch dashboard (replaces the olde2e-report-<n>)e2e-videos-<run_number>upload, which only ran on scheduled or manual runs, is replaced by the above.retriesis unchanged.Other changes
untilAfterRefetch/expectTemperatureOtherThanAfterRefetch/temperatureTile/shownTemperature/timedRefetchDiscoverinlib/app.tsopenDiscover(page, { ui, fromLoginScreen })inlib/app.ts: GUI tests pass presentation-aware clicks and typing (openAppFromLogininlib/gui.ts); the other tests keep plainfill/clickfollowLaneAndWait/pinToBaseAndWait/scratchStackinlib/stack.tsclearFieldOverrides/restoreDemoScenarios/setNetworkBodiesinlib/dashboard.tssetResponseSimulation(set or Clear),traceChildanddetailDurationMsinlib/gui.ts; the spec-leveltraceAppLoadis shared by the tracing and delay/status testsscripts/ww-service.shruns the gateway or wander-api against any dashboard (wander.shnow wraps it). Also new:scripts/scratch-dashboard.shand a sharedscripts/port-lib.sh.afterEach: Athens body, status override, response delay, field overrides, lane (re-created if removed), global scenario, lane global fallback and network body capture.wander-apifollows the lane for the demo GUI file and is pinned back inafterAll. The Network, tracing and delay/status tests clear only the demo lane's network log, which is telemetry and is not restored.rootDir, givinge2e/tests/<spec>:<line>. This replaces a branch commit that dropped thetests/prefix.npm run test:gui,npm run artifacts,--headed) and the artifacts. It also removes the stale "Known gaps" entries (header picker, proxy status/delay) that fix: Mockifyer and WanderWeird fixes found by the e2e suite (#481) #485 fixed.Testing
npx playwright test→ 41 passed (2.5 min), of which 33 are existing and 8 are GUI. In CI the from-scratch test takes about 30 s, the tracing walkthrough about 25 s, and the delay/status test 19 s (about 14 s more than the 503-only test it replaces); the test step varies by about ±30 s between runs.E2E_PRESENTATION=1: all GUI tests pass. Frames were checked: each clip starts with the app login next to the dashboard start screen, login, navigation and expand clicks are outlined, and the toast and the new app value are held on screen.npm run artifactswrites one mp4 and one.mdper GUI test, per-test.mdfiles for the other tests, and the summary. No hostname appears in any generated file.npm test: 137 suites passed. Dashboard frontend and backend builds pass; frontend lint shows only a warning that was already there (OverridesView.tsxline 428).To show artifacts inline, enable in settings.
Note
Medium Risk
Large E2E and CI pipeline changes plus a behavioral tweak to proxy
recordOnMisswhen the record env is unset; core product risk is low but nightly CI runtime and demo-stack recording semantics change.Reviewed by Cursor Bugbot for commit 55d8e27. Bugbot is set up for automated code reviews on this repo. Configure here.