Practice Landing-Page QA with Codex Computer Use

Use a downloadable local lab to check links, form submissions and narrow layouts. Includes flawed and corrected pages, a checklist and offline-tested source.

Practice Landing-Page QA with Codex Computer Use

A landing-page check should finish with reproducible findings, not a message that “everything looks good.” This tutorial uses a fictional, local page with a broken link, a misleading form success message and a layout that needs a narrow-screen check. A corrected version makes it possible to repeat exactly the same tests. The companion kit is a teaching exercise, not an audit of a production business.

Download the QA lab. It contains the Python server, both page versions, tests, a results template and an answer key. The interface is English. No real-browser run is claimed in this article.

Start the local lab

Install Python 3.9 or later, unpack the kit and run this from its folder:

python3 -B server.py --port 8876

The server binds only to 127.0.0.1. Open the printed address in the browser you permit Codex to use. If the port is occupied, select another unused local port and update every URL in your test plan consistently.

Use only addresses ending in @example.test. No real contact details, purchase or external form submission is needed. The baseline is at /, the corrected example at /fixed, and local receiver records at /submissions. Stop the server with Ctrl-C when the exercise is finished.

Give the tester a task, not the answer key

Ask Codex to inspect navigation links, the form and layout at 1440, 390 and 320 CSS pixels. Tell it to preserve evidence, report expected and actual behavior and make no repairs. Keep the fixture’s source and answer key out of the initial test prompt so the observed behavior, rather than a source-code description, drives the report.

This does not create a blind benchmark if the author also built the fixture. Describe the final demonstration as an illustrative controlled test. Do not infer real-world detection rates from a few deliberately constructed faults.

Copy this QA brief before the first pass

This brief gives the tester a reproducible task without revealing the injected faults. Keep the source, answer key and the explanatory sections below out of the first-pass context. Browser controls and permission prompts differ between environments; use the browser already authorized for the exercise.

Inspect the local landing-page fixture at http://127.0.0.1:8876/.
Do not read its source or answer key. Do not modify the site.
Record browser version, timestamp, URL and actual viewport dimensions.

1. Save the initial /submissions result as the receiver baseline.
2. Click Working guide and Pricing. Record final URL, title and relevance.
3. Test blank input, not-an-email, and qa-run1@example.test separately.
   Record visible feedback and refreshed receiver records after each case.
4. Inspect layout at 1440, 390 and 320 CSS pixels wide.
   If your authorized browser controls cannot set or report those widths,
   mark those cases pending; do not estimate dimensions from appearance.
   Record clipping, whole-page overflow and whether controls remain usable.
5. Write reproduction steps, expected/actual results and evidence paths.
   Mark cases not executed as pending, not passed.
6. Repeat on /fixed using qa-run2@example.test and a new receiver baseline.
7. Restore temporary viewport settings. Do not submit real contact details.

If access is denied, stop and report the denied resource. Do not bypass it.
Separate actual observations from assumptions. Do not claim device coverage
from a resized desktop viewport or declare success from the banner alone.

A useful run produces a short report plus evidence files. Use separate directories such as run-01/original/ and run-01/fixed/, with receiver-before.json, receiver-after.json, viewport screenshots and the final report. These are proposed filenames, not files claimed to have been captured in our browser.

Click the Working guide and Pricing links separately. Record the final page title and destination, then return to the test page. A 404 is a clear failure. A 200 response at an unrelated destination is also a failure when it does not fulfil the link’s promise. The corrected Pricing link should reach the fictional pricing explanation, not merely any route that happens to exist.

Test the form as three cases

Leave the first input empty, use not-an-email for the malformed case and use qa-run1@example.test as a valid synthetic address. Use qa-run2@example.test when repeating the valid case on the corrected page. Open /submissions in a separate tab and note its record count before each case, keeping the original test page open. Refresh the receiver tab after each submission and compare both the full prior records and the new address. Use a unique address for the valid case so an older saved record cannot be mistaken for this submission.

For empty and malformed inputs, useful validation feedback should appear and the receiver should not get a new record. For valid input, look for both visible feedback and exactly one matching receiver record. A success message alone does not prove that a lead was stored. Record both layers in the report.

The baseline deliberately displays success without saving anything. That is an expected property of the fixture’s source, not a claim that the browser test has already detected it. Keep that distinction in your own results.

Compare receiver data, not just record counts

These JSON values are an illustrative example of the acceptance rule, not collected browser data:

{
  "before": [{"email": "old@example.test"}],
  "after": [
    {"email": "old@example.test"},
    {"email": "qa-run1@example.test"}
  ]
}

A count increasing from one to two is insufficient on its own. Check that the original record is unchanged and that the additional record matches the current test address. Two new copies indicate duplicate submission; a different new address may belong to another run. Save the actual full records, including their timestamp fields, rather than simplifying the stored evidence to match this illustration.

For blank and malformed input, expect validation feedback and no extra record. For a valid input on the fixed fixture, expect one matching addition. This pairing helps distinguish frontend validation, a misleading success banner and actual receiver persistence. It does not prove the reliability of an unrelated production form.

Check narrow layouts at specified dimensions

At each width, inspect the metric cards, navigation, input and submit button. Look for content outside the viewport, obscured text and controls that are hard to reach. Save a screenshot with the actual viewport dimensions. A screenshot without its dimensions is difficult for another tester to reproduce.

A resized desktop browser does not test a physical phone’s browser, keyboard, touch behavior or device performance. Label it as viewport simulation. Restore temporary viewport settings when the test is over.

Read the original and fixed versions as a test matrix

The table below describes intended fixture behavior based on code. Fill a separate actual-result column after your own browser run.

CaseOriginal fixture designFixed fixture designEvidence to collect
Pricing linkDestination route is missingOpens the fictional pricing pageFinal URL and page title; response status if available
Blank or invalid form inputSuccess text without savingValidation feedback; no new recordFeedback plus refreshed receiver data
Valid synthetic addressSuccess text without savingOne new saved recordBefore/after data and exact address
Narrow metric rowMinimum width of 650 CSS pixelsCards can wrapActual viewport and overflow observations

At 390 and 320 CSS pixels, test the ability to reach and use the button as well as the visible card layout. A horizontally scrollable table inside its own container is different from the whole document overflowing. MDN’s overflow documentation explains the container behavior; it is not evidence that this fixture has passed a visual test.

Turn observations into a useful report

Each finding needs a URL, environment, exact inputs, reproduction steps, expected result, actual result and evidence reference. Separate related symptoms from root causes: accepting empty and malformed input and claiming false success can arise from the same form handler. Do not inflate three symptoms into three independent implementation failures.

Compare the report with the answer key after the first pass. Record missed defects and false alarms as well as correct findings. Repeat the tests on /fixed using new synthetic addresses, then repeat from a fresh task to check whether the written instructions are sufficient without the author’s help.

What a complete defect report looks like

The following is a source-derived teaching example, not an observed browser finding. It demonstrates how to report the fixture’s intentionally false success state without inventing screenshots or a detection result.

FieldExample entry
ID / scopeFORM-01, original fixture /
SetupSave receiver records; use a unique synthetic address
StepsEnter qa-run1@example.test, submit once, refresh /submissions
ExpectedExactly one new matching record; existing records unchanged
Source-derived behaviorOriginal page displays success without saving a record
Browser observationPending; must be filled from the actual run
EvidencePending; attach before/after receiver data and screenshot after execution
Impact to verifyA user may believe the request was saved when it was not
RetestRepeat on /fixed with qa-run2@example.test and a fresh baseline

In an actual report, replace the source-derived behavior with what you observed and attach the matching evidence. If you cannot read receiver records, record that limitation and leave persistence unverified. Do not infer a backend failure from a missing screenshot or a stale tab.

The three form inputs are separate test cases. They can expose one underlying implementation problem. Keep the case results separate while grouping the root cause when the evidence supports it; this preserves coverage without inflating a defect count.

Troubleshoot an inconclusive run

SymptomCheck nextWhat not to conclude
Browser cannot connectConfirm the server process is running and the printed address matches the authorized environmentDo not assume the page itself is broken
Explicit access denialRecord the denied resource and resolve permissions normallyDo not switch tools or hosts to evade it
“Address already in use” in the terminalStop an unused instance you own or select an authorized unused port consistentlyDo not use a port change to bypass denial
Receiver contains earlier entriesCapture a fresh baseline and choose a new synthetic addressDo not count old submissions as this run’s success
Success appears but receiver is unchangedRefresh the receiver and preserve both observationsDo not repeatedly click and create ambiguous retries
Screenshot seems mobileRecord CSS viewport and browser environmentDo not label it a real-phone test

The server writes local submissions.jsonl records. Restarting it does not necessarily remove that file. Preserve it for the run; work from a separate clean extracted copy when you need a fresh fixture. For another evidence-first browser task, the competitor research tutorial shows how to keep observed facts separate from unresolved fields.

Results and boundaries

Verified on Python 3.9.6 and Node.js 24.13.0, the local package includes seven in-process Python handler tests and nine JavaScript form simulations. They passed without opening a browser or making network requests. The Python checks cover invalid lengths and JSON, synthetic address validation, record writing, test routes and template substitution. The JavaScript checks execute the form code with fake document and fetch objects.

Run the development checks from the unpacked qa-kit folder:

python3 -B -m unittest discover -s . -p 'test_*.py' -v
node test_form.mjs

Both commands also passed after extracting a fresh copy of the ZIP. These are development checks, not layout tests. They do not prove that Codex finds the injected faults, that the controls render correctly, or that a real browser sends the request. The 1440/390/320 viewport results, screenshots and actual original/corrected browser comparison remain unverified.

This exercise checks a limited set of links, form states and layouts. It does not replace a full accessibility, security, performance or cross-device audit. Its useful output is a repeatable checklist and evidence-backed defect report that someone else can verify before approving a release.

For a programmatic completion check, see the offline Computer Use controller. For browser setup problems, see the permissions guide.

Frequently Asked Questions

Does this include a completed browser test?
No. The package passed seven Python handler tests and nine JavaScript simulations. Real-browser interactions, screenshots and narrow-screen rendering remain unverified.
How do I verify that a form really submitted?
Capture receiver records before the test, use a unique synthetic address, then verify exactly one matching addition with prior records unchanged. A success banner alone proves only what the page displayed.
Does desktop resizing count as mobile testing?
It checks layout at a specified CSS viewport. It does not establish behavior on physical phones, touch input, the mobile keyboard or device performance.
Why should the fixed page use a different email?
A new synthetic address and a fresh receiver baseline distinguish the retest from earlier records and make duplicates visible. Keep both runs as evidence.