229 lines
9.8 KiB
Markdown
229 lines
9.8 KiB
Markdown
---
|
|
id: "03-e2e-coverage"
|
|
title: "E2E coverage"
|
|
status: done
|
|
wave: 2
|
|
depends_on: ["01-contract-and-mapping"]
|
|
plan: "plan.md"
|
|
spec: "../../specs/plugins/requirements/plugin-nav-sidebar-footer.md"
|
|
---
|
|
|
|
# Task 03: E2E coverage
|
|
|
|
Prove the `insights` placement end to end through the real plugin install/boot
|
|
path: a real plugin registers an `insights` nav item, the real backend boots
|
|
it, and the real frontend renders it as a footer icon on desktop and a
|
|
Utilities row on a phone. Reuses the existing shared e2e fixture plugin
|
|
(`kandev-plugin-e2e`) and its existing `/plugins/e2e-hello` route/page — this
|
|
task adds a second nav-item registration pointing at that same page, not a
|
|
new page.
|
|
|
|
## Files to change
|
|
|
|
1. `apps/backend/cmd/plugin-fixture/fixture-package/ui/bundle.js` — directly
|
|
after the existing:
|
|
```js
|
|
registry.registerNavItem({
|
|
id: "e2e-hello",
|
|
label: "Hello E2E",
|
|
path: "/plugins/e2e-hello",
|
|
section: "main",
|
|
});
|
|
registry.registerRoute("/plugins/e2e-hello", PluginPage);
|
|
```
|
|
add a second registration:
|
|
```js
|
|
registry.registerNavItem({
|
|
id: "e2e-insights-tools",
|
|
label: "E2E Insights Tools",
|
|
path: "/plugins/e2e-hello",
|
|
section: "insights",
|
|
});
|
|
```
|
|
No new route: both nav items point at the existing `PluginPage`.
|
|
|
|
2. Repackage the fixture so the tar.gz every e2e spec installs from includes
|
|
the new bundle:
|
|
```
|
|
cd apps/backend && make e2e-plugin-package
|
|
```
|
|
This overwrites `apps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz`. Do
|
|
not hand-edit that file; only edit `bundle.js` and rebuild through the
|
|
Makefile target (see the target's comment in `apps/backend/Makefile` for
|
|
what it stages/builds/packs).
|
|
|
|
3. `apps/web/e2e/tests/plugins/plugins.spec.ts` — add one new `test(...)`
|
|
inside the existing `test.describe("Plugins — gRPC plugin
|
|
install/load/live-update/uninstall", ...)` block (its `afterEach` already
|
|
uninstalls via API, so a fresh test here does not need its own cleanup).
|
|
Reuse the file's `openInstallDialog`/`uploadPackage` helpers:
|
|
```ts
|
|
test("registers an insights-section item as a footer icon, not a rail row", async ({ testPage }) => {
|
|
await openInstallDialog(testPage);
|
|
await uploadPackage(testPage, PACKAGE_PATH);
|
|
await expect(testPage.getByTestId(`plugin-row-${PLUGIN_ID}`)).toBeVisible({ timeout: 15_000 });
|
|
await testPage.goto("/");
|
|
await testPage.reload();
|
|
|
|
const footerButton = testPage.getByTestId(
|
|
`sidebar-plugin:${PLUGIN_ID}:e2e-insights-tools-button`,
|
|
);
|
|
await expect(footerButton).toBeVisible({ timeout: 15_000 });
|
|
await expect(footerButton).toHaveAccessibleName("E2E Insights Tools");
|
|
await footerButton.click();
|
|
await expect(testPage).toHaveURL(/\/plugins\/e2e-hello$/);
|
|
|
|
await expect(testPage.getByTestId("plugin-nav-item-e2e-insights-tools")).toHaveCount(0);
|
|
});
|
|
```
|
|
Adjust the exact locator/assertion API to match what the rest of the file
|
|
already uses (e.g. confirm `toHaveAccessibleName` is used elsewhere or use
|
|
the row's `getByRole("button", { name: "E2E Insights Tools" })` form
|
|
instead, matching this repo's existing footer-button assertions in
|
|
`app-sidebar-footer.test.tsx`).
|
|
|
|
4. `apps/web/e2e/tests/plugins/mobile-plugin-nav.spec.ts` — add one new
|
|
`test(...)` inside the existing `test.describe("Mobile plugin
|
|
navigation", ...)` block, following the file's existing inline install
|
|
pattern (goto `/settings/plugins`, install via upload tab, wait for the
|
|
plugin row, `goto("/")`, `reload()`, open the menu sheet):
|
|
```ts
|
|
test("shows the insights item in the Utilities group, not the Plugins group", async ({ testPage }) => {
|
|
await testPage.goto("/settings/plugins");
|
|
await testPage.getByTestId("install-plugin-trigger").click();
|
|
await testPage.getByTestId("install-plugin-tab-upload").click();
|
|
await testPage.getByTestId("install-plugin-file-input").setInputFiles(PACKAGE_PATH);
|
|
await testPage.getByTestId("install-plugin-upload-submit").click();
|
|
await expect(testPage.getByTestId(`plugin-row-${PLUGIN_ID}`)).toBeVisible({ timeout: 30_000 });
|
|
|
|
await testPage.goto("/");
|
|
await testPage.reload();
|
|
await testPage.getByRole("button", { name: "Open menu" }).click();
|
|
|
|
const utilitiesRow = testPage.getByRole("link", { name: "E2E Insights Tools" });
|
|
await expect(utilitiesRow).toBeVisible();
|
|
|
|
const pluginsGroup = testPage.getByTestId("mobile-plugin-nav-section");
|
|
await expect(pluginsGroup.getByText("E2E Insights Tools")).toHaveCount(0);
|
|
});
|
|
```
|
|
The file's existing `afterEach` already deletes the plugin via API, so no
|
|
extra cleanup is needed. Adjust the exact "open menu" locator to match
|
|
whatever the file's existing tests already use for that button.
|
|
|
|
## Acceptance
|
|
|
|
- `apps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz` is rebuilt and contains
|
|
the second nav-item registration (verify via
|
|
`tar -xOzf apps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz ui/bundle.js | grep e2e-insights-tools`
|
|
or equivalent).
|
|
- The new desktop test in `plugins.spec.ts` and the new mobile test in
|
|
`mobile-plugin-nav.spec.ts` pass.
|
|
- No existing test in either file (or in `plugins-docs-screenshots.spec.ts`,
|
|
which references the same fixture by `NAV_ITEM_ID`/`PLUGIN_ROUTE`) breaks —
|
|
the new registration is additive and does not change `e2e-hello`'s id,
|
|
label, or route.
|
|
|
|
## Verification
|
|
|
|
```
|
|
cd apps/backend && make e2e-plugin-package
|
|
cd apps/web && pnpm install --frozen-lockfile && pnpm e2e:raw e2e/tests/plugins/plugins.spec.ts e2e/tests/plugins/mobile-plugin-nav.spec.ts e2e/tests/plugins/plugins-docs-screenshots.spec.ts
|
|
```
|
|
|
|
## Files likely touched
|
|
|
|
- `apps/backend/cmd/plugin-fixture/fixture-package/ui/bundle.js`
|
|
- `apps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz` (generated artifact,
|
|
rebuilt not hand-edited)
|
|
- `apps/web/e2e/tests/plugins/plugins.spec.ts`
|
|
- `apps/web/e2e/tests/plugins/mobile-plugin-nav.spec.ts`
|
|
|
|
## Dependencies
|
|
|
|
01-contract-and-mapping (the fixture's `section: "insights"` registration only
|
|
renders in the footer/Utilities group once `pluginDestinations()` maps it
|
|
there).
|
|
|
|
## Parallelism
|
|
|
|
parallel-safe with 02-frontend-regression-coverage — disjoint files (this task
|
|
touches the Go fixture bundle, its packaged artifact, and Playwright spec
|
|
files under `apps/web/e2e/**`; task 02 touches only unit test files under
|
|
`apps/web/components/**`).
|
|
|
|
## Inputs
|
|
|
|
- Spec **Scenarios**: the desktop footer/rail-exclusion scenario and the
|
|
phone Utilities/Plugins-group scenario.
|
|
- Spec **Rendered identity**: the footer testid format
|
|
`sidebar-plugin:<pluginId>:<itemId>-button`, and that phone Utilities rows
|
|
carry no `data-testid` (select by visible label there, as the new mobile
|
|
test does).
|
|
- `apps/backend/cmd/plugin-fixture/fixture-package/ui/bundle.js`'s existing
|
|
`e2e-hello` registration as the direct template.
|
|
- `apps/web/e2e/tests/plugins/plugins.spec.ts`'s `openInstallDialog`/
|
|
`uploadPackage` helpers and shared `afterEach`.
|
|
- `apps/web/e2e/tests/plugins/mobile-plugin-nav.spec.ts`'s existing inline
|
|
install pattern (no shared helper in that file today).
|
|
|
|
## Output contract
|
|
|
|
Summary of the fixture change, the repackage step's output, both new tests,
|
|
files touched, exact commands run with outcomes (including the `tar`
|
|
verification), and any blockers (e.g. a local platform-specific build issue
|
|
with `make e2e-plugin-package`). Update this file's `status` to `done` and
|
|
this plan's Wave 2 checkbox and **Verification Results** section in the same
|
|
change.
|
|
|
|
## Results
|
|
|
|
Added a second `registry.registerNavItem({ id: "e2e-insights-tools", label:
|
|
"E2E Insights Tools", path: "/plugins/e2e-hello", section: "insights" })` call
|
|
to `apps/backend/cmd/plugin-fixture/fixture-package/ui/bundle.js`, right after
|
|
the existing `e2e-hello` registration, reusing the same `PluginPage`/route.
|
|
|
|
Rebuilt the fixture package and verified the new registration made it into
|
|
the artifact:
|
|
```
|
|
cd apps/backend && make e2e-plugin-package
|
|
tar -xOzf apps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz ui/bundle.js | grep -A5 e2e-insights-tools
|
|
```
|
|
confirmed the `section: "insights"` registration is present in the packaged
|
|
bundle.
|
|
|
|
Added one test to `apps/web/e2e/tests/plugins/plugins.spec.ts` ("registers an
|
|
insights-section item as a footer icon, not a rail row") and one to
|
|
`apps/web/e2e/tests/plugins/mobile-plugin-nav.spec.ts` ("shows the insights
|
|
item in the Utilities group, not the Plugins group"), both inside their
|
|
files' existing `test.describe` blocks per the plan.
|
|
|
|
Built the binaries/artifacts `e2e/global-setup.ts` requires (none existed
|
|
yet in this worktree):
|
|
```
|
|
make build-backend # apps/backend/bin/{kandev,mock-agent,...}
|
|
make build-web-e2e # apps/web/dist/ (pseudo-locale build)
|
|
```
|
|
|
|
Ran, from `apps/web`:
|
|
- `pnpm e2e:raw e2e/tests/plugins/plugins.spec.ts --project=chromium` — **12
|
|
passed** (all pre-existing tests plus the new one), 51.0s.
|
|
- `pnpm e2e:raw e2e/tests/plugins/mobile-plugin-nav.spec.ts --project=mobile-chrome`
|
|
— **5 passed** (all pre-existing tests plus the new one), 24.0s.
|
|
- `pnpm e2e:raw e2e/tests/plugins/plugins-docs-screenshots.spec.ts --project=chromium`
|
|
— 2 skipped (gated behind a capture flag not set in this run; pre-existing,
|
|
unrelated to this change — confirms nothing crashed loading that spec with
|
|
the new fixture bundle).
|
|
- `pnpm run lint -- e2e/tests/plugins/plugins.spec.ts e2e/tests/plugins/mobile-plugin-nav.spec.ts`
|
|
— 0 errors, 0 warnings.
|
|
- `pnpm run typecheck` (apps/web) — clean.
|
|
|
|
No teardown needed beyond what the suites already do themselves (each test's
|
|
plugin install is cleaned up by the files' existing `afterEach`/backend reset).
|
|
No security/trust or external side-effect boundaries beyond the existing
|
|
plugin-install flow the other tests in these files already exercise.
|
|
|
|
Files touched matched **Files likely touched** exactly (plus the two build
|
|
artifacts `apps/backend/bin/*` and `apps/web/dist/*`, which are gitignored
|
|
build output, not tracked changes).
|