Skip to content

Commit 3095bc3

Browse files
author
Conduction Release Bot
committed
fix(e2e): assert the dashboard that exists, and stop pinning English on a Dutch instance
development E2E has been red for a day with six failures in two clusters. Both are the suite describing a world the app left behind. Neither was introduced by the icon work merged earlier today; the same six fail on the 08-31 21:06 run, checked. ## dashboard.spec.ts, three tests They assert an info box: the sentence "Overzicht van uw softwarecatalogus", a heading "Beheer van Organisaties", a "Vernieuwen" button on the surface and a "Ga naar Organisaties" quick-nav. None of that string set exists anywhere in src/ or l10n/nl.json any more. The dashboard is now four stat tiles plus the catalog-panels widget, since the KPI tiles landed in #892, and the spec was never updated. - the overview test now asserts the four tiles and the object-statistics panel; - the refresh test now opens the PAGE ACTIONS menu, where CnDashboardPage puts Refresh (showRefresh defaults true), instead of looking for a button on the surface; - the "Ga naar Organisaties" test is REMOVED rather than retargeted. Its own comment already recorded that the button was a no-op in the shared shell and that the user real path is the Organisations nav entry, which is the very next test in the file. Rewriting it would have tested that path twice while pretending to cover a control that no longer exists. ⚠️ The tile labels are asserted in DUTCH, and they are not all the manifest source. The manifest says "Services"; nl.json maps it to "Diensten". An English assertion would pass only on an English instance. ## sbom-import.spec.ts, two tests await page.getByRole("tab", { name: "Components" }).click() The manifest labels that tab "Components" and nl.json maps it to "Componenten". The e2e instance runs Dutch, so the tab never matched and both tests died on a 60s click timeout that reads like a missing feature rather than a wrong string. The matcher now accepts either spelling, as does the "Open sidebar" button above it. 🔑 The underlying debt is that this suite mixes locales: the dashboard tests asserted Dutch, the sbom tests asserted English, against one Dutch instance. Locale-tolerant matchers are the cheap fix; a decided convention is the real one.
1 parent fc0aeee commit 3095bc3

2 files changed

Lines changed: 61 additions & 53 deletions

File tree

tests/e2e/sbom-import.spec.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,18 @@ async function openComponentsTab(page: Page): Promise<void> {
122122
// The detail page mounts with its right-hand sidebar collapsed, and the
123123
// Components / History tabs live INSIDE that sidebar — present in the DOM but
124124
// not visible, so a direct tab click waits forever. Open the sidebar first.
125-
const openSidebar = page.getByRole('button', { name: 'Open sidebar' })
125+
const openSidebar = page.getByRole('button', {
126+
name: /Open sidebar|Zijbalk openen/i,
127+
})
126128
if (await openSidebar.isVisible().catch(() => false)) {
127129
await openSidebar.click()
128130
}
129-
await page.getByRole('tab', { name: 'Components' }).click()
131+
// The e2e instance runs DUTCH. The manifest labels this tab "Components"
132+
// and l10n/nl.json maps it to "Componenten", so pinning the English source
133+
// waits for a tab that never appears and the test dies on a 60s timeout
134+
// that reads like a missing feature. Matching either spelling keeps the
135+
// spec honest on both locales.
136+
await page.getByRole('tab', { name: /Components|Componenten/i }).click()
130137
}
131138

132139
// ---------------------------------------------------------------------------

tests/e2e/spec-coverage/dashboard.spec.ts

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -19,83 +19,84 @@ import {
1919
APP_MAIN,
2020
} from './_helpers'
2121

22-
test('dashboard: renders the overview surface (info box, refresh, statistics tables)', async ({
22+
test('dashboard: renders the overview surface (stat tiles and the object statistics panel)', async ({
2323
page,
2424
}) => {
2525
const bag = collectAppErrors(page)
2626
await gotoAppRoute(page, '/')
2727
const main = page.locator(APP_MAIN).first()
2828

29-
// Page intro / info-box widget content.
29+
// The dashboard is four stat tiles plus the catalog-panels widget. It used
30+
// to be an info box with an intro sentence and a "Beheer van Organisaties"
31+
// heading; that surface was replaced when the KPI tiles landed, and this
32+
// spec kept asserting the old one.
33+
//
34+
// Labels are asserted in DUTCH because the e2e instance runs Dutch, and
35+
// they are NOT all identical to the manifest source: the manifest says
36+
// "Services" and nl.json maps it to "Diensten". Asserting the English
37+
// source here would pass only on an English instance.
38+
for (const label of ['Organisaties', 'Modules', 'Diensten', 'Contracten']) {
39+
await expect(
40+
main.getByText(label, { exact: false }).first(),
41+
`the ${label} stat tile must render`,
42+
).toBeVisible({ timeout: 30000 })
43+
}
44+
3045
await expect(
31-
main
32-
.getByText('Overzicht van uw softwarecatalogus', { exact: false })
33-
.first(),
46+
main.getByText('Object statistieken', { exact: false }).first(),
47+
'the object statistics panel must render',
3448
).toBeVisible({ timeout: 30000 })
35-
await expect(
36-
main.getByRole('heading', { name: 'Beheer van Organisaties' }).first(),
37-
).toBeVisible()
38-
39-
// Refresh action is present and clickable (drives refreshAllData).
40-
const refresh = main.getByRole('button', { name: 'Vernieuwen' }).first()
41-
await expect(refresh).toBeVisible()
42-
await expect(refresh).toBeEnabled()
43-
44-
// The statistics overview renders as object-type count tables (two grids).
45-
// At least one statistics table is present in the rendered dashboard.
46-
await expect(main.locator('table').first()).toBeVisible({ timeout: 30000 })
4749

4850
expectNoAppErrors(bag)
4951
})
5052

51-
test('dashboard: "Vernieuwen" refresh re-runs the data load without error', async ({
53+
test('dashboard: the refresh action re-runs the data load without error', async ({
5254
page,
5355
}) => {
5456
const bag = collectAppErrors(page)
5557
await gotoAppRoute(page, '/')
5658
const main = page.locator(APP_MAIN).first()
5759

58-
const refresh = main.getByRole('button', { name: 'Vernieuwen' }).first()
59-
await expect(refresh).toBeEnabled()
60+
// Refresh is NOT a button on the surface. CnDashboardPage puts it in the
61+
// page actions menu, where showRefresh defaults to true, so it is reached
62+
// by opening that menu and clicking the item.
63+
//
64+
// The label is matched loosely on purpose: it comes from the nextcloud-vue
65+
// catalogue rather than this app's, so pinning one spelling would couple
66+
// this spec to the library's translations.
67+
const actions = main
68+
.getByRole('button', { name: /Acties|Actions|Meer|More/i })
69+
.first()
70+
await expect(actions, 'the page actions menu must be offered').toBeVisible({
71+
timeout: 30000,
72+
})
73+
await actions.click()
74+
75+
const refresh = page
76+
.locator('.v-popper__popper--shown')
77+
.last()
78+
.getByRole('menuitem', { name: /Vernieuwen|Refresh/i })
79+
.first()
80+
await expect(refresh, 'the actions menu must offer Refresh').toBeVisible({
81+
timeout: 15000,
82+
})
6083
await refresh.click()
6184

62-
// After refresh the dashboard surface is still intact (info-box heading).
85+
// The surface is still intact after the reload.
6386
await expect(
64-
main.getByRole('heading', { name: 'Beheer van Organisaties' }).first(),
87+
main.getByText('Organisaties', { exact: false }).first(),
6588
).toBeVisible({ timeout: 30000 })
6689

6790
expectNoAppErrors(bag)
6891
})
6992

70-
// The info-box "Ga naar Organisaties" button calls
71-
// navigationStore.setSelected('organisaties'). In the deployed manifest shell
72-
// this updates the navigation store but does NOT swap the page URL or the main
73-
// content region (see BUG LIST: the dashboard quick-nav button is a no-op in the
74-
// shared CnAppRoot shell — the user's working path is the "Organisations" nav
75-
// entry, covered separately). We therefore assert the button is a real,
76-
// clickable control and that clicking it leaves the app in a healthy state with
77-
// no stackiq-origin error — rather than asserting a navigation the
78-
// deployed shell does not perform.
79-
test('dashboard: "Ga naar Organisaties" quick-nav button is clickable and error-free', async ({
80-
page,
81-
}) => {
82-
const bag = collectAppErrors(page)
83-
await gotoAppRoute(page, '/')
84-
const main = page.locator(APP_MAIN).first()
85-
86-
const goButton = main
87-
.getByRole('button', { name: 'Ga naar Organisaties' })
88-
.first()
89-
await expect(goButton).toBeVisible({ timeout: 30000 })
90-
await expect(goButton).toBeEnabled()
91-
await goButton.click()
92-
93-
// App stays healthy after the click (dashboard surface still rendered).
94-
await expect(
95-
main.getByRole('heading', { name: 'Beheer van Organisaties' }).first(),
96-
).toBeVisible({ timeout: 30000 })
97-
expectNoAppErrors(bag)
98-
})
93+
// The "Ga naar Organisaties" quick-nav test is deliberately gone rather than
94+
// retargeted. It asserted a button inside the old info box, and that whole
95+
// surface was replaced by the KPI tiles. Its own comment already recorded that
96+
// the button was a no-op in the shared shell and that "the user's working path
97+
// is the Organisations nav entry, covered separately" — which is the test
98+
// immediately below. Keeping a rewritten version would re-test that same path
99+
// twice while pretending to cover a control that no longer exists.
99100

100101
// The organisaties index is genuinely reachable via the real app nav entry
101102
// "Organisations" — this is the user's actual navigation path and lands on the

0 commit comments

Comments
 (0)