External acceptance-test harness for rails_got_the_keys.
This repository runs:
- Playwright browser acceptance tests
- Playwright BDD public-auth coverage
- Lighthouse quality audits
k6read-heavy HTTP performance checks- Gatling JS read-heavy HTTP performance checks
It supports three target modes:
local: a developer-started Rails app onhttp://127.0.0.1:3000staging:https://staging.gotthekeys.uk, overrideable through environment variables or GitHub Actionsproduction: a deployed production URL supplied throughPRODUCTION_BASE_URLor GitHub Actions dispatch payloads
- Node.js 24+
- npm
k6installed locally for performance runs- a running
rails_got_the_keysapp when usinglocal
Copy .env.example to .env and fill in the values that match the Rails app contract.
For local runs, the test harness also falls back to the checked-in .env.example
when .env is missing. That means npm run test:e2e can boot with the default
local contract as long as your Rails app is running on http://127.0.0.1:3000.
The most important values are:
BASE_URLPROPERTY_PATHorPROPERTY_ADDRESS_LINE_1ADMIN_EMAILADMIN_PASSWORDUSER_EMAILUSER_PASSWORDADMIN_LOGIN_PATHADMIN_BOOKINGS_PATHADMIN_CUSTOMERS_PATHQA_PATH
Public auth coverage also supports these route overrides, with Devise-style defaults:
USER_SIGN_IN_PATHdefault:/users/sign_inUSER_REGISTER_PATHdefault:/users/registerUSER_RESET_PASSWORD_PATHdefault:/users/password/new
USER_EMAIL and USER_PASSWORD should point at a seeded member account for local and staging runs. The credentialed public sign-in scenario skips locally when those vars are absent, but staging should provide them so the full auth feature can run.
Selector-specific env vars are optional until the Rails app publishes its acceptance selector contract. When they are missing, the tests fall back to broader visibility assertions.
npm install
npx playwright install --with-deps chromiumThe repo includes a checked-in .env.example with the expected auth and route variables.
Start the Rails app in a separate terminal, then run:
npm run smoke:localOr run suites individually:
npm run test:auth
npm run test:smoke
npm run test:e2e
npm run lighthouse:local
npm run perf:smoke:local
npm run gatling:smoke:localTo stress the local catalogue with 100 concurrent users repeatedly querying /properties, run:
npm run gatling:stress:catalogue:localThe stress command defaults to BASE_URL=http://127.0.0.1:3000, TARGET_ENV=local, PROPERTY_PATH=/properties, GATLING_VUS=100, and GATLING_DURATION=2m. Override any of those values inline when needed:
GATLING_DURATION=5m npm run gatling:stress:catalogue:localTo watch Playwright run in a browser, load the local target variables and run headed. Use one worker for a slower, easier-to-follow debugging session:
set -a; source .env.example; set +a
HEADLESS=false npm run test:e2e
HEADLESS=false PW_WORKERS=1 npm run test:e2e
HEADLESS=false PW_WORKERS=1 npm run test:smokeTo make the headed Chromium window open maximized, use the real browser window
size and pass Chromium the maximize flag in playwright.config.ts:
use: {
baseURL: env.BASE_URL,
headless: env.HEADLESS,
trace: "on-first-retry",
screenshot: "only-on-failure",
video: "retain-on-failure",
viewport: null,
launchOptions: {
args: ["--start-maximized"],
},
},For a Cypress-like GUI, use Playwright UI Mode. Generate the BDD specs first, then open the runner:
set -a; source .env.example; set +a
npm run bddgen
HEADLESS=false npx playwright test --uiUI Mode lets you pick tests, run or stop them, rerun failures, watch the browser, and inspect steps, errors, console output, network activity, and traces. For a slower debugging session:
set -a; source .env.example; set +a
npm run bddgen
HEADLESS=false PW_WORKERS=1 npx playwright test --uiYou can also add a shortcut script:
"test:ui": "npm run bddgen && playwright test --ui"Then run:
set -a; source .env.example; set +a
HEADLESS=false npm run test:uiOther useful interactive tools:
npx playwright test --debug
npx playwright codegen http://127.0.0.1:3000After a run, open the Playwright HTML report:
npx playwright show-reportSet staging env vars, then run:
TARGET_ENV=staging BASE_URL=https://staging.gotthekeys.uk npm run test:auth
TARGET_ENV=staging BASE_URL=https://staging.gotthekeys.uk npm run test:staging
TARGET_ENV=staging BASE_URL=https://staging.gotthekeys.uk npm run lighthouse:staging
TARGET_ENV=staging BASE_URL=https://staging.gotthekeys.uk npm run perf:mixed
TARGET_ENV=staging BASE_URL=https://staging.gotthekeys.uk npm run gatling:mixedOr export the staging target once before running individual commands:
export TARGET_ENV=staging
export BASE_URL=https://staging.gotthekeys.uk
npm run test:auth
npm run test:staging
npm run lighthouse:staging
npm run perf:mixed
npm run gatling:mixedThe k6/ and gatling/ folders contain matching read-heavy performance scenarios:
smoke-home/gatling:smoke:localchecks the homepage with one virtual user and five requestsbrowse-catalogue/gatling:cataloguerepeatedly loads/propertiescatalogue-stress-local/gatling:stress:catalogue:localruns 100 local concurrent users against/propertiesproperty-detail/gatling:propertyrepeatedly loads the resolved property detail pathmixed-read-traffic/gatling:mixedsamples/,/properties,/for_sale,/for_rent, and the property detail path
Gatling scripts use the same target variables as k6: BASE_URL, TARGET_ENV, and either PROPERTY_PATH or PROPERTY_ADDRESS_LINE_1. Load settings can be set with GATLING_VUS, GATLING_DURATION, GATLING_HTTP_REQ_FAILED_RATE, and GATLING_HTTP_REQ_DURATION_P95_MS; when those are absent, the scripts fall back to the existing K6_* values.
Use the dedicated read-only production canary suite and reduced Lighthouse profile:
npm run test:production
npm run lighthouse:productionThese production checks are intentionally limited to public, non-destructive coverage so production dispatches do not depend on admin credentials or write flows.
config/ shared environment, target, and threshold config
tests/ Playwright fixtures, page objects, specs, helpers, and Gherkin features
lighthouse/ Lighthouse CI config and budgets
k6/ read-heavy traffic scenarios
gatling/ Gatling JS equivalents of the read-heavy traffic scenarios
scripts/ target validation and local orchestration helpers
.github/ CI workflows for local, staging, and production runs
The included GitHub Actions workflows cover:
- PR and push validation against a locally booted Rails app
repository_dispatchstaging verificationrepository_dispatchproduction verification- nightly staging verification
- optional GitHub Pages report publishing from the shared runner
The workflows expect repository variables and secrets for:
PROPERTY_PATHPROPERTY_ADDRESS_LINE_1STAGING_BASE_URLdefaults tohttps://staging.gotthekeys.ukin staging workflows when unsetPRODUCTION_BASE_URLis preferred for production dispatches so production reports cannot accidentally inherit a staging payload URL- optional
TEST_ID_*selector mappings ADMIN_EMAILADMIN_PASSWORDUSER_EMAILUSER_PASSWORD- optional
RAILS_REPO_READ_TOKENwhen local CI checks out a private Rails repo
This scaffold is ready to adapt, but the Rails app should still publish a short contract that defines:
- the deterministic property path
- the stable
data-testidvalues used for key pages - the exact admin and QA paths
- the expected seeded dataset
Until that contract is locked down, some assertions intentionally stay broad so the harness remains maintainable without inventing app details.
These values were verified from the current rails_got_the_keys repository:
- admin sign-in path:
/admins/sign_in - admin bookings path:
/admin/bookings - admin QA path:
/admin/qa - admin customers path:
/admin/customers - baseline admin credential: set
ADMIN_EMAIL/ADMIN_PASSWORDfrom local or CI secrets - baseline public member credential: set
USER_EMAIL/USER_PASSWORDfrom local or CI secrets - deterministic baseline property identity:
18 Cedar Road - stable selectors already present include
site-header,property-card,property-showcase,appointment-form,book-viewing-cta,property-documents-panel,admin-appointment-row,active-demo-scenario, and QA version selectors such asqa-version-box
Property show URLs currently use numeric IDs like /properties/4068, not stable slugs. Because of that, this harness can resolve the property page dynamically from the catalogue when PROPERTY_ADDRESS_LINE_1 is provided.