From b077244009d43849049c94660224bafdcd1628fd Mon Sep 17 00:00:00 2001 From: Vivswan Shah <58091053+Vivswan@users.noreply.github.com> Date: Tue, 22 Sep 2026 05:20:22 -0400 Subject: [PATCH] chore: drop dead e2e fixtures, fix stale comments, and pin the merge-scenario timeouts Twelve of the fourteen JSON files under test/e2e/fixtures are imported by nothing; only org.json and repo.json feed the mock state, so the other twelve go. Four comments named a dependabot-bun-lockfile workflow that exists nowhere; the ones in nightly.yml and package-pins.test.ts now credit the from-scratch resolve to nightly's float-canary, the only one in this repository. The _typos.toml glob comment still placed unit tests under src/sections; they all live under test/ now. The four 300-seed genMergeScenario batteries ran on bun's 5 s default while their sibling had 20 s; one MERGE_TIMEOUT constant now covers all five, and biome reflows the widened calls. --- .github/workflows/nightly.yml | 27 +-- _typos.toml | 2 +- test/e2e/fixtures/actions-permissions.json | 19 -- test/e2e/fixtures/autolink.json | 6 - test/e2e/fixtures/branch-protection.json | 74 ------ .../fixtures/code-scanning-default-setup.json | 10 - test/e2e/fixtures/collaborator.json | 19 -- test/e2e/fixtures/environment.json | 54 ----- test/e2e/fixtures/label.json | 9 - test/e2e/fixtures/milestone.json | 24 -- test/e2e/fixtures/pages.json | 21 -- test/e2e/fixtures/ruleset.json | 46 ---- test/e2e/fixtures/team-repo.json | 30 --- test/e2e/fixtures/workflow.json | 12 - test/e2e/generators.test.ts | 217 ++++++++++-------- test/package-pins.test.ts | 6 +- 16 files changed, 137 insertions(+), 439 deletions(-) delete mode 100644 test/e2e/fixtures/actions-permissions.json delete mode 100644 test/e2e/fixtures/autolink.json delete mode 100644 test/e2e/fixtures/branch-protection.json delete mode 100644 test/e2e/fixtures/code-scanning-default-setup.json delete mode 100644 test/e2e/fixtures/collaborator.json delete mode 100644 test/e2e/fixtures/environment.json delete mode 100644 test/e2e/fixtures/label.json delete mode 100644 test/e2e/fixtures/milestone.json delete mode 100644 test/e2e/fixtures/pages.json delete mode 100644 test/e2e/fixtures/ruleset.json delete mode 100644 test/e2e/fixtures/team-repo.json delete mode 100644 test/e2e/fixtures/workflow.json diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 47660015..70231b15 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -4,10 +4,12 @@ # # Each job fails a night instead of surprising a later PR: checks runs the # schema lockstep tests and the typecheck against the latest Octokit -# packages, float-canary re-resolves the lockfile from scratch like the -# Dependabot lockfile workflow, and e2e runs the curated corpus with the -# endpoint-coverage tripwire. The report job files one tracking issue on a -# red night and closes it on a green one (the platform's docs/nightly.md). +# packages, float-canary deletes bun.lock and re-resolves from scratch so a +# breaking transitive release fails a night instead of the next from-scratch +# install, and e2e runs the curated corpus with the endpoint-coverage +# tripwire. +# The report job files one tracking issue on a red night and closes it on a +# green one (the platform's docs/nightly.md). name: Nightly on: @@ -86,12 +88,11 @@ jobs: exit 1 fi - # Predicts what the dependabot-bun-lockfile workflow's from-scratch resolve - # will hand the next Dependabot PR: package.json is pinned exactly (the - # package-pins test guards that), so only transitive ranges can float, and - # a float that breaks the gate fails here first. Its own job because the - # checks job's @octokit/types probe leaves node_modules upgraded, and this - # probe needs a clean tree to re-resolve from. + # The only from-scratch resolve in this repository: package.json is pinned + # exactly (the package-pins test guards that), so only transitive ranges + # can float, and a float that breaks the gate fails here first. Its own + # job because the checks job's @octokit/types probe leaves node_modules + # upgraded, and this probe needs a clean tree to re-resolve from. float-canary: runs-on: ubuntu-latest timeout-minutes: 15 @@ -101,9 +102,9 @@ jobs: - uses: ./.github/actions/setup with: install: "false" - # Delete before resolving, exactly like the Dependabot workflow: bun - # keeps a stale lockfile as a valid resolution, and only a - # from-scratch resolve floats what that workflow would float. + # Delete before resolving: bun keeps a stale lockfile as a valid + # resolution, and only a from-scratch resolve floats every transitive + # range. - name: Re-resolve from scratch run: | rm bun.lock diff --git a/_typos.toml b/_typos.toml index 4cfbc650..e2fae14f 100644 --- a/_typos.toml +++ b/_typos.toml @@ -48,7 +48,7 @@ alikes = "alikes" # matches type globs against the file NAME, never the path, hence these shapes. [type.fixtures] extend-glob = [ - "*.test.ts", # unit tests under test/ and src/sections/*/ + "*.test.ts", # unit tests under test/ "generators.ts", # the fuzz generators (test/e2e and the per-section fragments) "*-rejected.yml", # e2e scenarios whose input is rejected on purpose ] diff --git a/test/e2e/fixtures/actions-permissions.json b/test/e2e/fixtures/actions-permissions.json deleted file mode 100644 index 2684b033..00000000 --- a/test/e2e/fixtures/actions-permissions.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "permissions": { - "enabled": true, - "allowed_actions": "selected", - "selected_actions_url": "https://api.github.com/repos/e2e-owner/e2e-repo/actions/permissions/selected-actions" - }, - "selected_actions": { - "github_owned_allowed": true, - "verified_allowed": false, - "patterns_allowed": ["monalisa/octocat@*", "docker/*"] - }, - "workflow_permissions": { - "default_workflow_permissions": "read", - "can_approve_pull_request_reviews": false - }, - "access": { - "access_level": "none" - } -} diff --git a/test/e2e/fixtures/autolink.json b/test/e2e/fixtures/autolink.json deleted file mode 100644 index 0a8b7849..00000000 --- a/test/e2e/fixtures/autolink.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "id": 3438996, - "is_alphanumeric": true, - "key_prefix": "TICKET-", - "url_template": "https://example.com/TICKET?query=" -} diff --git a/test/e2e/fixtures/branch-protection.json b/test/e2e/fixtures/branch-protection.json deleted file mode 100644 index 7cdc8043..00000000 --- a/test/e2e/fixtures/branch-protection.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection", - "required_status_checks": { - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/required_status_checks", - "strict": true, - "contexts": ["all-green"], - "checks": [{ "context": "all-green", "app_id": null }], - "contexts_url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/required_status_checks/contexts" - }, - "enforce_admins": { - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/enforce_admins", - "enabled": true - }, - "required_pull_request_reviews": { - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/required_pull_request_reviews", - "dismissal_restrictions": { - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/dismissal_restrictions", - "users_url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/dismissal_restrictions/users", - "teams_url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/dismissal_restrictions/teams", - "users": [ - { - "login": "e2e-maintainer", - "id": 101, - "node_id": "MDQ6VXNlcjEwMQ==", - "type": "User", - "site_admin": false - } - ], - "teams": [ - { - "id": 201, - "node_id": "MDQ6VGVhbTIwMQ==", - "name": "Reviewers", - "slug": "reviewers", - "permission": "push" - } - ], - "apps": [] - }, - "bypass_pull_request_allowances": { - "users": [], - "teams": [], - "apps": [] - }, - "dismiss_stale_reviews": true, - "require_code_owner_reviews": false, - "required_approving_review_count": 1, - "require_last_push_approval": false - }, - "restrictions": { - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/restrictions", - "users_url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/restrictions/users", - "teams_url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/restrictions/teams", - "apps_url": "https://api.github.com/repos/e2e-owner/e2e-repo/branches/main/protection/restrictions/apps", - "users": [], - "teams": [ - { - "id": 201, - "node_id": "MDQ6VGVhbTIwMQ==", - "name": "Reviewers", - "slug": "reviewers", - "permission": "push" - } - ], - "apps": [] - }, - "required_linear_history": { "enabled": true }, - "allow_force_pushes": { "enabled": false }, - "allow_deletions": { "enabled": false }, - "block_creations": { "enabled": false }, - "required_conversation_resolution": { "enabled": true }, - "lock_branch": { "enabled": false }, - "allow_fork_syncing": { "enabled": false } -} diff --git a/test/e2e/fixtures/code-scanning-default-setup.json b/test/e2e/fixtures/code-scanning-default-setup.json deleted file mode 100644 index 984f0ed9..00000000 --- a/test/e2e/fixtures/code-scanning-default-setup.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "state": "configured", - "languages": ["javascript-typescript"], - "runner_type": "standard", - "runner_label": null, - "query_suite": "default", - "threat_model": "remote", - "updated_at": "2026-07-01T10:00:00Z", - "schedule": null -} diff --git a/test/e2e/fixtures/collaborator.json b/test/e2e/fixtures/collaborator.json deleted file mode 100644 index 3332a1cc..00000000 --- a/test/e2e/fixtures/collaborator.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "login": "e2e-collaborator", - "id": 303, - "node_id": "MDQ6VXNlcjMwMw==", - "avatar_url": "https://avatars.githubusercontent.com/u/303?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/e2e-collaborator", - "html_url": "https://github.com/e2e-collaborator", - "type": "User", - "site_admin": false, - "permissions": { - "admin": false, - "maintain": false, - "push": true, - "triage": false, - "pull": true - }, - "role_name": "write" -} diff --git a/test/e2e/fixtures/environment.json b/test/e2e/fixtures/environment.json deleted file mode 100644 index 45bcf6c8..00000000 --- a/test/e2e/fixtures/environment.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "id": 161088068, - "node_id": "MDExOkVudmlyb25tZW50MTYxMDg4MDY4", - "name": "production", - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/environments/production", - "html_url": "https://github.com/e2e-owner/e2e-repo/deployments/activity_log?environments_filter=production", - "created_at": "2024-06-01T22:00:40Z", - "updated_at": "2026-07-01T22:00:40Z", - "protection_rules": [ - { - "id": 3736, - "node_id": "MDQ6R2F0ZTM3MzY=", - "type": "wait_timer", - "wait_timer": 15 - }, - { - "id": 3755, - "node_id": "MDQ6R2F0ZTM3NTU=", - "type": "required_reviewers", - "prevent_self_review": true, - "reviewers": [ - { - "type": "User", - "reviewer": { - "login": "e2e-maintainer", - "id": 101, - "node_id": "MDQ6VXNlcjEwMQ==", - "type": "User", - "site_admin": false - } - }, - { - "type": "Team", - "reviewer": { - "id": 201, - "node_id": "MDQ6VGVhbTIwMQ==", - "name": "Reviewers", - "slug": "reviewers", - "permission": "push" - } - } - ] - }, - { - "id": 3756, - "node_id": "MDQ6R2F0ZTM3NTY=", - "type": "branch_policy" - } - ], - "deployment_branch_policy": { - "protected_branches": true, - "custom_branch_policies": false - } -} diff --git a/test/e2e/fixtures/label.json b/test/e2e/fixtures/label.json deleted file mode 100644 index 8d65e219..00000000 --- a/test/e2e/fixtures/label.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": 208045946, - "node_id": "MDU6TGFiZWwyMDgwNDU5NDY=", - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/labels/bug", - "name": "bug", - "color": "d73a4a", - "default": true, - "description": "Something isn't working" -} diff --git a/test/e2e/fixtures/milestone.json b/test/e2e/fixtures/milestone.json deleted file mode 100644 index 6c97ce05..00000000 --- a/test/e2e/fixtures/milestone.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/milestones/1", - "html_url": "https://github.com/e2e-owner/e2e-repo/milestones/v1.0", - "labels_url": "https://api.github.com/repos/e2e-owner/e2e-repo/milestones/1/labels", - "id": 1002003, - "node_id": "MDk6TWlsZXN0b25lMTAwMjAwMw==", - "number": 1, - "state": "open", - "title": "v1.0", - "description": "First stable release.", - "creator": { - "login": "e2e-maintainer", - "id": 101, - "node_id": "MDQ6VXNlcjEwMQ==", - "type": "User", - "site_admin": false - }, - "open_issues": 2, - "closed_issues": 5, - "created_at": "2024-06-01T09:00:00Z", - "updated_at": "2026-07-01T09:00:00Z", - "closed_at": null, - "due_on": "2026-12-31T08:00:00Z" -} diff --git a/test/e2e/fixtures/pages.json b/test/e2e/fixtures/pages.json deleted file mode 100644 index 51c647fb..00000000 --- a/test/e2e/fixtures/pages.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/pages", - "status": "built", - "cname": "docs.example.com", - "custom_404": false, - "html_url": "https://e2e-owner.github.io/e2e-repo/", - "build_type": "workflow", - "source": { - "branch": "main", - "path": "/" - }, - "public": true, - "https_certificate": { - "state": "approved", - "description": "Certificate is approved", - "domains": ["docs.example.com"] - }, - "https_enforced": true, - "protected_domain_state": null, - "pending_domain_unverified_at": null -} diff --git a/test/e2e/fixtures/ruleset.json b/test/e2e/fixtures/ruleset.json deleted file mode 100644 index f4654b1b..00000000 --- a/test/e2e/fixtures/ruleset.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": 42, - "name": "main-protection", - "target": "branch", - "source_type": "Repository", - "source": "e2e-owner/e2e-repo", - "enforcement": "active", - "node_id": "RRS_lACkUmVwbwTNBQZ80DBg", - "created_at": "2024-06-01T10:00:00Z", - "updated_at": "2026-07-01T10:00:00Z", - "conditions": { - "ref_name": { - "include": ["refs/heads/main"], - "exclude": [] - } - }, - "rules": [ - { "type": "deletion" }, - { "type": "non_fast_forward" }, - { - "type": "pull_request", - "parameters": { - "required_approving_review_count": 1, - "dismiss_stale_reviews_on_push": true, - "require_code_owner_review": false, - "require_last_push_approval": false, - "required_review_thread_resolution": false - } - } - ], - "bypass_actors": [ - { - "actor_id": 5, - "actor_type": "RepositoryRole", - "bypass_mode": "always" - } - ], - "_links": { - "self": { - "href": "https://api.github.com/repos/e2e-owner/e2e-repo/rulesets/42" - }, - "html": { - "href": "https://github.com/e2e-owner/e2e-repo/rules/42" - } - } -} diff --git a/test/e2e/fixtures/team-repo.json b/test/e2e/fixtures/team-repo.json deleted file mode 100644 index b6fb2d0c..00000000 --- a/test/e2e/fixtures/team-repo.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id": 500100200, - "node_id": "R_kgDOHdPQ2A", - "name": "e2e-repo", - "full_name": "e2e-owner/e2e-repo", - "private": false, - "owner": { - "login": "e2e-owner", - "id": 900800700, - "node_id": "O_kgDONjE1_A", - "type": "Organization", - "site_admin": false - }, - "html_url": "https://github.com/e2e-owner/e2e-repo", - "url": "https://api.github.com/repos/e2e-owner/e2e-repo", - "description": "End-to-end fixture repository for settings-as-code.", - "fork": false, - "default_branch": "main", - "visibility": "public", - "archived": false, - "disabled": false, - "permissions": { - "admin": false, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "role_name": "maintain" -} diff --git a/test/e2e/fixtures/workflow.json b/test/e2e/fixtures/workflow.json deleted file mode 100644 index 5a5a0eeb..00000000 --- a/test/e2e/fixtures/workflow.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "id": 161335, - "node_id": "MDg6V29ya2Zsb3cxNjEzMzU=", - "name": "CI", - "path": ".github/workflows/ci.yml", - "state": "active", - "created_at": "2024-01-15T10:00:00.000-08:00", - "updated_at": "2026-07-01T10:00:00.000-08:00", - "url": "https://api.github.com/repos/e2e-owner/e2e-repo/actions/workflows/161335", - "html_url": "https://github.com/e2e-owner/e2e-repo/blob/main/.github/workflows/ci.yml", - "badge_url": "https://github.com/e2e-owner/e2e-repo/workflows/CI/badge.svg" -} diff --git a/test/e2e/generators.test.ts b/test/e2e/generators.test.ts index 2f69422a..0b5e4328 100644 --- a/test/e2e/generators.test.ts +++ b/test/e2e/generators.test.ts @@ -1036,115 +1036,136 @@ describe("dead-corner knobs", () => { describe("genMergeScenario", () => { const SEEDS = Array.from({ length: 300 }, (_, i) => i); + // Each battery below runs hundreds of generator draws, the heaviest probing the validator per layer: near bun's 5 s default on a loaded runner. + const MERGE_TIMEOUT = 20_000; - test("produces schema-valid mode: render scenarios whose layers the runner files in meta order", () => { - for (const seed of SEEDS) { - const { scenario, meta } = genMergeScenario(new Rng(seed)); - expect(() => parseScenario(scenario, `seed-${seed}`)).not.toThrow(); - expect(scenario.inputs?.mode).toBe("render"); - expect(meta.layers.length).toBeGreaterThanOrEqual(2); - expect(meta.layers.length).toBeLessThanOrEqual(5); - // The runner writes settings_layers[i] as layer-i.yml and settings as settings.yml, the names the action's refusals and notices carry. - const below = scenario.settings_layers ?? []; - expect(below.length).toBe(meta.layers.length - 1); - below.forEach((doc, i) => { - expect(meta.layers[i]).toEqual({ name: `layer-${i}.yml`, doc }); - }); - expect(meta.layers[meta.layers.length - 1]).toEqual({ - name: "settings.yml", - doc: scenario.settings as Record, - }); - expect(meta.layering).toBe(scenario.inputs?.layering ?? "deep"); - } - }); - - test("the oracle's boundary read agrees with the generator's refusal intent, layer by layer", () => { - let refused = 0; - for (const seed of SEEDS) { - const { meta } = genMergeScenario(new Rng(seed)); - const prediction = predictMerge(meta); - if (meta.refusal === undefined) { - expect(prediction.kind, `seed ${seed}: an admitted stack read as refused`).not.toBe( - "refused", - ); - continue; + test( + "produces schema-valid mode: render scenarios whose layers the runner files in meta order", + () => { + for (const seed of SEEDS) { + const { scenario, meta } = genMergeScenario(new Rng(seed)); + expect(() => parseScenario(scenario, `seed-${seed}`)).not.toThrow(); + expect(scenario.inputs?.mode).toBe("render"); + expect(meta.layers.length).toBeGreaterThanOrEqual(2); + expect(meta.layers.length).toBeLessThanOrEqual(5); + // The runner writes settings_layers[i] as layer-i.yml and settings as settings.yml, the names the action's refusals and notices carry. + const below = scenario.settings_layers ?? []; + expect(below.length).toBe(meta.layers.length - 1); + below.forEach((doc, i) => { + expect(meta.layers[i]).toEqual({ name: `layer-${i}.yml`, doc }); + }); + expect(meta.layers[meta.layers.length - 1]).toEqual({ + name: "settings.yml", + doc: scenario.settings as Record, + }); + expect(meta.layering).toBe(scenario.inputs?.layering ?? "deep"); } - refused++; - expect(prediction, `seed ${seed}: ${meta.refusal.kind}`).toEqual({ - kind: "refused", - layer: meta.refusal.layer, - }); - } - expect(refused).toBeGreaterThan(20); - }); + }, + MERGE_TIMEOUT, + ); - test("a predicted merged document is valid and survives the YAML round trip the runner compares through", () => { - let merged = 0; - for (const seed of SEEDS) { - const { meta } = genMergeScenario(new Rng(seed)); - const prediction = predictMerge(meta); - if (prediction.kind !== "merged") { - continue; - } - merged++; - const verdict = validateSettingsDoc( - prediction.merged, - "merged", - SectionSelection.ALL, - silentIo(), - ); - expect("error" in verdict ? verdict.error : undefined, `seed ${seed}`).toBeUndefined(); - expect(parseYaml(stringifyYaml(prediction.merged))).toEqual(prediction.merged); - // The directives address the fold; none may reach the written document. - expect(prediction.merged._layering).toBeUndefined(); - for (const value of Object.values(prediction.merged)) { - if (typeof value === "object" && value !== null && !Array.isArray(value)) { - expect((value as Record)._layering).toBeUndefined(); + test( + "the oracle's boundary read agrees with the generator's refusal intent, layer by layer", + () => { + let refused = 0; + for (const seed of SEEDS) { + const { meta } = genMergeScenario(new Rng(seed)); + const prediction = predictMerge(meta); + if (meta.refusal === undefined) { + expect(prediction.kind, `seed ${seed}: an admitted stack read as refused`).not.toBe( + "refused", + ); + continue; } + refused++; + expect(prediction, `seed ${seed}: ${meta.refusal.kind}`).toEqual({ + kind: "refused", + layer: meta.refusal.layer, + }); } - } - expect(merged).toBeGreaterThan(150); - }); + expect(refused).toBeGreaterThan(20); + }, + MERGE_TIMEOUT, + ); - test("every merge feature and every refusal kind surfaces across seeds", () => { - const features = new Set(); - const refusals = new Set(); - for (const seed of SEEDS) { - const { meta } = genMergeScenario(new Rng(seed)); - for (const feature of meta.features) { - features.add(feature); - } - if (meta.refusal !== undefined) { - refusals.add(meta.refusal.kind); - expect(meta.features).toEqual(["refused"]); + test( + "a predicted merged document is valid and survives the YAML round trip the runner compares through", + () => { + let merged = 0; + for (const seed of SEEDS) { + const { meta } = genMergeScenario(new Rng(seed)); + const prediction = predictMerge(meta); + if (prediction.kind !== "merged") { + continue; + } + merged++; + const verdict = validateSettingsDoc( + prediction.merged, + "merged", + SectionSelection.ALL, + silentIo(), + ); + expect("error" in verdict ? verdict.error : undefined, `seed ${seed}`).toBeUndefined(); + expect(parseYaml(stringifyYaml(prediction.merged))).toEqual(prediction.merged); + // The directives address the fold; none may reach the written document. + expect(prediction.merged._layering).toBeUndefined(); + for (const value of Object.values(prediction.merged)) { + if (typeof value === "object" && value !== null && !Array.isArray(value)) { + expect((value as Record)._layering).toBeUndefined(); + } + } } - } - expect(MERGE_FEATURES.filter((feature) => !features.has(feature))).toEqual([]); - expect(MERGE_REFUSAL_KINDS.filter((kind) => !refusals.has(kind))).toEqual([]); - }); + expect(merged).toBeGreaterThan(150); + }, + MERGE_TIMEOUT, + ); - // 720 forced generator runs, each probing the validator per layer: ~1.4 s alone, near bun's 5 s default on a loaded runner. - test("forces construct their eligibility: a pinned run layering, or the named refusal", () => { - for (let seed = 0; seed < 60; seed++) { - for (const layering of LAYERING_DIRECTIVES) { - const { scenario, meta } = genMergeScenario(new Rng(seed), { - force: { kind: "valid", layering }, - }); - expect(scenario.inputs?.layering).toBe(layering); - expect(meta.refusal).toBeUndefined(); - // The whole point of the force: the battery compares a document. - expect(predictMerge(meta).kind, `seed ${seed} ${layering}`).toBe("merged"); + test( + "every merge feature and every refusal kind surfaces across seeds", + () => { + const features = new Set(); + const refusals = new Set(); + for (const seed of SEEDS) { + const { meta } = genMergeScenario(new Rng(seed)); + for (const feature of meta.features) { + features.add(feature); + } + if (meta.refusal !== undefined) { + refusals.add(meta.refusal.kind); + expect(meta.features).toEqual(["refused"]); + } } - for (const refusal of MERGE_REFUSAL_KINDS) { - const { meta } = genMergeScenario(new Rng(seed), { force: { kind: "refused", refusal } }); - if (meta.refusal === undefined) { - throw new Error(`seed ${seed}: the ${refusal} force produced no refused layer`); + expect(MERGE_FEATURES.filter((feature) => !features.has(feature))).toEqual([]); + expect(MERGE_REFUSAL_KINDS.filter((kind) => !refusals.has(kind))).toEqual([]); + }, + MERGE_TIMEOUT, + ); + + test( + "forces construct their eligibility: a pinned run layering, or the named refusal", + () => { + for (let seed = 0; seed < 60; seed++) { + for (const layering of LAYERING_DIRECTIVES) { + const { scenario, meta } = genMergeScenario(new Rng(seed), { + force: { kind: "valid", layering }, + }); + expect(scenario.inputs?.layering).toBe(layering); + expect(meta.refusal).toBeUndefined(); + // The whole point of the force: the battery compares a document. + expect(predictMerge(meta).kind, `seed ${seed} ${layering}`).toBe("merged"); + } + for (const refusal of MERGE_REFUSAL_KINDS) { + const { meta } = genMergeScenario(new Rng(seed), { force: { kind: "refused", refusal } }); + if (meta.refusal === undefined) { + throw new Error(`seed ${seed}: the ${refusal} force produced no refused layer`); + } + expect(meta.refusal.kind).toBe(refusal); + expect(predictMerge(meta)).toEqual({ kind: "refused", layer: meta.refusal.layer }); } - expect(meta.refusal.kind).toBe(refusal); - expect(predictMerge(meta)).toEqual({ kind: "refused", layer: meta.refusal.layer }); } - } - }, 20_000); + }, + MERGE_TIMEOUT, + ); test("honors the sections option", () => { const pool: SectionKey[] = ["labels", "rulesets", "milestones", "pages"]; diff --git a/test/package-pins.test.ts b/test/package-pins.test.ts index 7d8ba2a1..ee2a58e0 100644 --- a/test/package-pins.test.ts +++ b/test/package-pins.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; import pkg from "../package.json"; -// The managed dependabot-bun-lockfile workflow deletes bun.lock and re-resolves on every Dependabot PR, so a range specifier floats there untested -// against main (zod ^4.4.3 floating to 4.5.4 broke every open Dependabot PR at once). -// `bun add` writes "^" by default. +// A from-scratch `bun install` (nightly's float-canary) honors every range in package.json, so a range specifier floats there untested against +// main (zod ^4.4.3 floating to 4.5.4 broke every open Dependabot PR when a lockfile-regenerating workflow still existed). Exact pins leave only +// transitive ranges to float. `bun add` writes "^" by default. const EXACT_VERSION = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/; const DEPENDENCY_FIELDS = [