Skip to content

test: replace low-signal tests with behavior integrations - #51

Merged
yyyyaaa merged 4 commits into
mainfrom
phat/test-suite-behavior-audit
Oct 11, 2026
Merged

yyyyaaa merged 4 commits into
mainfrom
phat/test-suite-behavior-audit

Conversation

@yyyyaaa

@yyyyaaa yyyyaaa commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor
  • Replace low-signal unit tests with behavior coverage: remove 345 cases, add 23 public integration workflows, and retain 1,167 original contracts. The normal suite shrinks from 1,512 to 1,190 cases (21.3% fewer).
  • Remove source greps, implementation-shape assertions, duplicate lower-boundary checks and behavior-reimplementing mocks; delete 52 production lines supporting three unused Sheets test seams.
  • Update all seven billing E2E journeys for the current Account and Console UI, preserving lifecycle/readiness gates, host actions, refusal/recovery, keyboard accessibility, focus restoration and responsive layout.
  • Fix bugs those flows expose: ignored command events canceling invocations, stale loader results reaching a skipped step’s successor before React cleanup, invalid multi-step completion/skip, stale policy state after mutations, nested picker Escape dismissing its parent editor, inaccessible radio keyboard navigation and unnamed billing tables.
  • Save billing screenshots and page-error diagnostics during teardown in unique per-attempt directories. Failures and timeouts retain evidence, and capture failures preserve the original journey error.
  • Add the behavior-first testing rules to AGENTS.md. No failing behavior assertion is removed or weakened, and no coverage probe, threshold or exclusion change is used.
Coverage Main (7e9f277) This branch Change
Lines/statements 46.60% 50.18% +3.58 points
Functions 65.98% 65.15% −0.83 points
Branches 74.79% 74.19% −0.60 points
  • Coverage uses the same 13 production-source projects and measurement policy on both revisions; browser and Node tooling cases are separate. All metrics remain within the two-point loss budget.
  • Integrations exercise real components with literal host responses, not live provider writes or database RLS. Billing reflow uses an equivalent CSS viewport, and reduced-motion checks prove iframe preference propagation rather than suppression of every animation.

@tenki-reviewer

tenki-reviewer Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Review complete. 🟠 1 high · 🟡 1 medium

💬 Inline comments (1)

📍 Findings outside the diff (1) — 🟡 1 medium — defects on lines GitHub can't attach comments to

🟡 Medium — SKIP_STEP leaves loader in flight; stale result lands on next step · machine.ts:183–193 · unchanged line

// packages/command-palette/src/multi-step/machine.ts
183	        case 'SKIP_STEP': {
184	          if (
185	            !state.config ||
186	            state.view.flowStatus !== 'active' ||
187	            !state.config.steps[state.view.currentStepIndex]?.skippable
188	          ) return { state };
189	          const view = multiStepReducer(state.view, { type: 'SKIP_STEP' });
190	          const next = { ...state, view };
191	          const withCompletion = withCompletionEffect(state, next, options);
192	          const withLoader = withLoaderEffect(withCompletion.state);
193	          return mergeResults(withCompletion, withLoader);

SKIP_STEP (packages/command-palette/src/multi-step/machine.ts:183) advances the flow without emitting a cancel effect for the in-flight loader:<i> invocation, unlike CANCEL which cancels loader:<index> explicitly. A skippable step with a loader can be skipped while loading (the new guard checks only flowStatus === 'active' and skippable, not step status).

When the orphaned loader later resolves, LOADER_RESOLVE dispatches SET_STEP_DATA against the new currentStepIndex, so step i's data is written onto step i+1 and that step is marked active, suppressing its own loader; a stale LOADER_REJECT instead marks the wrong step as error. Since GO_BACK is now blocked while loading and its cancel effect was removed, SKIP_STEP is the only remaining path that can abandon a running loader.


This PR overhauls test coverage and several production paths across the monorepo: it replaces the Playwright billing e2e journey with an artifact-recording version, refactors command-palette machine guards (SKIP_STEP, GO_BACK, loader effects), removes now-unused sheets editor helpers (resolveEditorLocation, dateOnlyStringFromCalendarValue, copyDraftMeta), and adds roving-tabindex keyboard support to the workspace-kit FilterGroup plus billing table captions.

Files Change
apps/blocks/e2e/docs.interaction.spec.ts Rewritten billing journey spec with recordBillingJourney capturing screenshots, annotations, attachments, and page-error assertions
packages/command-palette/src/machine/use-machine.ts, multi-step/machine.ts Machine guard refactors: ignored-event early returns, effect identity handling, and reworked skip/back/load transition semantics
packages/sheets/src/grid/** Cell routing, date editor, and row-model cleanup removing dead pure helpers and their tests
packages/ui/src/components/workspace-kit/primitives.tsx, billing-kit/* FilterGroup keyboard navigation, sr-only table captions, billing catalog/invoice tweaks
Test files across packages/* Large batch of added/updated unit and integration tests aligned with the refactors
package.json, AGENTS.md Removed test:agent-skill script and deleted its test; AGENTS.md testing-policy updates

Reviewed commit: 3e5be34

@tenki-reviewer tenki-reviewer Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR rewrites the billing e2e journey with artifact capture, refactors the command-palette multi-step machine's loader/back/skip transitions, tightens sheets grid editor helpers, and updates workspace-kit/billing UI primitives and tests.

Key findings

Comment on lines +45 to +54
async function recordBillingJourney(page: Page, errors: string[]) {
const artifactDirectory = process.env.BLOCKS_E2E_ARTIFACT_DIR
?? join(tmpdir(), 'constructive-blocks-billing-e2e');
await mkdir(artifactDirectory, { recursive: true });
const screenshot = join(artifactDirectory, `${test.info().title.replace(/[^a-z0-9]+/gi, '-')}.png`);
await page.screenshot({ path: screenshot, fullPage: true });
test.info().annotations.push({ type: 'artifact', description: screenshot });
await test.info().attach('billing-journey', { path: screenshot, contentType: 'image/png' });
expect(errors).toEqual([]);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 bug · high

Billing artifacts captured only on success path

Every billing test calls recordBillingJourney(page, errors) as its final statement (e.g. apps/blocks/e2e/docs.interaction.spec.ts:418), so when any earlier step fails the full-page screenshot, artifact annotation, billing-journey attachment, and the expect(errors).toEqual([]) check are all skipped (apps/blocks/e2e/docs.interaction.spec.ts:45).

With screenshot: 'off', trace: 'off', and video: 'off' in playwright.config.ts, a failed billing journey produces no diagnostic evidence at all, and page errors are never surfaced because the only assertion on the errors array lives inside the skipped helper.

📋 Prompt for AI Agents

In apps/blocks/e2e/docs.interaction.spec.ts, wrap each billing test's body in try { ... } finally { await recordBillingJourney(page, errors); } so the screenshot, artifact annotation, billing-journey attachment, and expect(errors).toEqual([]) all run even when an earlier step fails. The helper is at lines 45-54; the final calls are around lines 418, 453, 480, 535, 567, 594, 620. With playwright.config.ts setting screenshot/trace/video to 'off', this helper is the sole artifact source, and skipping it on failure loses the screenshot, the attachment, and the pageerror report for exactly the runs that need them.

@yyyyaaa
yyyyaaa merged commit 69b81bb into main Oct 11, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant