feat: integrate Playwright for E2E testing and enhance testing framework
- Added Playwright for end-to-end testing in the `apps/web` module, including a new `login.spec.ts` for testing login functionality. - Updated package.json to include Playwright dependencies and new test commands for E2E testing. - Enhanced .gitignore to exclude Playwright test results and reports. - Modified existing documentation to reflect the integration of Playwright and updated testing guidelines. - Refactored test commands to streamline the testing process, including a dedicated command for E2E tests. These changes improve the testing framework by providing robust E2E testing capabilities, enhancing the reliability and quality of the application.
This commit is contained in:
@@ -3,7 +3,7 @@ name: archify
|
|||||||
description: Create polished, validated architecture, workflow, sequence, data-flow, and lifecycle/state diagrams as explorable standalone HTML with inline SVG, dark/light themes, optional trace motion, and PNG/JPEG/WebP/SVG/WebM export. Accept plain-language requirements or pasted Mermaid flowchart, sequenceDiagram, and stateDiagram input; inspect repository evidence when the diagram must reflect real code. Use when the user asks to visualize system architecture, infrastructure, cloud/security/network topology, technical workflows, API call sequences, request lifecycles, data pipelines, ETL/ELT, data lineage, state machines, or to convert/beautify Mermaid.
|
description: Create polished, validated architecture, workflow, sequence, data-flow, and lifecycle/state diagrams as explorable standalone HTML with inline SVG, dark/light themes, optional trace motion, and PNG/JPEG/WebP/SVG/WebM export. Accept plain-language requirements or pasted Mermaid flowchart, sequenceDiagram, and stateDiagram input; inspect repository evidence when the diagram must reflect real code. Use when the user asks to visualize system architecture, infrastructure, cloud/security/network topology, technical workflows, API call sequences, request lifecycles, data pipelines, ETL/ELT, data lineage, state machines, or to convert/beautify Mermaid.
|
||||||
license: MIT
|
license: MIT
|
||||||
metadata:
|
metadata:
|
||||||
version: "2.16"
|
version: '2.16'
|
||||||
author: tt-a1i
|
author: tt-a1i
|
||||||
based_on: Cocoon-AI/architecture-diagram-generator (MIT, v1.0)
|
based_on: Cocoon-AI/architecture-diagram-generator (MIT, v1.0)
|
||||||
---
|
---
|
||||||
@@ -26,6 +26,7 @@ Use this bounded path for ordinary generation. Do not read the optional Viewer R
|
|||||||
```
|
```
|
||||||
|
|
||||||
A receipt with only 4 artifact checks is basic validation, never showcase acceptance. A showcase pass must report all 9 artifact checks with 0 composition errors and 0 warnings. If the candidate omits or misspells the exact `meta.quality_profile` field, fix it before geometry. For a workflow v2 geometry diagnosis, run `node bin/archify.mjs validate workflow <candidate.json> --layout-json` and use the stable compiler receipt; solver internals are not authoring controls. A passing final validation freezes the candidate: never edit it afterward.
|
A receipt with only 4 artifact checks is basic validation, never showcase acceptance. A showcase pass must report all 9 artifact checks with 0 composition errors and 0 warnings. If the candidate omits or misspells the exact `meta.quality_profile` field, fix it before geometry. For a workflow v2 geometry diagnosis, run `node bin/archify.mjs validate workflow <candidate.json> --layout-json` and use the stable compiler receipt; solver internals are not authoring controls. A passing final validation freezes the candidate: never edit it afterward.
|
||||||
|
|
||||||
5. For a delivered HTML, `deliver` is the final acceptance command:
|
5. For a delivered HTML, `deliver` is the final acceptance command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -54,13 +55,13 @@ Lifecycle note: phase columns `0..4` occupy the main rail; event/terminal column
|
|||||||
|
|
||||||
## Type router
|
## Type router
|
||||||
|
|
||||||
| Type | Use for |
|
| Type | Use for |
|
||||||
|---|---|
|
| -------------- | --------------------------------------------------------------- |
|
||||||
| `architecture` | Components, services, cloud/security boundaries, infrastructure |
|
| `architecture` | Components, services, cloud/security boundaries, infrastructure |
|
||||||
| `workflow` | Processes, approval gates, tool calls, runbooks, CI/CD |
|
| `workflow` | Processes, approval gates, tool calls, runbooks, CI/CD |
|
||||||
| `sequence` | API call chains, request lifecycles, async traces, returns |
|
| `sequence` | API call chains, request lifecycles, async traces, returns |
|
||||||
| `dataflow` | Pipelines, ETL/ELT, lineage, governance, consumers |
|
| `dataflow` | Pipelines, ETL/ELT, lineage, governance, consumers |
|
||||||
| `lifecycle` | State/status transitions, retries, waiting and terminal states |
|
| `lifecycle` | State/status transitions, retries, waiting and terminal states |
|
||||||
|
|
||||||
When ambiguous, run `node bin/archify.mjs guide "<scenario>" --json`. Scenario proof examples are structural references, not facts to copy.
|
When ambiguous, run `node bin/archify.mjs guide "<scenario>" --json`. Scenario proof examples are structural references, not facts to copy.
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Reference this skill when working on this project. It contains:
|
|||||||
|
|
||||||
- **Apps**: React 19 + Vite (`apps/web`, `apps/showcase`, `apps/landing`) + Electron (`apps/desktop`) + VitePress (`apps/docs-dev`)
|
- **Apps**: React 19 + Vite (`apps/web`, `apps/showcase`, `apps/landing`) + Electron (`apps/desktop`) + VitePress (`apps/docs-dev`)
|
||||||
- **Packages**: `@repo/ui` (Mantine), `@repo/core-api`, `@repo/core-storage`, `@repo/core-i18n`, `@repo/core-events`, `@repo/utils`, `@repo/brand`, `packages/configs`
|
- **Packages**: `@repo/ui` (Mantine), `@repo/core-api`, `@repo/core-storage`, `@repo/core-i18n`, `@repo/core-events`, `@repo/utils`, `@repo/brand`, `packages/configs`
|
||||||
- **Testing**: Vitest; Testing Library in `packages/ui` and `packages/core-events`
|
- **Testing**: Vitest; Playwright E2E in `apps/web/e2e/`; Testing Library in `packages/ui` and `packages/core-events`
|
||||||
- **Package manager**: pnpm 8.15.6 + Turbo
|
- **Package manager**: pnpm 8.15.6 + Turbo
|
||||||
|
|
||||||
**Where to work:** product in `apps/web`; copy UI/API usage from `apps/showcase`; concepts from `apps/docs-dev`. Do not invent a parallel UI kit.
|
**Where to work:** product in `apps/web`; copy UI/API usage from `apps/showcase`; concepts from `apps/docs-dev`. Do not invent a parallel UI kit.
|
||||||
@@ -128,6 +128,7 @@ export const createFullPageSchema = (t: (key: string) => string) =>
|
|||||||
```bash
|
```bash
|
||||||
pnpm test
|
pnpm test
|
||||||
pnpm --filter web test
|
pnpm --filter web test
|
||||||
|
pnpm test:e2e:web
|
||||||
pnpm --filter @repo/ui test
|
pnpm --filter @repo/ui test
|
||||||
pnpm typecheck:web
|
pnpm typecheck:web
|
||||||
pnpm check:all
|
pnpm check:all
|
||||||
@@ -135,7 +136,7 @@ pnpm check:all
|
|||||||
|
|
||||||
- Unit tests colocated as `*.test.ts(x)`
|
- Unit tests colocated as `*.test.ts(x)`
|
||||||
- Component tests with Testing Library in packages that already have it
|
- Component tests with Testing Library in packages that already have it
|
||||||
- App journeys: browser-verify login and FULL_PAGE index / form / detail
|
- App journeys: Playwright in `apps/web/e2e/` (login is the first sample)
|
||||||
- Minimum 80% coverage; TDD (red → green → refactor)
|
- Minimum 80% coverage; TDD (red → green → refactor)
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -149,6 +150,7 @@ pnpm dev:docs-dev
|
|||||||
pnpm lint
|
pnpm lint
|
||||||
pnpm typecheck:web
|
pnpm typecheck:web
|
||||||
pnpm test
|
pnpm test
|
||||||
|
pnpm test:e2e:web
|
||||||
pnpm check:all
|
pnpm check:all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: tdd-workflow
|
name: tdd-workflow
|
||||||
description: Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage using Vitest, Testing Library, and browser journeys.
|
description: Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage using Vitest, Testing Library, and Playwright E2E.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Test-Driven Development Workflow
|
# Test-Driven Development Workflow
|
||||||
@@ -24,7 +24,7 @@ TDD for this frontend monorepo (Vitest, not NestJS/Supertest).
|
|||||||
|
|
||||||
- **Unit** — validators, transformers, utils, stores (`*.test.ts`)
|
- **Unit** — validators, transformers, utils, stores (`*.test.ts`)
|
||||||
- **Component** — Testing Library in `packages/ui` / `packages/core-events`
|
- **Component** — Testing Library in `packages/ui` / `packages/core-events`
|
||||||
- **Journeys** — login and FULL_PAGE index/form/detail; mock HTTP services; browser-verify layout
|
- **Journeys** — Playwright in `apps/web/e2e/` (login sample first); mock HTTP with `page.route`
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ vi.mock('@repo/core-api/http-client', () => ({
|
|||||||
|
|
||||||
## File organization
|
## File organization
|
||||||
|
|
||||||
Colocate `*.test.ts(x)` next to source. No `test/*.e2e-spec.ts` NestJS tree.
|
Colocate unit tests as `*.test.ts(x)` next to source. Playwright E2E lives in `apps/web/e2e/` (see `login.spec.ts`). Do not use a NestJS `test/*.e2e-spec.ts` tree.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
@@ -85,6 +85,7 @@ Colocate `*.test.ts(x)` next to source. No `test/*.e2e-spec.ts` NestJS tree.
|
|||||||
pnpm test
|
pnpm test
|
||||||
pnpm --filter @repo/ui test
|
pnpm --filter @repo/ui test
|
||||||
pnpm --filter web test -- --watch
|
pnpm --filter web test -- --watch
|
||||||
|
pnpm test:e2e:web
|
||||||
pnpm lint
|
pnpm lint
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -99,4 +100,4 @@ pnpm lint
|
|||||||
|
|
||||||
- 80%+ coverage
|
- 80%+ coverage
|
||||||
- All tests green
|
- All tests green
|
||||||
- Critical FULL_PAGE flows covered or browser-verified
|
- Critical FULL_PAGE flows covered by Playwright or browser-verified
|
||||||
|
|||||||
@@ -1,43 +1,46 @@
|
|||||||
---
|
---
|
||||||
name: e2e-runner
|
name: e2e-runner
|
||||||
description: Frontend journey specialist using Vitest, Testing Library, and browser verification for apps/web module flows. Use PROACTIVELY for critical UI journeys (login, index, form, detail).
|
description: Frontend journey specialist using Playwright for apps/web E2E, plus Vitest and Testing Library for package journeys. Use PROACTIVELY for critical UI journeys (login, index, form, detail).
|
||||||
tools: Read, Write, Edit, Bash, Grep, Glob
|
tools: Read, Write, Edit, Bash, Grep, Glob
|
||||||
model: opus
|
model: opus
|
||||||
---
|
---
|
||||||
|
|
||||||
# E2E / Journey Runner
|
# E2E / Journey Runner
|
||||||
|
|
||||||
You are a frontend journey specialist for this pnpm + Turborepo React monorepo. There is no NestJS, Supertest, or Playwright suite. Cover critical user journeys with Vitest (+ Testing Library where the package already uses it) and browser verification for `apps/web`.
|
You are a frontend journey specialist for this pnpm + Turborepo React monorepo. Cover critical user journeys with Playwright in `apps/web/e2e/` and with Vitest (+ Testing Library where the package already uses it) for packages.
|
||||||
|
|
||||||
## Core Responsibilities
|
## Core Responsibilities
|
||||||
|
|
||||||
1. **Package / component journeys** — Vitest + Testing Library in `packages/ui` and `packages/core-events`
|
1. **App E2E** — Playwright specs in `apps/web/e2e/` (first sample: `e2e/login.spec.ts`)
|
||||||
2. **App journeys** — browser-verify `apps/web` flows (login, FULL_PAGE index / form / detail)
|
2. **Package / component journeys** — Vitest + Testing Library in `packages/ui` and `packages/core-events`
|
||||||
3. **Isolation** — mock `@repo/core-api` HTTP services; never hit a real backend unless the user asks
|
3. **Isolation** — mock the backend with Playwright `page.route` (see `e2e/fixtures/mock-api.ts`); never hit a real API unless the user asks
|
||||||
4. **Flaky management** — no arbitrary sleeps; wait for UI or network conditions
|
4. **Flaky management** — no arbitrary sleeps; wait for UI or network conditions
|
||||||
5. **Reporting** — Vitest output and a short pass/fail summary
|
5. **Reporting** — Playwright/Vitest output and a short pass/fail summary
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
pnpm test:e2e:web
|
||||||
|
pnpm --filter web test:e2e
|
||||||
|
pnpm --filter web test:e2e:ui
|
||||||
pnpm test
|
pnpm test
|
||||||
pnpm --filter @repo/ui test
|
pnpm --filter @repo/ui test
|
||||||
pnpm --filter @repo/core-events test
|
|
||||||
pnpm --filter web test
|
pnpm --filter web test
|
||||||
pnpm check:all
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
First-time browsers: `pnpm --filter web exec playwright install chromium`
|
||||||
|
|
||||||
## What to test
|
## What to test
|
||||||
|
|
||||||
### Critical `apps/web` journeys
|
### Critical `apps/web` journeys (Playwright)
|
||||||
|
|
||||||
1. Login (`src/apps/auth/login`)
|
1. Login (`e2e/login.spec.ts`) — copy this sample for new journeys
|
||||||
2. FULL_PAGE index — table + filters
|
2. FULL_PAGE index — table + filters
|
||||||
3. FULL_PAGE form — create / edit / duplicate
|
3. FULL_PAGE form — create / edit / duplicate
|
||||||
4. FULL_PAGE detail
|
4. FULL_PAGE detail
|
||||||
5. Auth session teardown (`terminateAuthSession`)
|
5. Auth session teardown (`terminateAuthSession`)
|
||||||
|
|
||||||
Canonical sample: `apps/web/src/apps/main/modules/example/full-page/`. Copy that pattern; do not invent a third page style.
|
Canonical UI sample: `apps/web/src/apps/main/modules/example/full-page/`. Copy that page pattern; do not invent a third page style.
|
||||||
|
|
||||||
### Package component tests (Testing Library)
|
### Package component tests (Testing Library)
|
||||||
|
|
||||||
@@ -52,36 +55,18 @@ it('renders the field label', () => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mock remote data services (not a database)
|
### Mock the HTTP backend (Playwright)
|
||||||
|
|
||||||
```ts
|
Reuse `mockBackend(page)` from `apps/web/e2e/fixtures/mock-api.ts`. Extend that helper for new endpoints instead of calling a live server.
|
||||||
vi.mock('../../domain/factories', () => ({
|
|
||||||
fullPageDataService: {
|
|
||||||
list: vi.fn(),
|
|
||||||
get: vi.fn(),
|
|
||||||
create: vi.fn(),
|
|
||||||
update: vi.fn(),
|
|
||||||
delete: vi.fn(),
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
```
|
|
||||||
|
|
||||||
## Browser verification (`apps/web`)
|
Unit tests still mock `@repo/core-api` services — not a database.
|
||||||
|
|
||||||
When the change is routing, layout, or a flow Vitest cannot see:
|
|
||||||
|
|
||||||
1. Use `pnpm dev:web`
|
|
||||||
2. Drive login → index → form → detail the way a user would
|
|
||||||
3. Check empty, error, and success states
|
|
||||||
4. Confirm related routes that share module state stay consistent
|
|
||||||
|
|
||||||
Do not add Playwright unless the user explicitly asks.
|
|
||||||
|
|
||||||
## Flaky-test rules
|
## Flaky-test rules
|
||||||
|
|
||||||
- Prefer `getByRole` / `getByLabelText` over CSS classes
|
- Prefer `getByRole` / `getByLabel` over CSS classes
|
||||||
- Wait for elements or responses, never fixed sleeps
|
- Wait for elements or responses, never fixed sleeps
|
||||||
- Each test sets up its own data
|
- Each test sets up its own data
|
||||||
|
- Keep Playwright specs in `apps/web/e2e/`; do not colocate them next to source (Vitest would pick them up)
|
||||||
|
|
||||||
## Report format
|
## Report format
|
||||||
|
|
||||||
@@ -89,7 +74,7 @@ Do not add Playwright unless the user explicitly asks.
|
|||||||
# Journey Report
|
# Journey Report
|
||||||
|
|
||||||
**Status:** PASSING / FAILING
|
**Status:** PASSING / FAILING
|
||||||
**Command:** pnpm test
|
**Command:** pnpm test:e2e:web
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const createFullPageSchema = (t: (key: string) => string) =>
|
|||||||
|
|
||||||
1. **Unit** — validators, transformers, utils, stores (`*.test.ts`)
|
1. **Unit** — validators, transformers, utils, stores (`*.test.ts`)
|
||||||
2. **Component** — Testing Library in packages that already have it
|
2. **Component** — Testing Library in packages that already have it
|
||||||
3. **Journeys** — login and FULL_PAGE index / form / detail; mock `fullPageDataService`. Browser-verify layout/routing. See **e2e-runner**.
|
3. **Journeys** — Playwright in `apps/web/e2e/` (copy `login.spec.ts`). Mock HTTP with `mockBackend`. See **e2e-runner**.
|
||||||
|
|
||||||
## Mocking
|
## Mocking
|
||||||
|
|
||||||
|
|||||||
+10
-12
@@ -1,18 +1,17 @@
|
|||||||
---
|
---
|
||||||
description: Generate and run frontend journey tests with Vitest/Testing Library, plus browser verification for apps/web. Covers login and FULL_PAGE index/form/detail.
|
description: Generate and run frontend journey tests with Playwright for apps/web, plus Vitest/Testing Library for packages. Covers login and FULL_PAGE index/form/detail.
|
||||||
---
|
---
|
||||||
|
|
||||||
# E2E / Journey Command
|
# E2E / Journey Command
|
||||||
|
|
||||||
This command invokes the **e2e-runner** agent to cover critical UI journeys. There is no NestJS or Playwright suite.
|
This command invokes the **e2e-runner** agent to cover critical UI journeys.
|
||||||
|
|
||||||
## What This Command Does
|
## What This Command Does
|
||||||
|
|
||||||
1. **Identify journeys** — login, FULL_PAGE index / form / detail
|
1. **Identify journeys** — login, FULL_PAGE index / form / detail
|
||||||
2. **Write or update Vitest tests** — mock `@repo/core-api` services
|
2. **Write or update Playwright specs** in `apps/web/e2e/` (copy `e2e/login.spec.ts`)
|
||||||
3. **Run** `pnpm test` (or `pnpm --filter web test`)
|
3. **Run** `pnpm test:e2e:web` (or `pnpm --filter web test:e2e`)
|
||||||
4. **Browser-verify** `apps/web` when the change is routing or layout
|
4. **Report** pass/fail
|
||||||
5. **Report** pass/fail
|
|
||||||
|
|
||||||
## When to Use
|
## When to Use
|
||||||
|
|
||||||
@@ -27,11 +26,10 @@ Use `/e2e` when:
|
|||||||
|
|
||||||
The e2e-runner agent will:
|
The e2e-runner agent will:
|
||||||
|
|
||||||
1. Copy patterns from `apps/web/src/apps/main/modules/example/full-page/`
|
1. Copy the login sample in `apps/web/e2e/login.spec.ts` and UI patterns from `example/full-page`
|
||||||
2. Mock `fullPageDataService` (or the module's factory) — not a database
|
2. Mock the backend with `mockBackend` (`e2e/fixtures/mock-api.ts`) — not a live API
|
||||||
3. Run `pnpm test`
|
3. Run `pnpm test:e2e:web`
|
||||||
4. Drive the browser for layout/routing if needed (`pnpm dev:web`)
|
4. Summarize failures
|
||||||
5. Summarize failures
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
@@ -39,7 +37,7 @@ The e2e-runner agent will:
|
|||||||
User: /e2e Test the example full-page index and detail flow
|
User: /e2e Test the example full-page index and detail flow
|
||||||
```
|
```
|
||||||
|
|
||||||
Canonical sample: `example/full-page`. Do not invent a third page style. Do not add Playwright unless asked.
|
Canonical UI sample: `example/full-page`. Canonical E2E sample: `apps/web/e2e/login.spec.ts`.
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ alwaysApply: true
|
|||||||
| code-reviewer | Code review | After writing code |
|
| code-reviewer | Code review | After writing code |
|
||||||
| security-reviewer | Security analysis | Before commits |
|
| security-reviewer | Security analysis | Before commits |
|
||||||
| build-error-resolver | Fix build errors | When build fails |
|
| build-error-resolver | Fix build errors | When build fails |
|
||||||
| e2e-runner | Frontend journeys | Vitest + RTL, browser flows |
|
| e2e-runner | Frontend journeys | Playwright in `apps/web/e2e/` |
|
||||||
| refactor-cleaner | Dead code cleanup | Code maintenance |
|
| refactor-cleaner | Dead code cleanup | Code maintenance |
|
||||||
| doc-updater | Documentation | Updating docs |
|
| doc-updater | Documentation | Updating docs |
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ pnpm + Turborepo monorepo. Work from the repository root. Package manager: `pnpm
|
|||||||
- Before inventing UI or package usage, match `apps/showcase` demos and `apps/docs-dev` docs.
|
- Before inventing UI or package usage, match `apps/showcase` demos and `apps/docs-dev` docs.
|
||||||
- Prefer `@repo/ui`, `@repo/core-*`, `@repo/utils` over app-local duplicates or raw Mantine/axios.
|
- Prefer `@repo/ui`, `@repo/core-*`, `@repo/utils` over app-local duplicates or raw Mantine/axios.
|
||||||
- Env files live **inside the app** (`apps/web/.env*`), never at monorepo root. Read env via `src/core/environment` (`ENV`), not `import.meta.env` in components.
|
- Env files live **inside the app** (`apps/web/.env*`), never at monorepo root. Read env via `src/core/environment` (`ENV`), not `import.meta.env` in components.
|
||||||
- Run scripts from root: `pnpm dev:web`, `pnpm dev:showcase`, `pnpm lint`, `pnpm typecheck:web`, `pnpm test`, `pnpm check:all`.
|
- Run scripts from root: `pnpm dev:web`, `pnpm dev:showcase`, `pnpm lint`, `pnpm typecheck:web`, `pnpm test`, `pnpm test:e2e:web`, `pnpm check:all`.
|
||||||
|
|
||||||
## Import map (preferred)
|
## Import map (preferred)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: TDD workflow, 80% coverage minimum, Vitest unit tests, and browser journey verification
|
description: TDD workflow, 80% coverage minimum, Vitest unit tests, and Playwright E2E for apps/web
|
||||||
alwaysApply: true
|
alwaysApply: true
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -11,9 +11,9 @@ Test types:
|
|||||||
|
|
||||||
1. **Unit tests** — pure functions, transformers, validators, stores, utilities (`*.test.ts` / `*.test.tsx`, colocated or `__tests__/`)
|
1. **Unit tests** — pure functions, transformers, validators, stores, utilities (`*.test.ts` / `*.test.tsx`, colocated or `__tests__/`)
|
||||||
2. **Component tests** — Testing Library in packages that already have it (`packages/ui`, `packages/core-events`)
|
2. **Component tests** — Testing Library in packages that already have it (`packages/ui`, `packages/core-events`)
|
||||||
3. **App journeys** — browser verification of `apps/web` flows (login, index / form / detail). There is no Playwright or NestJS E2E suite in this repo.
|
3. **App journeys** — Playwright E2E in `apps/web/e2e/` (login is the first sample). Mock the backend with `page.route`; do not hit a live API unless the user asks. There is no NestJS/Supertest suite in this frontend repo.
|
||||||
|
|
||||||
Runner: **Vitest**. Root command: `pnpm test`. Per-package: `pnpm --filter <pkg> test`. Also `pnpm typecheck` and `pnpm check:all`.
|
Runner: **Vitest** for unit tests (`pnpm test`). Playwright for web E2E (`pnpm test:e2e:web` or `pnpm --filter web test:e2e`). Also `pnpm typecheck` and `pnpm check:all` (unit/lint/typecheck only).
|
||||||
|
|
||||||
## Test-Driven Development
|
## Test-Driven Development
|
||||||
|
|
||||||
@@ -30,11 +30,11 @@ MANDATORY workflow:
|
|||||||
|
|
||||||
1. Use **tdd-guide** agent
|
1. Use **tdd-guide** agent
|
||||||
2. Check test isolation
|
2. Check test isolation
|
||||||
3. Verify mocks are correct (`@repo/core-api` services, HTTP client — not a database)
|
3. Verify mocks are correct (`@repo/core-api` / HTTP client for unit tests; `mockBackend` in `apps/web/e2e/fixtures/mock-api.ts` for Playwright)
|
||||||
4. Fix implementation, not tests (unless tests are wrong)
|
4. Fix implementation, not tests (unless tests are wrong)
|
||||||
|
|
||||||
## Agent Support
|
## Agent Support
|
||||||
|
|
||||||
- **tdd-guide** — Use PROACTIVELY for new features, enforces write-tests-first
|
- **tdd-guide** — Use PROACTIVELY for new features, enforces write-tests-first
|
||||||
- **e2e-runner** — Frontend journeys: Vitest + Testing Library, plus browser verification for `apps/web`
|
- **e2e-runner** — Playwright E2E in `apps/web/e2e/`, plus Vitest + Testing Library for package journeys
|
||||||
- Skill: `.agents/skills/tdd-workflow/`
|
- Skill: `.agents/skills/tdd-workflow/`
|
||||||
|
|||||||
+7
-1
@@ -51,4 +51,10 @@ legacy/
|
|||||||
|
|
||||||
# VitePress
|
# VitePress
|
||||||
**/.vitepress/cache/
|
**/.vitepress/cache/
|
||||||
**/.vitepress/dist/
|
**/.vitepress/dist/
|
||||||
|
|
||||||
|
# Playwright
|
||||||
|
**/test-results/
|
||||||
|
**/playwright-report/
|
||||||
|
**/blob-report/
|
||||||
|
**/playwright/.cache/
|
||||||
@@ -10,10 +10,10 @@ You need permission to view each menu. Status buttons (Process, Complete, Submit
|
|||||||
|
|
||||||
Set up the records that every sales document needs:
|
Set up the records that every sales document needs:
|
||||||
|
|
||||||
| You need | Where to create it |
|
| You need | Where to create it |
|
||||||
| --- | --- |
|
| ----------------------------------- | ---------------------------- |
|
||||||
| Division, branch, customer, product | **Settings → Data** |
|
| Division, branch, customer, product | **Settings → Data** |
|
||||||
| Salesperson | **Sales → Data → Employees** |
|
| Salesperson | **Sales → Data → Employees** |
|
||||||
|
|
||||||
If a menu is missing, ask an administrator to give your privilege **View** (and **Update** for status buttons) on that area.
|
If a menu is missing, ask an administrator to give your privilege **View** (and **Update** for status buttons) on that area.
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ A request is optional. You can go straight to a sales order.
|
|||||||
|
|
||||||
1. Click **Create**. Fill in the same kind of details as a request. On a new order you can pick a sales request under **Source**; that copies the request into the form. Save. A new order starts as **Draft**.
|
1. Click **Create**. Fill in the same kind of details as a request. On a new order you can pick a sales request under **Source**; that copies the request into the form. Save. A new order starts as **Draft**.
|
||||||
2. On a **Draft** order, click **Process**.
|
2. On a **Draft** order, click **Process**.
|
||||||
- You will see: *Processing creates a sales invoice and, unless skipped, a packing slip.*
|
- You will see: _Processing creates a sales invoice and, unless skipped, a packing slip._
|
||||||
- **Generate packing slip** is checked by default. Uncheck it if you do not want a packing slip.
|
- **Generate packing slip** is checked by default. Uncheck it if you do not want a packing slip.
|
||||||
3. On **Draft** or **Processed**, you can **Cancel**. There is no **Complete** button on orders. If the order later shows **Completed**, that was not something you clicked on this screen.
|
3. On **Draft** or **Processed**, you can **Cancel**. There is no **Complete** button on orders. If the order later shows **Completed**, that was not something you clicked on this screen.
|
||||||
4. On the order detail page you can see linked packing slips and invoices, and click **Create Sales Invoice**.
|
4. On the order detail page you can see linked packing slips and invoices, and click **Create Sales Invoice**.
|
||||||
@@ -134,32 +134,32 @@ Approving a payment does not change the invoice status from this screen. Refresh
|
|||||||
|
|
||||||
Both use Draft → Pending → Approved or Rejected.
|
Both use Draft → Pending → Approved or Rejected.
|
||||||
|
|
||||||
| Current status | Buttons | Change status |
|
| Current status | Buttons | Change status |
|
||||||
| --- | --- | --- |
|
| -------------- | ------------------------------------------------------------ | ------------------------- |
|
||||||
| Draft | Submit | Rejected |
|
| Draft | Submit | Rejected |
|
||||||
| Pending | Approve, Reject. Payments also have Rollback (back to Draft) | Draft, Approved, Rejected |
|
| Pending | Approve, Reject. Payments also have Rollback (back to Draft) | Draft, Approved, Rejected |
|
||||||
| Approved | — | — |
|
| Approved | — | — |
|
||||||
| Rejected | — | Draft |
|
| Rejected | — | Draft |
|
||||||
|
|
||||||
### Sales order
|
### Sales order
|
||||||
|
|
||||||
| Current status | Buttons | Change status |
|
| Current status | Buttons | Change status |
|
||||||
| --- | --- | --- |
|
| -------------- | --------------- | -------------------- |
|
||||||
| Draft | Process, Cancel | Processed, Cancelled |
|
| Draft | Process, Cancel | Processed, Cancelled |
|
||||||
| Processed | Cancel | Cancelled |
|
| Processed | Cancel | Cancelled |
|
||||||
| Completed | — | — |
|
| Completed | — | — |
|
||||||
| Cancelled | — | — |
|
| Cancelled | — | — |
|
||||||
|
|
||||||
**Process** always opens the packing-slip checkbox dialog (not Change status).
|
**Process** always opens the packing-slip checkbox dialog (not Change status).
|
||||||
|
|
||||||
### Packing slip
|
### Packing slip
|
||||||
|
|
||||||
| Current status | Buttons | Change status |
|
| Current status | Buttons | Change status |
|
||||||
| --- | --- | --- |
|
| -------------- | ---------------- | -------------------- |
|
||||||
| Draft | Cancel | Processed, Cancelled |
|
| Draft | Cancel | Processed, Cancelled |
|
||||||
| Processed | Complete, Cancel | Completed, Cancelled |
|
| Processed | Complete, Cancel | Completed, Cancelled |
|
||||||
| Completed | — | — |
|
| Completed | — | — |
|
||||||
| Cancelled | — | — |
|
| Cancelled | — | — |
|
||||||
|
|
||||||
**Complete** always asks for delivered quantities.
|
**Complete** always asks for delivered quantities.
|
||||||
|
|
||||||
@@ -167,11 +167,11 @@ Both use Draft → Pending → Approved or Rejected.
|
|||||||
|
|
||||||
You may see Draft, Processed, Partial, Completed, or Cancelled.
|
You may see Draft, Processed, Partial, Completed, or Cancelled.
|
||||||
|
|
||||||
| Current status | What you can do |
|
| Current status | What you can do |
|
||||||
| --- | --- |
|
| ---------------------------- | ----------------- |
|
||||||
| Draft, Processed, or Partial | Cancel |
|
| Draft, Processed, or Partial | Cancel |
|
||||||
| Completed | No status buttons |
|
| Completed | No status buttons |
|
||||||
| Cancelled | No status buttons |
|
| Cancelled | No status buttons |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ Use the sidebar to open **Sales** for day-to-day selling, **Logistics** for pack
|
|||||||
|
|
||||||
## Where to find things
|
## Where to find things
|
||||||
|
|
||||||
| Area | Menu | What you do there |
|
| Area | Menu | What you do there |
|
||||||
| --- | --- | --- |
|
| ------------ | ---------------------- | ------------------------------------------------- |
|
||||||
| Sales | Sales → Activities | Requests, orders, invoices, payments, visit plans |
|
| Sales | Sales → Activities | Requests, orders, invoices, payments, visit plans |
|
||||||
| Logistics | Logistics → Activities | Packing slips, delivery plans |
|
| Logistics | Logistics → Activities | Packing slips, delivery plans |
|
||||||
| Company data | Settings → Data | Divisions, branches, customers, products |
|
| Company data | Settings → Data | Divisions, branches, customers, products |
|
||||||
| Access | Settings → User | Users and privileges |
|
| Access | Settings → User | Users and privileges |
|
||||||
|
|
||||||
If a menu item is missing, your privilege does not include **View** for that area.
|
If a menu item is missing, your privilege does not include **View** for that area.
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ This repository uses **[Turborepo](https://turbo.build/repo)** to orchestrate ta
|
|||||||
| `pnpm build:docs-dev` | Build only the docs-dev application |
|
| `pnpm build:docs-dev` | Build only the docs-dev application |
|
||||||
| `pnpm build:desktop` | Build the web app, then compile the Electron app |
|
| `pnpm build:desktop` | Build the web app, then compile the Electron app |
|
||||||
| `pnpm test` | Run unit tests ([Vitest](https://vitest.dev/)) across all packages |
|
| `pnpm test` | Run unit tests ([Vitest](https://vitest.dev/)) across all packages |
|
||||||
|
| `pnpm test:e2e:web` | Run Playwright E2E for `apps/web` (starts Vite on port 4173) |
|
||||||
| `pnpm lint` | Run [ESLint](https://eslint.org/) across the workspace |
|
| `pnpm lint` | Run [ESLint](https://eslint.org/) across the workspace |
|
||||||
| `pnpm format` | Format code using [Prettier](https://prettier.io/) |
|
| `pnpm format` | Format code using [Prettier](https://prettier.io/) |
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export const E2E_LOGIN = {
|
||||||
|
username: 'administrator',
|
||||||
|
password: 'password123',
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export function createFakeJwt(expiresInSeconds = 3600): string {
|
||||||
|
const header = Buffer.from(JSON.stringify({ alg: 'none', typ: 'JWT' })).toString('base64url');
|
||||||
|
const payload = Buffer.from(
|
||||||
|
JSON.stringify({
|
||||||
|
sub: 'e2e-user',
|
||||||
|
exp: Math.floor(Date.now() / 1000) + expiresInSeconds,
|
||||||
|
}),
|
||||||
|
).toString('base64url');
|
||||||
|
|
||||||
|
return `${header}.${payload}.e2e`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import type { Page, Route } from '@playwright/test';
|
||||||
|
import { E2E_LOGIN } from './credentials';
|
||||||
|
import { createFakeJwt } from './fake-jwt';
|
||||||
|
|
||||||
|
const APP_HOSTS = new Set(['127.0.0.1', 'localhost']);
|
||||||
|
const APP_PORT = Number(process.env.E2E_PORT ?? 4173);
|
||||||
|
|
||||||
|
const EMPTY_LIST = {
|
||||||
|
data: [],
|
||||||
|
meta: {
|
||||||
|
currentPage: 1,
|
||||||
|
itemsPerPage: 10,
|
||||||
|
totalItems: 0,
|
||||||
|
totalPages: 0,
|
||||||
|
itemCount: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const E2E_USER = {
|
||||||
|
id: 'e2e-user-id',
|
||||||
|
username: E2E_LOGIN.username,
|
||||||
|
isSuperadmin: true,
|
||||||
|
privilege: null,
|
||||||
|
permissions: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LoginApiOutcome = 'success' | 'unauthorized';
|
||||||
|
|
||||||
|
export async function mockBackend(page: Page, login: LoginApiOutcome = 'success'): Promise<void> {
|
||||||
|
await page.route('**/*', async (route) => {
|
||||||
|
const requestUrl = new URL(route.request().url());
|
||||||
|
if (isAppRequest(requestUrl)) {
|
||||||
|
await route.continue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await fulfillBackend(route, login);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAppRequest(requestUrl: URL): boolean {
|
||||||
|
const port = Number(requestUrl.port || (requestUrl.protocol === 'https:' ? 443 : 80));
|
||||||
|
return APP_HOSTS.has(requestUrl.hostname) && port === APP_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fulfillBackend(route: Route, login: LoginApiOutcome): Promise<void> {
|
||||||
|
const request = route.request();
|
||||||
|
const pathname = new URL(request.url()).pathname.replace(/\/$/, '');
|
||||||
|
|
||||||
|
if (pathname.endsWith('/auth/login') && request.method() === 'POST') {
|
||||||
|
if (login === 'unauthorized') {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 401,
|
||||||
|
contentType: 'application/json',
|
||||||
|
body: JSON.stringify({ statusCode: 401, message: 'Unauthorized' }),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: 'application/json',
|
||||||
|
body: JSON.stringify({
|
||||||
|
accessToken: createFakeJwt(),
|
||||||
|
refreshToken: createFakeJwt(86_400),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathname.endsWith('/auth/me') && request.method() === 'GET') {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: 'application/json',
|
||||||
|
body: JSON.stringify(E2E_USER),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resourceType = request.resourceType();
|
||||||
|
if (resourceType === 'xhr' || resourceType === 'fetch') {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: 'application/json',
|
||||||
|
body: JSON.stringify(EMPTY_LIST),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await route.abort();
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
import { E2E_LOGIN } from './fixtures/credentials';
|
||||||
|
import { mockBackend } from './fixtures/mock-api';
|
||||||
|
|
||||||
|
test.describe('login', () => {
|
||||||
|
test('renders the login form', async ({ page }) => {
|
||||||
|
await mockBackend(page);
|
||||||
|
await page.goto('/auth/login');
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: 'Login to your account!' })).toBeVisible();
|
||||||
|
await expect(page.getByLabel('Username')).toBeVisible();
|
||||||
|
await expect(page.getByLabel('Password')).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Login' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('signs in with valid credentials and lands in the app', async ({ page }) => {
|
||||||
|
await mockBackend(page, 'success');
|
||||||
|
await page.goto('/auth/login');
|
||||||
|
|
||||||
|
await page.getByLabel('Username').fill(E2E_LOGIN.username);
|
||||||
|
await page.getByLabel('Password').fill(E2E_LOGIN.password);
|
||||||
|
await page.getByRole('button', { name: 'Login' }).click();
|
||||||
|
|
||||||
|
await expect(page).toHaveURL(/\/app(\/|$)/);
|
||||||
|
await expect(page.getByRole('heading', { name: 'Full Page' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('shows an error and stays on login when credentials are rejected', async ({ page }) => {
|
||||||
|
await mockBackend(page, 'unauthorized');
|
||||||
|
await page.goto('/auth/login');
|
||||||
|
|
||||||
|
await page.getByLabel('Username').fill(E2E_LOGIN.username);
|
||||||
|
await page.getByLabel('Password').fill(E2E_LOGIN.password);
|
||||||
|
await page.getByRole('button', { name: 'Login' }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText('Invalid username or password')).toBeVisible();
|
||||||
|
await expect(page).toHaveURL(/\/auth\/login/);
|
||||||
|
await expect(page.getByRole('heading', { name: 'Login to your account!' })).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -8,9 +8,12 @@
|
|||||||
"dev": "pnpm run copy:brand && vite --clearScreen false",
|
"dev": "pnpm run copy:brand && vite --clearScreen false",
|
||||||
"build": "pnpm run copy:brand && tsc && vite build",
|
"build": "pnpm run copy:brand && tsc && vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint \"src/**/*.ts\"",
|
"lint": "eslint \"src/**/*.ts\" \"e2e/**/*.ts\" \"playwright.config.ts\"",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest --watch",
|
"test:watch": "vitest --watch",
|
||||||
|
"test:e2e": "playwright test",
|
||||||
|
"test:e2e:ui": "playwright test --ui",
|
||||||
|
"test:e2e:install": "playwright install chromium",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -37,6 +40,7 @@
|
|||||||
"zustand": "^5.0.14"
|
"zustand": "^5.0.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.55.0",
|
||||||
"@repo/eslint-config": "workspace:*",
|
"@repo/eslint-config": "workspace:*",
|
||||||
"@repo/typescript-config": "workspace:*",
|
"@repo/typescript-config": "workspace:*",
|
||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
|
||||||
|
const E2E_PORT = Number(process.env.E2E_PORT ?? 4173);
|
||||||
|
const E2E_ORIGIN = `http://127.0.0.1:${E2E_PORT}`;
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './e2e',
|
||||||
|
fullyParallel: true,
|
||||||
|
forbidOnly: Boolean(process.env.CI),
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
reporter: 'list',
|
||||||
|
timeout: 60_000,
|
||||||
|
use: {
|
||||||
|
baseURL: E2E_ORIGIN,
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
},
|
||||||
|
webServer: {
|
||||||
|
command: `pnpm run copy:brand && vite --clearScreen false --host 127.0.0.1 --port ${E2E_PORT} --strictPort`,
|
||||||
|
url: E2E_ORIGIN,
|
||||||
|
reuseExistingServer: !process.env.CI,
|
||||||
|
timeout: 120_000,
|
||||||
|
},
|
||||||
|
projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
|
||||||
|
});
|
||||||
@@ -21,5 +21,6 @@ export default defineConfig({
|
|||||||
test: {
|
test: {
|
||||||
environment: 'node',
|
environment: 'node',
|
||||||
globals: false,
|
globals: false,
|
||||||
|
exclude: ['**/node_modules/**', '**/dist/**', '**/e2e/**'],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"lint": "turbo run lint",
|
"lint": "turbo run lint",
|
||||||
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
||||||
"test": "turbo run test",
|
"test": "turbo run test",
|
||||||
|
"test:e2e:web": "pnpm --filter web test:e2e",
|
||||||
"typecheck": "turbo run typecheck",
|
"typecheck": "turbo run typecheck",
|
||||||
"typecheck:web": "turbo run typecheck --filter=web",
|
"typecheck:web": "turbo run typecheck --filter=web",
|
||||||
"typecheck:landing": "turbo run typecheck --filter=landing",
|
"typecheck:landing": "turbo run typecheck --filter=landing",
|
||||||
|
|||||||
Generated
+39
-4
@@ -239,7 +239,7 @@ importers:
|
|||||||
version: 5.4.17(@types/node@22.19.3)
|
version: 5.4.17(@types/node@22.19.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^4.0.17
|
specifier: ^4.0.17
|
||||||
version: 4.0.17(@opentelemetry/api@1.9.1)
|
version: 4.0.17(jsdom@26.1.0)
|
||||||
|
|
||||||
apps/web:
|
apps/web:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -307,6 +307,9 @@ importers:
|
|||||||
specifier: ^5.0.14
|
specifier: ^5.0.14
|
||||||
version: 5.0.14(@types/react@19.2.7)(react@19.2.3)
|
version: 5.0.14(@types/react@19.2.7)(react@19.2.3)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@playwright/test':
|
||||||
|
specifier: ^1.55.0
|
||||||
|
version: 1.62.1
|
||||||
'@repo/eslint-config':
|
'@repo/eslint-config':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/configs/eslint
|
version: link:../../packages/configs/eslint
|
||||||
@@ -333,7 +336,7 @@ importers:
|
|||||||
version: 5.4.17(@types/node@22.19.3)
|
version: 5.4.17(@types/node@22.19.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^4.0.17
|
specifier: ^4.0.17
|
||||||
version: 4.0.17(@opentelemetry/api@1.9.1)
|
version: 4.0.17(jsdom@26.1.0)
|
||||||
|
|
||||||
packages/brand:
|
packages/brand:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@@ -551,7 +554,7 @@ importers:
|
|||||||
version: 5.5.4
|
version: 5.5.4
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^4.0.17
|
specifier: ^4.0.17
|
||||||
version: 4.0.17(@opentelemetry/api@1.9.1)
|
version: 4.0.17(jsdom@26.1.0)
|
||||||
|
|
||||||
packages/ui:
|
packages/ui:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -733,7 +736,7 @@ importers:
|
|||||||
version: 5.5.4
|
version: 5.5.4
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^4.0.17
|
specifier: ^4.0.17
|
||||||
version: 4.0.17(@opentelemetry/api@1.9.1)
|
version: 4.0.17(jsdom@26.1.0)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -2607,6 +2610,14 @@ packages:
|
|||||||
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@playwright/test@1.62.1:
|
||||||
|
resolution: {integrity: sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
playwright: 1.62.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@protobufjs/aspromise@1.1.2:
|
/@protobufjs/aspromise@1.1.2:
|
||||||
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -7682,6 +7693,14 @@ packages:
|
|||||||
/fs.realpath@1.0.0:
|
/fs.realpath@1.0.0:
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
|
|
||||||
|
/fsevents@2.3.2:
|
||||||
|
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||||
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
/fsevents@2.3.3:
|
/fsevents@2.3.3:
|
||||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
@@ -10098,6 +10117,22 @@ packages:
|
|||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/playwright-core@1.62.1:
|
||||||
|
resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/playwright@1.62.1:
|
||||||
|
resolution: {integrity: sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
playwright-core: 1.62.1
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/plist@3.1.0:
|
/plist@3.1.0:
|
||||||
resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
|
resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
|
||||||
engines: {node: '>=10.4.0'}
|
engines: {node: '>=10.4.0'}
|
||||||
|
|||||||
@@ -52,6 +52,10 @@
|
|||||||
"test:watch": {
|
"test:watch": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true
|
"persistent": true
|
||||||
|
},
|
||||||
|
"test:e2e": {
|
||||||
|
"cache": false,
|
||||||
|
"dependsOn": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user