9.8 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec | |
|---|---|---|---|---|---|---|---|
| 03-e2e-coverage | E2E coverage | done | 2 |
|
plan.md | ../../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
-
apps/backend/cmd/plugin-fixture/fixture-package/ui/bundle.js— directly after the existing:registry.registerNavItem({ id: "e2e-hello", label: "Hello E2E", path: "/plugins/e2e-hello", section: "main", }); registry.registerRoute("/plugins/e2e-hello", PluginPage);add a second registration:
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. -
Repackage the fixture so the tar.gz every e2e spec installs from includes the new bundle:
cd apps/backend && make e2e-plugin-packageThis overwrites
apps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz. Do not hand-edit that file; only editbundle.jsand rebuild through the Makefile target (see the target's comment inapps/backend/Makefilefor what it stages/builds/packs). -
apps/web/e2e/tests/plugins/plugins.spec.ts— add one newtest(...)inside the existingtest.describe("Plugins — gRPC plugin install/load/live-update/uninstall", ...)block (itsafterEachalready uninstalls via API, so a fresh test here does not need its own cleanup). Reuse the file'sopenInstallDialog/uploadPackagehelpers: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
toHaveAccessibleNameis used elsewhere or use the row'sgetByRole("button", { name: "E2E Insights Tools" })form instead, matching this repo's existing footer-button assertions inapp-sidebar-footer.test.tsx). -
apps/web/e2e/tests/plugins/mobile-plugin-nav.spec.ts— add one newtest(...)inside the existingtest.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):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
afterEachalready 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.gzis rebuilt and contains the second nav-item registration (verify viatar -xOzf apps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz ui/bundle.js | grep e2e-insights-toolsor equivalent).- The new desktop test in
plugins.spec.tsand the new mobile test inmobile-plugin-nav.spec.tspass. - No existing test in either file (or in
plugins-docs-screenshots.spec.ts, which references the same fixture byNAV_ITEM_ID/PLUGIN_ROUTE) breaks — the new registration is additive and does not changee2e-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.jsapps/backend/.build/kandev-plugin-e2e-1.0.0.tar.gz(generated artifact, rebuilt not hand-edited)apps/web/e2e/tests/plugins/plugins.spec.tsapps/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 nodata-testid(select by visible label there, as the new mobile test does). apps/backend/cmd/plugin-fixture/fixture-package/ui/bundle.js's existinge2e-helloregistration as the direct template.apps/web/e2e/tests/plugins/plugins.spec.ts'sopenInstallDialog/uploadPackagehelpers and sharedafterEach.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).