QA plan: Frontend build and deploy (#30)
Story: Frontend build and deploy per env (#30)
Capability: Environments and deployment promotion (#26)
ADR: RAG001 — per-env SPA bundle on S3 + CloudFront
Test scope
Section titled “Test scope”| Type | Coverage |
|---|---|
| Build | npm run build exits 0; dist/ contains index.html and hashed JS/CSS assets |
| Build | No console.error or TypeScript errors in the Vite build output |
| Pipeline behavior | Deploy step syncs dist/ to the correct env S3 bucket (QA bucket on QA job, Prod bucket on Prod job) |
| Pipeline behavior | CloudFront invalidation runs after S3 sync; the new index.html is served within 60 s |
| Security | CloudFront response-headers policy includes Content-Security-Policy header; verified by fetching index.html from the CloudFront URL after deploy |
| Security | SPA bundle does not contain any hardcoded secret, API key, or credential (checked by secret scanner in CI pipeline, Story #29) |
| Integration (manual, QA) | After deploy, loading the QA CloudFront URL renders the chat UI (no blank screen, no 404 on assets) |
| e2e (QA only) | Playwright smoke: page loads, key input field is visible, badge renders after key entry |
Entry criteria
Section titled “Entry criteria”- Story #17 (React chat UI) merged
- Story #24 (Frontend Terraform module — S3 + CloudFront) deployed to QA
- CloudFront distribution and S3 bucket exist in QA
Exit criteria
Section titled “Exit criteria”npm run buildexits 0 in CI- S3 sync and CloudFront invalidation steps exit 0
- CSP header present on the CloudFront
index.htmlresponse (verified bycurl -I) - Manual QA: chat UI renders at QA CloudFront URL
- Playwright smoke: all assertions pass against QA
Environments
Section titled “Environments”Build: CI. Deploy: CI (QA on main merge, Prod on approval). Smoke: QA (manual + Playwright in CI).
Tooling
Section titled “Tooling”npm/Vite, AWS CLI (s3 sync, cloudfront create-invalidation), curl, Playwright.
How tests are written
Section titled “How tests are written”# Given the frontend has been deployed to the QA CloudFront distribution# When the Content-Security-Policy header is checkedRESPONSE=$(curl -sI "https://$QA_CF_DOMAIN/")echo "$RESPONSE" | grep -i "content-security-policy"# Then the header is present in the responsePlaywright smoke:
// Given the QA SPA URL is loadedawait page.goto(process.env.QA_SPA_URL);// When the page settlesawait page.waitForLoadState('networkidle');// Then the key input field is visibleawait expect(page.getByTestId('key-input')).toBeVisible();- CloudFront propagation delay: CI may check the URL before the invalidation completes. Add a
sleep 30or a retry loop in the smoke step to avoid a false failure. - Stale browser cache in Playwright: use
--no-cachecontext option to ensure fresh asset loading.
Capability acceptance criteria link
Section titled “Capability acceptance criteria link”RAG001: SPA bundle deployed per-env to S3/CloudFront. Security per-feature requirements (#18): CSP header on the CloudFront distribution. Exit criteria cover both.
© 2026 Benjamin Arunski