QA
What to QA next
A page-by-page worklist for the QA reviewer (no technical background needed). Switch stores with the tabs. The developer testing guide below is the deeper method. Driven by docs/qa/*.md.
Testing guide for future work — Migration (developers)Show
What should be tested and verified. This is the reusable method behind the per-page checklists below.
SSR / body-content
- Disable JavaScript in the browser, reload. The H1, body prose, product/price summary, and review content must still be visible. Blank with JS off = FAIL (invisible to AI crawlers).
- View Source (Ctrl+U — the raw HTML, not the inspector): the main copy text is present in the served HTML.
Section parity vs the original — at desktop AND mobile
- Every section in the original is present in the migration. Write the original's sections top-to-bottom (hero, trust row, each content block, specs, gallery, FAQ, related, CTA, footer) and tick each off on the migrated page. Nothing missing.
- Section order matches the original, OR the difference is an approved redesign (e.g. split-hero standardization), not an accidental drop/reshuffle.
- Per-section content matches — headings, body copy, images, links, and counts (gallery items, FAQ entries, related links, nav items) are equivalent. No truncated, placeholder, or lorem text.
- No stray/orphan sections the migration introduced that don't belong.
- Mobile (390px): repeat the whole section-by-section pass. Sections may stack/reflow, but all must be present and legible — no overlap, no horizontal overflow, hamburger nav opens and lists the expected items.
- Spacing, colors, fonts, and component styling read as the same brand at both widths; tablet (768px) spot-check shows no broken layout between breakpoints.
- All images load (no broken/placeholder), correct aspect ratio; the LCP hero is present and not shifted (CLS).
Content & copy compliance
- H1 present, correct, single per page; heading order has no skips (H1 -> H2 -> H3).
- No em dashes, no exclamation marks, no emoji in visible copy.
- No banned words (discover, unlock, leverage, robust, seamless, transform, elevate, journey, dive into, embark, plethora, myriad, game-changing, revolutionary).
- Glazing language is "frame shop grade acrylic" / "non-glare acrylic" only — no UV claims, no museum/conservation glazing.
- Turnaround reads "3-5 business days" for in-cap sizes; over-32x40 shows freight/local-pickup language.
- No star ratings / review counts in STATIC copy (only the dynamic widget shows them).
- "picture framing" used as the lead descriptor (not "custom framing"); facility-anchored phrasing ("made at our Somerset production facility").
SEO (view-source + Rich Results Test)
- <title> present and ends with | CustomPictureFrames.com.
- <meta name=description> present, unique, ~150 chars.
- <link rel=canonical> present, self-referential, points at www.custompictureframes.com (NOT localhost/preview host), clean path (no query params).
- OG tags (og:title, og:description, og:image, og:url) present; og:image resolves.
- JSON-LD present with the right @type for the page type; paste into Google Rich Results Test -> 0 errors.
- Aggregate Rating node present only where a real rating exists; self-omitted when unavailable.
Links & navigation
- Header/footer nav links work; breadcrumb correct.
- In-body internal links resolve (no 404); page is not orphaned (>=1 inbound link from a hub/related block).
- Designer CTA present where expected (size/color/style/specialty pages); deep-links to the designer with the right preset.
Functional
- Any interactive element works (accordions, carousels, filters, forms).
- Forms validate + submit (and are honeypot / rate-limit protected).
Console & network
- Browser console: 0 errors, 0 warnings.
- Network tab: no failed (4xx/5xx) requests; no 429s under a normal click-through.
Accessibility
- Keyboard-only: tab order logical, focus ring visible, skip-link works, no keyboard trap.
- Run axe DevTools (or the Playwright axe step): 0 violations.
- Tap targets >=24px (target 44px) on mobile controls (carousel dots, option rows, info icons).
Cross-browser / device
- Chrome + Safari + Firefox (desktop); Safari iOS + Chrome Android (real or emulated).
Redirect retention (once Epic H is live for that route)
- The legacy .html URL 301s to this page (curl: 301 -> Location -> destination 200).
How to test
- 1.Run the AI-bot for testing — codebase level.
- 2.Manual testing across devices / browsers after dev deployment, in the order above.
- 3.Hand off to the QA team for the Framing Industry Standards logic check.
CustomPictureFrames.com
2 blocking gates openEvery page — verify these first
On every page below, confirm: opens with no error; the big title at the top matches the topic; scrolling top-to-bottom shows real text and images (no blank gaps, no "lorem", no broken images); on a phone it stacks neatly with no sideways scroll and the menu opens; every link and button goes to a real page (no "page not found").
- I've read these standard checks and will apply them to each page below
/canvas-prints
- Standard checks pass
- The FAQ section opens and shows real questions and answers
/canvas-stretching
- Standard checks pass
/giclee-printing
- Standard checks pass
/large-format-printing
- Standard checks pass
- Any prices shown read correctly
/custom-mats
- Standard checks pass
/photo-mats
- Standard checks pass
/framed-chalkboards
- Standard checks pass
/framed-cork-boards
- Standard checks pass
/framed-dry-erase-boards
- Standard checks pass
/framed-wall-art
- Standard checks pass
/magazine-sizes-guide
- Standard checks pass
- The size tables/lists show real numbers (no blanks)
/photo-restoration
- Standard checks pass
/sports-photo-framing
- Standard checks pass
/puzzle-glue-sheets
- Standard checks pass
/floater-frame-for-panel-painting
- Standard checks pass
/scarf-and-sash-framing
- Standard checks pass
- Glazing text reads "framer's grade acrylic" (a shadow box, so no non-glare/UV/museum wording)
After this batch — queued next
Once the 16 pages above are signed off, the next batches are the 8 sports display cases, the 5 category landings (wood/large/ornate/rustic/vintage), the 9 flat specialty pages, and the 9 shadow-box/keepsake pages. (/metal-picture-frames and /designer are on hold — see Issues.)
- Batch 1 (above) signed off, ready to load the next batch
Launch gate — pricing parity (Wave 10)
Prices must match the live site to the cent. Now verified by an automated harness rather than by hand: 252 golden values snapshotted from the LIVE CPF engine (original-cpf/shared/schema.ts) and asserted against the migrated one — every moulding SKU, the 4x4 minimum, 8.5x11 decimals, the 32x40 cap, both oversize bands, 40x60 freight, 80 mat and 12 print configs. All match. Re-run: `cd packages/core && npx vitest run pricing-parity`.
- ✓Designer built
- ✓Configs compared to the cent (252, automated)
- ✓Over-cap + oversize bands verified
- ✓Harness proven non-vacuous (perturb a lever, it fails)
FLAGSHIP_MIGRATION_PLAN.md · Wave 10
Launch gate — /designer and /cart
- ✓/designer renders, prices live, and reaches the cart
- ✓Body + Product schema present with JavaScript OFF
- ✓Legacy size links land on the right size (`/designer?w=16&h=20` prefills 16x20)
- ✓Checkout payload proven: price in cents, packing block, storeCode CPF
- ✓Section order matches the source: designer above the fold on mobile, hero above it on desktop
- A REAL test order lands in Shopify Admin (blocked on the variant id env — see variant-id-env)
- Human side-by-side against the live site on a phone and a desktop
FLAGSHIP_MIGRATION_PLAN.md · Waves 10 + 13
Launch gate — the 39 specialty designers
Every specialty landing page now embeds its real designer (the "being wired up" placeholder is gone everywhere). Automated sweep covers one page per distinct designer.
- ✓All 39 pages embed a real designer; zero placeholders
- ✓Pages still serve their prose with JavaScript off, and stay static
- ✓No landing page rewrites its own URL when you use the designer
- Human pass: does each page's designer match the live CPF page (styling, sections, mobile)?
- /custom-mats is currently the REDUCED mat designer, not CPF's v2 (see mat-v2-missing)
- /heart-frames and the canvas traditional/unframed paths are not migrated yet
FLAGSHIP_MIGRATION_PLAN.md · Wave 11
CustomFrameSizes.com
/ (homepage)
- Standard checks pass
- Single big title (H1); trust row + designer + sections all present
/designer
- Standard checks pass
- The frame designer loads; changing size/mat/glazing updates the live preview and price
a frame product page (/frames/<any>)
- Standard checks pass
- Designer present; price shows; add-to-cart works
a specialty page (e.g. /jersey, /diploma)
- Standard checks pass
- The specialty designer loads and prices correctly
Learn + company pages (/learn, /about, /contact, policies)
- Standard checks pass
- Contact form: submit it and confirm the message actually arrives (currently it does NOT — see issue cfs-contact-form)
Measured checks that have never been run
Not page content — these tools must actually be run once before launch.
- Lighthouse >=90 on /, /designer, a PDP, a category page
- axe / WAVE accessibility scan: 0 violations
- Screen-reader pass (designer -> cart)
- Real-device mobile pass at 375px
Blocked until infra is wired (do last)
- Real Shopify checkout end-to-end (needs Cart Transform + BFF + prod env)
- Cart line price == displayed price; packing-slip attributes correct
- Preview deploys return noindex (needs the staging gate first)
ShadowboxFrames.com
Fix first (blocks most QA)
- Add the missing media API routes (upload/export/upscale/AI) or the flows will 404
- Set the CDN env vars (or images will be broken across every page)
- Provision Shopify (or checkout stays a mock)
/ (homepage) + hub pages
Content/SEO QA — safe to do now.
- Standard checks pass (opens, correct title, real text/images, phone-friendly, links resolve)
- Replace the placeholder gallery/achievements content before sign-off
Shadow-box + picture-frame category pages
- Standard checks pass across a sample of gateway/category pages
- Images load (confirms CDN env is set)
Blog + resources
- Standard checks pass on a sample of blog posts + resource articles
Once media + Shopify are fixed
- Designer -> upload artwork -> add to cart works
- Real Shopify checkout end-to-end with the SBF store code
- Fix the broken default social-share image
Platform & Shared
2 blocking gates openCart Transform — pricing to the cent
- ✓Unit test present (_price_cents -> price, _line_title)
- Configurator price == cart price == checkout price across sizes/styles/mats/glazing
- 8-case matrix: single / multi / qty / over-cap / min / complex / persistence / mismatch
- Tax + discount correct on overridden prices
- An invalid/tampered price line is rejected (needs the signed-payload fix — see issue P-1-unsigned-price)
Checkout branding
- ✓BFF sets brand attributes on cart create; the extension reads them
- Matrix: each store shows its own logo; unknown -> fallback; image-fail -> safe state
- Mobile/desktop; bundle under budget; no cross-brand contamination
API health
- ✓/api/health + /api/health/db exist
- /api/health/db green once the database URL is set
- CORS allows every storefront origin — add the flagship origin (see issue P-6-cors-flagship)
- orders/create webhook is signature-verified and idempotent
Customer accounts (per phase, when creds land)
- Sign in / out round-trip; account is created on first login
- Save a design, reload, it restores exactly; soft-delete hides it
- Logged-in photo upload attaches to the account
- Security: signed webhooks, encrypted sessions, per-store data isolation