From bf2a8c1f23582e3d3b6a04f44039275322b73901 Mon Sep 17 00:00:00 2001 From: quality Date: Mon, 5 Oct 2026 23:47:47 -0400 Subject: [PATCH 1/2] test: cover GroupLinkStatus's plural arms and invalid-checkedAt guard src/components/GroupLinkStatus/index.js is the lowest-covered file in the end-to-end report at 60% of regions. Three of its four uncovered regions are reachable, and all three need a second build: * line 7, formatDate's Number.isNaN guard, needs a checkedAt that does not parse, which the real file never carries; * lines 32-33, the plural arms of the drift warning, need two groups drifting at once, while the ordinary coverage overlay appends exactly one archived group. Clearing checkedAt or emptying the list in the ordinary coverage build would swap which arm renders rather than add a case, so the overlay goes in tests/e2e/fixtures/data-variants/ and the variant site is asserted beside the real one. The appended group drifts through reachable:false rather than archived:true so the filter's second operand decides it, as a link-check run that cannot reach a repository produces. tests/e2e-data-fixtures.test.mjs used community-groups.json as the contrast case for a file with no variant overlay, which this makes false. case-studies.json takes that role: members.json is the other base-only overlay, but open PR #1104 adds a members.json variant, so it would stop being a contrast as soon as that lands. Verified by building both sites locally with npm run build:e2e:coverage and reading the rendered HTML. build/community: verification line dated "September 23, 2026", singular "has an archived or unreachable upstream repository", one group named, no plural. build/e2e-coverage-variant/ community: no verification line and no "Invalid Date", plural "have archived or unreachable upstream repositories", both groups named. The Playwright run itself was not executed here -- this sandbox has no browser (chrome-headless-shell cannot load libglib-2.0.so.0 and there is no root to install it), so CI is the first place the spec runs. Line 23's `|| []` is deliberately left uncovered: reaching it means clearing `groups` entirely, which stops the warning rendering at all. Signed-off-by: quality --- tests/e2e-data-fixtures.test.mjs | 10 ++ .../data-variants/community-groups.json | 17 +++ tests/e2e/group-link-status-variant.spec.js | 116 ++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 tests/e2e/fixtures/data-variants/community-groups.json create mode 100644 tests/e2e/group-link-status-variant.spec.js diff --git a/tests/e2e-data-fixtures.test.mjs b/tests/e2e-data-fixtures.test.mjs index 92ed1e35..881a97c3 100644 --- a/tests/e2e-data-fixtures.test.mjs +++ b/tests/e2e-data-fixtures.test.mjs @@ -326,7 +326,17 @@ test('a data file patched by both directories collects both overlays', () => { const groups = join(DATA_DIR, 'community-groups.json'); assert.deepEqual(overlayPathsFor(groups, { E2E_COVERAGE_VARIANT: '1' }), [ join(FIXTURE_DIR, 'community-groups.json'), + join(VARIANT_FIXTURE_DIR, 'community-groups.json'), ]); + // The contrast case: a file the ordinary coverage build overlays and the + // variant build has nothing to add to still collects one path, which is + // what proves the variant directory is consulted only when it has + // something to say rather than always appended. + const caseStudies = join(DATA_DIR, 'case-studies.json'); + assert.deepEqual( + overlayPathsFor(caseStudies, { E2E_COVERAGE_VARIANT: '1' }), + [join(FIXTURE_DIR, 'case-studies.json')], + ); }); // Both arms have to be reachable in one Playwright run, which is the whole diff --git a/tests/e2e/fixtures/data-variants/community-groups.json b/tests/e2e/fixtures/data-variants/community-groups.json new file mode 100644 index 00000000..eabfa177 --- /dev/null +++ b/tests/e2e/fixtures/data-variants/community-groups.json @@ -0,0 +1,17 @@ +{ + "description": "Appends a second drifted group and makes checkedAt unparseable, so GroupLinkStatus renders the plural arms of its drift warning (src/components/GroupLinkStatus/index.js lines 32-33) and takes formatDate's Number.isNaN guard at line 7. The ordinary coverage overlay appends exactly one archived group, so that build renders the singular grammar and the verification line; both arms are only reachable in one Playwright run because the variant build is served beside the real one. The appended group drifts through reachable:false rather than archived:true so the filter's second operand decides it, as a link-check run that cannot reach the repository produces.", + "set": { + "checkedAt": "not a timestamp" + }, + "append": { + "groups": [ + { + "slug": "e2e-coverage-unreachable", + "name": "Second Coverage Fixture User Group", + "repository": "https://github.com/cncf/endusers", + "archived": false, + "reachable": false + } + ] + } +} diff --git a/tests/e2e/group-link-status-variant.spec.js b/tests/e2e/group-link-status-variant.spec.js new file mode 100644 index 00000000..130203b5 --- /dev/null +++ b/tests/e2e/group-link-status-variant.spec.js @@ -0,0 +1,116 @@ +// End-to-end coverage for the plural arms of src/components/GroupLinkStatus/ +// index.js and for formatDate's invalid-date guard, which need a build of +// their own. +// +// The component reads data/community-groups.json at module scope and renders +// two things the checked-in corpus cannot vary: +// +// line 7 `if (Number.isNaN(parsed.getTime())) return null;` — formatDate +// returns null for a checkedAt that does not parse, which drops +// the "Upstream group links last verified on ..." line entirely; +// lines 32-33 `stale.length === 1 ? 'has an' : 'have'` and +// `stale.length === 1 ? 'repository' : 'repositories'` — the +// plural grammar of the drift warning. +// +// Neither is reachable against the data the site ships. Both real groups are +// archived:false / reachable:true, and tests/e2e/fixtures/data/ +// community-groups.json appends exactly one archived group, so the ordinary +// coverage build has `stale.length === 1` and always takes the singular arm. +// The real checkedAt is a valid ISO timestamp, so line 7 never returns. +// +// Two groups drifting at once is an ordinary shape rather than defensive dead +// code: `npm run check:community-group-links` sets `archived` and `reachable` +// on every group independently, so a run that finds two repositories gone is +// exactly what produces it. +// +// This is not a case tests/e2e/data-fixtures.spec.js can take. That file +// covers the branches an *additive* overlay reaches, where an extra record +// renders beside the real ones and nothing already covered stops rendering. +// Here the two arms of each ternary are mutually exclusive on one page, and +// clearing checkedAt removes the verification line that the ordinary build +// covers — so overlaying once would swap which arm is reachable rather than +// add a case. They belong to the variant build for the same reason +// AwardsTimeline's provenance paragraph does; see the preamble of +// tests/e2e/data-variants.spec.js for the mechanism. `npm run +// build:e2e:coverage` compiles a second site under /e2e-coverage-variant/ +// with tests/e2e/fixtures/data-variants/** layered on, one `docusaurus serve` +// offers both, and the report unions what each build reached. +// +// The real route is asserted alongside the variant one. On its own, an +// assertion that the variant page says "repositories" passes just as well +// when the page failed to build or the route is wrong; pairing it with the +// real route rendering "repository" is what makes the pair evidence that the +// arms *switched* rather than that one of them is all the site ever renders. +import { test, expect } from '../tools/e2e-coverage.cjs'; +import { loadSiteData } from '../tools/e2e-data-fixtures.cjs'; + +const COMMUNITY_PATH = '/community'; +const VARIANT_BASE = '/e2e-coverage-variant'; +const VERIFIED_LINE = /Upstream group links last verified on/; +const SINGULAR = /has an archived or unreachable upstream repository —/; +const PLURAL = /have archived or unreachable upstream repositories —/; + +// The variant site is only built by the coverage run; outside it the base +// path does not exist and the ordinary page still has a parseable checkedAt. +const describeCoverage = + process.env.E2E_COVERAGE === '1' ? test.describe : test.describe.skip; + +const COVERAGE_ENV = { E2E_COVERAGE: '1' }; +const VARIANT_ENV = { E2E_COVERAGE: '1', E2E_COVERAGE_VARIANT: '1' }; + +// Read the corpus through the overlays rather than hard-coding names or a +// count, so an edited overlay fails here instead of leaving a test that +// asserts nothing. +const isStale = (group) => group.archived || group.reachable === false; +const groups = loadSiteData('community-groups.json', COVERAGE_ENV); +const variantGroups = loadSiteData('community-groups.json', VARIANT_ENV); +const stale = groups.groups.filter(isStale); +const variantStale = variantGroups.groups.filter(isStale); + +describeCoverage('a link check that found more than one group drifting', () => { + test('the real page dates its verification line and uses the singular', async ({ + page, + }) => { + // The premise of the whole file: against the data the coverage build + // ships, both arms below are unreachable. + expect(stale).toHaveLength(1); + expect(new Date(groups.checkedAt).getTime()).not.toBeNaN(); + + await page.goto(COMMUNITY_PATH); + await expect(page.getByText(VERIFIED_LINE)).toBeVisible(); + const warning = page.getByText(SINGULAR); + await expect(warning).toBeVisible(); + await expect(warning).toContainText(stale[0].name); + await expect(page.getByText(PLURAL)).toHaveCount(0); + }); + + test('the variant page drops the verification line and uses the plural', async ({ + page, + }) => { + expect(variantStale.length).toBeGreaterThan(1); + // What line 7 turns on: the overlaid checkedAt is present but does not + // parse, so formatDate reaches its guard instead of returning early on a + // missing field. + expect(variantGroups.checkedAt).toBeTruthy(); + expect(new Date(variantGroups.checkedAt).getTime()).toBeNaN(); + + await page.goto(`${VARIANT_BASE}${COMMUNITY_PATH}`); + // The route built and served: the page's own heading is prose around the + // component, so it renders whether or not the corpus has anything to say. + await expect( + page.getByRole('heading', { name: 'Community', level: 1 }), + ).toBeVisible(); + // formatDate returned null, so the verification line is gone rather than + // rendering "Invalid Date". + await expect(page.getByText(VERIFIED_LINE)).toHaveCount(0); + await expect(page.getByText(/Invalid Date/)).toHaveCount(0); + const warning = page.getByText(PLURAL); + await expect(warning).toBeVisible(); + // Both drifted groups are named, which is what distinguishes the plural + // arm rendering from the list simply having changed. + for (const group of variantStale) { + await expect(warning).toContainText(group.name); + } + await expect(page.getByText(SINGULAR)).toHaveCount(0); + }); +}); From c5599463912c1878f97de0ede19951c1608ded17 Mon Sep 17 00:00:00 2001 From: mrbobbytables Date: Wed, 7 Oct 2026 07:57:44 -0500 Subject: [PATCH 2/2] test: move the no-variant contrast case to architectures/catalog.json case-studies.json gained a variant overlay in #1133, and members.json gains one in #1104; the architectures catalog is the remaining data file the ordinary coverage build overlays and the variant build does not. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables --- tests/e2e-data-fixtures.test.mjs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/e2e-data-fixtures.test.mjs b/tests/e2e-data-fixtures.test.mjs index 881a97c3..c3027a89 100644 --- a/tests/e2e-data-fixtures.test.mjs +++ b/tests/e2e-data-fixtures.test.mjs @@ -332,11 +332,10 @@ test('a data file patched by both directories collects both overlays', () => { // variant build has nothing to add to still collects one path, which is // what proves the variant directory is consulted only when it has // something to say rather than always appended. - const caseStudies = join(DATA_DIR, 'case-studies.json'); - assert.deepEqual( - overlayPathsFor(caseStudies, { E2E_COVERAGE_VARIANT: '1' }), - [join(FIXTURE_DIR, 'case-studies.json')], - ); + const catalog = join(DATA_DIR, 'architectures', 'catalog.json'); + assert.deepEqual(overlayPathsFor(catalog, { E2E_COVERAGE_VARIANT: '1' }), [ + join(FIXTURE_DIR, 'architectures', 'catalog.json'), + ]); }); // Both arms have to be reachable in one Playwright run, which is the whole