Skip to content

test(website): give the suite an nx target and repair what rotted in the dark - #851

Merged
blove merged 1 commit into
mainfrom
blove/website-test-target
Aug 29, 2026
Merged

test(website): give the suite an nx target and repair what rotted in the dark#851
blove merged 1 commit into
mainfrom
blove/website-test-target

Conversation

@blove

@blove blove commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

apps/website has 36 spec files and no test target. Nothing ran them — not by local convention, not in CI. Three files had drifted red and there was no way to find out.

Wiring

  • test target on apps/website (@nx/vitest:test, reusing the existing vite.config.mts)
  • npx nx test website added to the Website CI job
  • Job renamed Website — lint / buildWebsite — lint / test / build, and its require_scoped label updated in the same commit so the required-checks aggregation keeps matching (the name appears in two places)

Repairs

PostCard asserted the raw ISO 2026-05-17, but the card renders through formatCardDateMay 17. Fixed by deriving the expectation from that same formatter rather than hardcoding 'May 17'formatCardDate omits the year only for same-year posts, so a literal would silently rot on 1 Jan.

Differentiator listed a row renamed MIT + self-hostedOpen adapters + self-hosted. Added a length assertion, because deleting a row from both the component and the expected list would otherwise leave a shrunken table green.

ThanksPage — not drift. Every assertion ran against <body><div /></body>: it's an async Server Component taking searchParams: Promise<...>, so rendering it as sync JSX produces nothing. This test never worked against this component shape. It now awaits the component. Also fixed a stale link (Installation docsInstallation & licensing, /docs/licensing) and added coverage for the Stripe session-id guard that keeps an arbitrary query value out of the portal URL.

Verification

  • 347/347 across 36 files.
  • The target is a real gate, checked directly rather than assumed: nx test website exits 1 with a deliberately broken test and 0 when green. A target that always passes would be worse than no target — which is close to the situation this PR is fixing.
  • Both repaired assertions mutation-tested: removing the date from PostCard, and loosening the session-id regex to true, each turn their spec red.
  • nx lint website 0 errors, nx build website green.

Note

apps/website/next-env.d.ts is tracked but build-generated, and flips between ./.next/dev/... and ../../dist/... depending on whether dev or build ran last. I reverted the churn rather than including it; it's probably a gitignore candidate, but that's outside this change.

🤖 Generated with Claude Code

…the dark

apps/website had 36 spec files and no `test` target, so nothing ever ran
them — not locally by convention, not in CI. Three files had drifted red
and nobody could have known.

Wiring:
- `test` target on apps/website (@nx/vitest:test, existing vite.config.mts)
- `npx nx test website` in the Website CI job, renamed to
  'Website — lint / test / build' along with its require_scoped label so
  the aggregation keeps matching

Repairs:
- PostCard: asserted the raw ISO date, but the card renders through
  formatCardDate ('May 17'). Fixed by deriving from that same formatter —
  a literal would rot again on 1 Jan, since the year is omitted only for
  same-year posts.
- Differentiator: a row was renamed 'MIT + self-hosted' ->
  'Open adapters + self-hosted'. Added a length assertion so deleting a
  row from both the component and the list can't stay green.
- ThanksPage: every assertion ran against `<body><div /></body>`. It is an
  async Server Component taking `searchParams: Promise<...>`, so rendering
  it as sync JSX yields nothing — this never worked, it isn't drift. Now
  awaits the component. Also fixed a stale link ('Installation docs' ->
  'Installation & licensing', /docs/licensing) and added coverage for the
  Stripe session-id guard that keeps an arbitrary query value out of the
  portal URL.

Verified: 347/347 across 36 files. The nx target exits 1 on a failing test
and 0 when green (checked directly — a target that always passes would be
worse than none). Both repaired assertions mutation-tested: removing the
date from PostCard and loosening the session-id regex each fail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview Aug 29, 2026 9:39pm

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@blove
blove enabled auto-merge (squash) August 29, 2026 21:37
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove merged commit 9b5bfff into main Aug 29, 2026
23 checks passed
blove added a commit that referenced this pull request Aug 29, 2026
… off inline styles (#855)

* docs(plans): website suite now has an nx target and a green baseline (#851)

* refactor(website): move pricing components to marketing.css

CompareTable, LeadForm, CompatibilityMatrix, and PricingFAQ move their
static presentation (backgrounds, borders, type scale, table cell
shapes) from inline style props into src/styles/marketing.css, with
zero visual change.

- CompareTable's repeated cell/header style objects (shape D) collapse
  into a handful of `.pricing-compare-*` classes reused across tiers
  and rows; bounded tier/row states (highlighted tier, active billing
  cycle, last row) become `data-highlight`/`data-active`/`data-last`
  modifiers instead of inline ternaries.
- LeadForm's 6 focus/blur handler pairs (border-color + box-shadow) are
  replaced by a single `.lead-form-input:focus` rule; the handlers are
  deleted.
- CompatibilityMatrix's TONE_COLORS lookup becomes a `data-tone`
  modifier on `.compat-matrix-td-label`.
- Values computed from external config (CtaStrip's
  `gridTemplateColumns` keyed off `TIERS.length`) stay inline per the
  migration's "unbounded/computed" exception.

Migration: docs/superpowers/plans/2026-08-29-inline-style-substrate-migration.md

* refactor(website): move blog components to marketing.css

PostCard, FeaturedPostCard, BlogTagFilter, AuthorByline, and TagChips
move their static presentation into src/styles/marketing.css, with
zero visual change.

- PostCard/FeaturedPostCard keep the existing `data-ui="card"
  data-hoverable` hooks (ui.css) for the resting/hover treatment from
  Batch 1, and layer a single component class after it in import order
  (marketing.css loads after ui.css) to override background/border/
  padding/radius, matching the specificity precedence the inline
  styles previously had.
- BlogTagFilter's PILL_BASE/ACTIVE/INACTIVE variant maps (shape B)
  become one `.blog-tag-pill` class with a `data-active` modifier; the
  non-link "current tag" span keeps its `cursor: default` override via
  a `data-static` modifier.
- RecentArticles (batch 4) only consumes `<PostCard>` with no wrapping
  style — confirmed no double-styling.

Migration: docs/superpowers/plans/2026-08-29-inline-style-substrate-migration.md

* refactor(website): move contact and solutions components to marketing.css

ContactForm, AltChannelRow, SlaCard, GitHubStarsPill, SolutionDemoBlock,
and SolutionCodeBlock move their static presentation into
src/styles/marketing.css, with zero visual change.

- ContactForm has no focus/blur/invalid handling in the source (the
  batch brief mentions focus/validation states for the contact+pricing
  pair, but only LeadForm, migrated in commit 1, actually implements
  it) — moved as plain shape A/D, `'use client'` kept for form state.
- SolutionDemoBlock/SolutionCodeBlock's `<Eyebrow style={{ color:
  accent, marginBottom: 12 }}>` stays inline: `accent` is a per-page
  prop (unbounded value), the migration's documented exception.
- SolutionCodeBlock's `marginTop: index === 0 ? 0 : 24` ternary becomes
  a `data-first` modifier on `.sol-code-block-item`.
- SolutionCodeBlock's code-frame styles merge into the `.solution-code`
  class the component already applied via className (unstyled until
  now).

Migration: docs/superpowers/plans/2026-08-29-inline-style-substrate-migration.md
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