Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ node_modules/
.aos/
notes-world/
.playwright-mcp/
platform/web/test-results/
.tmp/
refs/
.bridge-state.json
Expand Down
176 changes: 129 additions & 47 deletions package-lock.json

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

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
"test:release-packaging": "npm --prefix clients/typescript ci --ignore-scripts && npm --prefix platform/configurator-mcp ci --ignore-scripts && scripts/release/stage-runtimes.sh",
"typecheck": "tsc --noEmit && npm run typecheck --workspace @lightspeed-ai/connectors && npm run typecheck --workspace @lightspeed-ai/platform-web && npm run typecheck --workspace @lightspeed-ai/sdk && npm run typecheck --workspace @lightspeed-ai/configurator-mcp",
"build:demo": "npm run build:demo --workspace @lightspeed-ai/platform-web",
"demo": "npm run dev:demo --workspace @lightspeed-ai/platform-web"
"demo": "npm run dev:demo --workspace @lightspeed-ai/platform-web",
"screenshots:demo": "npm run screenshots:demo --workspace @lightspeed-ai/platform-web --",
"screendiff:demo": "npm run screendiff:demo --workspace @lightspeed-ai/platform-web --"
},
"devDependencies": {
"@types/node": "^24.19.1",
Expand Down
36 changes: 36 additions & 0 deletions platform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,39 @@ and manifest keys stay stable). The connector host serves the providers named
by `LIGHTSPEED_CONNECTOR_PROVIDERS` for every account the core reports; see
`connectors/README.md`. The release manifest records one digest for each
image.

### Testing & Visual Tests

The web UI's tests run in Vitest and are part of `npm test` and `npm run check`.
Logic tests call page helpers with plain data; component tests mount pages in
jsdom with the API mocked, click through them, and assert the resulting DOM and
API calls. They sit next to the code they cover (`*.test.ts`, `*.test.tsx`):

```bash
npm run test --workspace @lightspeed-ai/platform-web
npm run test --workspace @lightspeed-ai/platform-web -- src/pages/AccountPage.test.tsx
```

Visual tests capture the demo build in a real browser with Playwright
(`web/e2e/`) and compare two versions with
[screendiff](https://github.com/dankrusi/screendiff). Each screen is captured
in light and dark at a 1440×900 viewport and 2× pixel density:

```bash
npx playwright install chromium # once
npm run screenshots:demo # capture the working tree
npm run screendiff:demo # working tree vs. where the branch left main
npm run screendiff:demo -- main~3 HEAD # any two refs
npm run screendiff:demo -- --theme dark # one theme
```

Results go to `platform/web/test-results/`: screenshots, and one
self-contained `report.html` per comparison. The report embeds every image, so
a comparison removes its captured PNGs afterwards; pass `--keep-screenshots` to
keep them. A committed ref is built in a temporary worktree and its build is
cached by commit.

Visual tests are not part of the automatic test process and should not be added
to `npm test`, `npm run check`, or CI. Use them as a review tool: to see what a
change does to the UI and UX, and to show it to others before merging. A
changed screen is a prompt to look, not a failure.
47 changes: 47 additions & 0 deletions platform/web/e2e/screens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/// Screens captured from the demo build. Paths are relative to the demo base
/// (`/demo/`). Ids name the PNGs, so keep them stable: renaming one shows up
/// as a removed and an added screen in the next comparison.
///
/// Only plain routes for now; screens that need a click first (open dialogs,
/// expanded panels) come later as per-screen setup steps.
export interface Screen {
id: string;
path: string;
}

const factory = "u/software-factory";

export const SCREENS: Screen[] = [
{ id: "sessions", path: `${factory}/sessions` },
{ id: "session-detail", path: `${factory}/sessions/session-flaky-scheduler` },
{ id: "session-detail-audit", path: `${factory}/sessions/session-scheduler-audit` },
{ id: "bots", path: `${factory}/bots` },
{ id: "bot-chat", path: `${factory}/bots/planner` },
{ id: "bot-activity", path: `${factory}/bots/planner/activity` },
{ id: "bots-support", path: "u/technical-support/bots" },
{ id: "workspace", path: `${factory}/workspaces/acme-web` },
{ id: "workspace-file", path: `${factory}/workspaces/acme-web/files/docs/adr-0007.md` },
{ id: "profiles", path: `${factory}/profiles` },
{ id: "profile-detail", path: `${factory}/profiles/planner` },
{ id: "models", path: `${factory}/models` },
{ id: "environments", path: `${factory}/environments` },
{ id: "mcp-servers", path: `${factory}/mcp-servers` },
{ id: "credentials", path: `${factory}/credentials` },
{ id: "api-keys", path: `${factory}/api-keys` },
{ id: "members", path: `${factory}/members` },
{ id: "settings-general", path: `${factory}/settings/general` },
{ id: "settings-channels", path: `${factory}/settings/channels` },
{ id: "settings-templates", path: `${factory}/settings/templates` },
{ id: "admin-users", path: "admin/users" },
{ id: "admin-audit", path: "admin/audit" },
{ id: "admin-universes", path: "admin/universes" },
{ id: "admin-api-keys", path: "admin/api-keys" },
{ id: "admin-channels", path: "admin/channels" },
{ id: "admin-environment-providers", path: "admin/environment-providers" },
{ id: "account", path: "account" },
];

export const THEMES = ["light", "dark"] as const;
export type Theme = (typeof THEMES)[number];

export const VIEWPORT = { name: "desktop", width: 1440, height: 900, scale: 2 } as const;
Loading
Loading