Skip to content

Test an interactive web application

You will execute repeatable function, input, keyboard, focus, state, responsive, zoom, source, and Console tests against one identified application commit. You will record actual results before changing source and use a reproduce → hypothesis → focused repair → same-path retest loop for every confirmed defect.

An interactive application can show the right final screen while handling the wrong record, losing keyboard focus, accepting invalid input, duplicating an event, or reporting a stale status. A resettable test path exposes the starting state, action, state transition, rendered result, and evidence needed to repeat the observation.

What you will practice

  • Write a reset procedure that gives repeated test paths the same starting state.
  • Define expected results from the product contract instead of copying current behavior.
  • Record actual DOM, state, focus, status, and Console evidence for scripted interaction paths.
  • Test the same user outcome with pointer and keyboard input without requiring timed keystrokes.
  • Distinguish a confirmed defect, an intermittent observation, a blocked condition, and an accepted limitation.
  • Use a bounded exploratory charter after the required scripted paths.
  • Repair one confirmed cause at a time and repeat the original path plus related regression checks.
  • New: Tested build, product contract, reset procedure, precondition, state transition, test oracle, intermittent result, exploratory charter, defect triage, and focused regression set.
  • Reused: The private quality board, GitHub issues, test conditions, expected and actual results, evidence, status labels, JavaScript state, DOM events, focus restoration, role="status", keyboard testing, validators, responsive tools, 200% zoom, Git commits, and GitHub pushes.

Starting point

Before you start

  • The same private application repository and GitHub Project used in the quality-planning lesson.
  • A closed baseline issue with the full tested commit, environment, launch method, primary interaction, and Console result.
  • The core-interaction issue in In progress and every other required issue in Ready.
  • A clean local main branch that matches the current remote commit.
  • VS Code, a current browser, DevTools, Git, and internet access for source validation.
Current state
The quality board describes what must be checked, but the interaction paths do not yet have a shared reset procedure, actual results, defect records, or same-condition retests.
First action
Open the active core-interaction issue, run the documented application once, and create interactive-test-report.md at the repository root.
First checkpoint
interactive-test-report.md identifies the tested commit, environment, product contract, reset procedure, scope, status labels, and fifteen Not run cases.
Help trigger
Use the recovery note or ask for help if the starting state cannot be restored, the expected result conflicts with the product brief, a failure changes between identical runs, focus cannot be located, a validator message is unclear, or a repair would affect more than the confirmed cause.

You have completed the lesson when:

  • interactive-test-report.md identifies one full commit hash, browser and version, operating system, launch method, date, and test data boundary;
  • the report states the primary interaction, invalid-input result, successful state change, status result, focus result, and reload boundary expected from the product;
  • one reset procedure restores the named starting state before an independent test path;
  • fifteen scripted cases contain preconditions, actions, expected results, actual results, evidence, and final statuses;
  • empty, whitespace-only, valid, repeated, long, and HTML-looking text paths use synthetic data only;
  • pointer and keyboard paths reach the same primary outcomes;
  • keyboard focus stays visible and reaches an intentional element after validation, submission, and state-changing renders;
  • visible status text and its programmatic role or property are inspected without moving focus to the message;
  • the app is tested near 320px, at a wider viewport, and at 200% browser zoom;
  • saved HTML and CSS messages are resolved or evidence-backed, and required interaction paths add no unresolved red Console error;
  • one bounded exploratory charter runs after the scripted paths and records three variations or stops at the first confirmed defect;
  • every confirmed defect has two matching reproductions, one focused issue, one tested hypothesis, the smallest relevant repair, the original-path retest, and related regression evidence;
  • when no defect is confirmed, the report states that no source repair was required instead of inventing one;
  • the function, keyboard and focus, responsive, and source-and-Console quality issues close only after their evidence requirements pass;
  • only the current issue is In progress, and the final-regression issue remains Ready for later product changes;
  • the report names open limits and the final tested commit; and
  • focused repair commits, if any, and the final report commit are pushed to the private repository.

Run these commands from the application repository:

Identify the test baseline
git status
git rev-parse HEAD
git log -1 --oneline

Stop if git status shows an unexpected source change. Decide whether to commit, restore, or intentionally include that change before testing. Do not attach pass evidence to an undefined working tree.

Copy the full git rev-parse HEAD output into the report. A commit hash identifies source; the environment and reset procedure identify the conditions around it.

The product contract states the behavior the application is meant to provide. Its expected results come from the assignment requirements and documented decisions, not from whatever the current browser happens to show.

Use these default interaction roles when the app is based on the task tracker:

Role Default task-tracker behavior Adaptation rule
Primary input Task description text field Name the real user input
Primary action Add task Name the real submit or state action
Invalid input Empty or whitespace-only text stays out of state Name the real rejected boundary
Successful result One record and one rendered item are added Name the observable state and DOM result
Secondary action Change a task checkbox Name the real item-level action
Status Completed and total counts update Name the visible result message
Focus result Input or changed control keeps intentional focus Name the intended target after each action
Reload boundary Two initial tasks return; added tasks do not persist State the real persistence decision

If your application uses a filter, quiz, animation state, or resource directory, replace the task terms. Keep one invalid path, one successful path, one secondary state change, one status result, and one documented reload result.

A reset procedure gives independent test cases a known precondition. Add exact steps to the report.

For an in-memory task tracker, use:

  1. Reload the page.
  2. Confirm that the two documented initial records appear.
  3. Confirm that the first record is complete and the second is open.
  4. Confirm that the summary says 1 of 2 tasks complete.
  5. Confirm that focus begins at the browser’s normal page-entry position.
  6. Open the Console and record any startup error before clearing or filtering messages.

If the product persists data, use its visible reset function or a documented clean test profile. Do not delete storage or change a database in DevTools unless that is the agreed test procedure and the data is synthetic.

Reference pattern: make an unpredictable precondition repeatable

Section titled “Reference pattern: make an unpredictable precondition repeatable”

Use this pattern when a required test depends on randomness, time, or another result that you cannot reproduce on demand. A controlled test setting replaces only that unpredictable decision. The rest of the application must follow the same state-update and render route as normal use.

Keep one decision boundary: one named place in the source where the program decides which result continues into the normal state transition. Do not add controlled branches to render functions or repeat the same mode check in several event handlers.

Use this general contract:

Setting Result at the decision boundary What must remain unchanged
Normal Use the product’s ordinary unpredictable rule Its documented percentage, allowed values, and later state transition
Controlled no-result Return the documented no-result outcome The action, status, focus, and render route after that outcome
Controlled known-result Return one named result from the product’s allowed data The state transition that normally receives a successful result
Restored checkpoint Normal is active again The controlled routes remain documented and repeatable

The setting is a source-code configuration for development. It is not user input, application state, browser storage, or saved progress. One clear option is a string value near the fixed application definitions. Record the file, setting name, allowed values, normal value, and known result in the test report.

Plan the boundary before you write syntax:

Controlled-decision pseudocode
read the development setting
if the setting requests no result
produce the normal no-result outcome
otherwise if the setting requests a known result
select the documented item from the allowed definitions
produce the normal successful-result shape
otherwise
use the ordinary unpredictable rule
send the one result into the existing state update

The controlled known result must come from the same allowed definitions as a normal result. After the decision, the normal and controlled paths must update the same state properties and use the same render function. This proves the application behavior after the decision without creating a second version of the feature.

Record one route at a time:

  1. Restore the complete starting state.
  2. Set controlled no-result mode. Perform the action twice and record the same no-result outcome twice.
  3. Restore the starting state.
  4. Set controlled known-result mode. Perform the action twice and record the same allowed result twice.
  5. Restore the normal setting and reload the page.
  6. Inspect the source setting. Perform the action in normal mode and record evidence that the ordinary rule ran.

Do not change the ordinary probability, product data, or business rule to force a test result. Do not mark the test complete until the report records the normal setting and the restoration result.

Add this structure to interactive-test-report.md:

interactive-test-report.md — starting structure
# Interactive test report: Product name
## Tested build
- Commit:
- Browser and version:
- Operating system:
- Test date:
- Launch method:
- Test data: Synthetic values only
## Product contract
- Primary interaction:
- Invalid-input result:
- Successful state result:
- Secondary state change:
- Status result:
- Focus result:
- Reload boundary:
## Reset procedure
1. Add exact steps that restore the documented starting state.
## Scope
Included: scripted interaction, keyboard, focus, visible and programmatic
status, responsive and zoom behavior, saved source validation, and Console.
Outside this report: full assistive-technology user testing, network and
server load, security assessment, and browsers not named above.
## Status labels
- Not run: No current evidence.
- Pass: Actual result matches expected result.
- Issue: A repeatable actual result conflicts with expected result.
- Blocked: The named condition cannot be tested; the missing input is recorded.
- Accepted limitation: A verified scope or tool limit remains and its effect is recorded.
## Scripted cases
Add the required matrix from the lesson.
## Exploratory charter
Add after the scripted cases pass or have evidence-backed statuses.
## Defects and retests
Add one section for each confirmed defect.
## Final evidence
- Final tested commit:
- Required cases:
- Repaired defects:
- Accepted limitations:
- Outside scope:
- Next active quality item:

Replace every placeholder that describes the current build and contract. Keep all test statuses Not run until you perform their exact paths.

Checkpoint: Every path has a stable starting point

What now works
The report identifies the build and environment, states the product contract and scope, defines one repeatable reset procedure, and has stable evidence statuses.
Files changed
interactive-test-report.md, quality-plan.md
What remains
Add and execute the fifteen scripted paths before exploratory testing or source repair.
Next action
Add the test matrix, reset the application, and run START-01 without changing source.
If it does not work
If reset steps do not reproduce one starting state, classify later cases as Blocked and repair or document the reset boundary before testing transitions from it.

Add this matrix under Scripted cases. Replace generic product terms with actual labels and state values before testing.

ID Reset or precondition Action Expected result Actual result Status and evidence
START-01 Reset procedure Inspect initial controls, records, state text, and Console Documented initial state appears with no startup error Not run Not run
INPUT-01 Reset procedure Submit an empty primary input No record enters state; useful error appears; input is invalid and focused Not run Not run
INPUT-02 Reset procedure Submit spaces only Result matches the empty-input contract Not run Not run
INPUT-03 Reset procedure Submit Run narrow viewport check Exactly one record and one item appear; status updates; input clears Not run Not run
INPUT-04 Reset procedure Submit the same valid value twice Each permitted action has one documented result; no event is duplicated Not run Not run
INPUT-05 Reset procedure Submit a long sentence and RESPONSIVE-INTERACTION-2026 Required text remains present, readable, and contained Not run Not run
SAFE-01 Reset procedure Submit <strong>Review</strong> Literal text appears; input is not parsed as a new element Not run Not run
STATE-01 Reset, then add one valid record Change the new record’s secondary state Correct record and status update once Not run Not run
STATE-02 Continue from STATE-01 Reverse the same state twice Record, control, and summary agree after each change Not run Not run
KEY-01 Reset procedure; pointer aside Reach and operate every required control with keyboard Same outcomes are available without pointer input or timed keystrokes Not run Not run
FOCUS-01 Reset procedure Run invalid, valid, and secondary-state paths with keyboard Focus remains visible and moves to each documented target Not run Not run
STATUS-01 Reset procedure Trigger error, success, and state-summary changes Visible text updates; appropriate role or property exposes status without taking focus Not run Not run
RES-01 Reset procedure; viewport near 320px Run primary and secondary interactions Content and focus remain visible; no unintended horizontal scroll Not run Not run
ZOOM-01 Reset procedure; normal viewport at 200% zoom Run primary and secondary interactions Content reflows; controls and status remain visible and operable Not run Not run
SRC-01 Saved source and reset state Validate HTML; review CSS diagnostics in VS Code; run every interaction with Console open No unresolved author error or interaction-triggered red Console error remains Not run Not run

The expected result is the test oracle: the rule used to decide whether the actual result passes. Make it specific enough that two people can compare the same observation with the same rule.

Record the actual result before writing Pass or Issue. Evidence can be exact visible text, DOM attributes, record counts, focused element, Console messages, source-check messages, or an image when the image adds information that text cannot preserve.

Move no additional issue to In progress. Use the active core-interaction issue while you run START-01 through STATE-02.

For each independent case:

  1. Perform the reset procedure.
  2. Confirm the named precondition.
  3. Run only the listed action.
  4. Observe the state, DOM, visible text, focus, and Console before another action.
  5. Write the actual result in the report.
  6. Compare actual with expected and assign the evidence status.
  7. Stop at the first confirmed Issue until it has a focused record.

Compare counts, identity, and rendered output

Section titled “Compare counts, identity, and rendered output”

A visible item count can look correct while the wrong record changed. For state paths, inspect:

  • the number of state records before and after the action when the app exposes that state for debugging;
  • the stable identity of the record the event is meant to change;
  • the control value or checked state;
  • the corresponding rendered label;
  • the derived summary; and
  • any unrelated record that must remain unchanged.

Do not add production debugging output only to make the test pass. A temporary local log can support an investigation, but remove it or document it before the tested commit.

For SAFE-01, inspect the rendered DOM after submitting <strong>Review</strong>.

Expected evidence:

  • the visible label contains the angle brackets and text;
  • no new strong element appears inside that label;
  • no script or markup from input executes; and
  • the Console contains no related error.

This path checks the documented textContent boundary. It is not a complete security audit.

Checkpoint: Core state paths have actual evidence

What now works
START-01, INPUT-01 through INPUT-05, SAFE-01, and STATE-01 through STATE-02 contain reset conditions, actual state and DOM results, statuses, and evidence; any confirmed failure has a focused issue.
Files changed
interactive-test-report.md, active core-interaction GitHub issue
What remains
Test keyboard, focus, status, narrow layout, zoom, source, and Console paths, then run the exploratory charter.
Next action
Put the pointer aside, reset the application, and run KEY-01 from the browser address bar.
If it does not work
If state and DOM disagree, record both values and the action that separated them. Do not repair the renderer until the same path reproduces the mismatch.

Move the core-interaction issue to Done only when its cases meet the issue close condition. Close it, then move QA: Verify keyboard use and visible focus to In progress.

For KEY-01:

  1. Put the pointer aside.
  2. Start from the browser address bar.
  3. Use Tab and Shift + Tab through every required control.
  4. Enter text with the keyboard.
  5. Use the control’s native activation key, such as Enter for form submission and Space for a focused checkbox or toggle button.
  6. Confirm the same product outcome available through pointer input.
  7. Confirm that no step requires several keys within a narrow time limit.

For FOCUS-01, record the focused element after:

  • empty-input validation;
  • a valid primary action;
  • one secondary state change; and
  • a render that replaces interactive DOM elements.

The focused element must be visible and useful for the next action. “Focus exists somewhere” is not enough.

You can enter document.activeElement in the Console to inspect the current element. Use the visible indicator and the DOM result together; the Console value does not replace the keyboard observation.

Inspect status changes without moving focus

Section titled “Inspect status changes without moving focus”

For STATUS-01, trigger each message while focus stays on the control that owns the current task.

Record:

  • the complete visible status text;
  • whether an appropriate semantic element, role, or ARIA property exposes it in the accessibility tree;
  • whether the message updates after the relevant action; and
  • whether the program avoids moving focus to a noninteractive status message.

This source and accessibility-tree inspection does not prove how every assistive technology will announce the message. Record that broader testing remains outside scope unless you perform it with a named tool and method.

Close the keyboard-and-focus issue only after KEY-01, FOCUS-01, and STATUS-01 meet their expected results. Move QA: Verify responsive layout and zoom to In progress.

Use responsive design mode and record the actual viewport size. Run the invalid, valid, secondary-state, and long-input paths.

Confirm that:

  • no required content or control is outside the viewport;
  • no unintended horizontal page scrollbar appears;
  • labels, status text, long input, and buttons wrap or size without overlap;
  • the focused element and complete focus indicator remain visible; and
  • a state update does not scroll to an unrelated region.

Return to the normal page view and set browser zoom to 200%. Repeat the same interaction paths.

Record the actual visible result. Do not use a narrow viewport setting, CSS zoom, or operating-system magnification as a substitute for the named browser-zoom condition.

Close the responsive issue after RES-01 and ZOOM-01 pass or have an evidence-backed status. Move QA: Check HTML, CSS, and the JavaScript Console to In progress.

For SRC-01:

  1. Save every source file.
  2. Validate the relevant HTML with the Nu Html Checker used in Level 1.
  3. Review the relevant CSS in the VS Code Problems panel.
  4. Classify source-check messages as author errors, context warnings, verified tool limitations, or unresolved.
  5. Reload with the Console open and preserve startup messages.
  6. Run every required interaction path once.
  7. Record each red error, first application stack frame, action, and state.

Do not replace current standard syntax only to clear a tool message that comes from a checker or editor limitation. Verify a suspected tool limitation against an official language source.

Scripted tests check known expectations. Exploratory testing combines learning, test design, and execution while the tester follows one bounded question.

Use this charter after the scripted cases pass or have evidence-backed statuses:

interactive-test-report.md — exploratory charter
## Exploratory charter: event, state, and render consistency
- Goal: Find a sequence where one user action, stored state, rendered control,
visible status, and focus no longer agree.
- Starting state: Use the documented reset procedure.
- Variation 1: Activate the same state control rapidly four times.
- Variation 2: Add one long value, then change its secondary state twice.
- Variation 3: Alternate invalid and valid primary actions without reloading.
- Stop condition: Complete all three variations or stop at the first
repeatable defect.
- Evidence: Record the exact sequence, actual final state, DOM result,
status text, focused element, and Console result.

The charter is not an invitation to test everything. It has one risk, three variations, and a stop condition. Add a new charter later when a different risk needs investigation.

Use the same reset, action, and environment before deciding what happened:

Result Evidence state Next action
Confirmed defect Same conflict occurs twice from the same reset Create a focused defect issue and investigate
Intermittent observation Conflict does not repeat consistently Keep both observations and collect the missing condition
Blocked test Required input, access, environment, or reset is unavailable Record the missing condition, owner, and next question
Accepted limitation Verified scope or tool boundary explains the result and effect Preserve the evidence and consequence
Expected behavior Actual matches the product contract Record Pass; do not change source

Do not call a failure intermittent only because the first reproduction attempt differs. Record what changed between runs: input, state, timing, viewport, focus, browser, or source.

If a defect is confirmed, pause the active QA issue as Blocked. Create one defect issue, add it to the project, and move only that defect to In progress.

Use this defect record:

GitHub issue — confirmed interaction defect
## Observed conflict
State which values disagree.
## Environment and tested commit
- Commit:
- Browser and version:
- Operating system:
## Reproduction
1. Reset to the named starting state.
2. Perform the exact input and action sequence.
3. Inspect the named state, DOM, status, focus, and Console values.
## Expected result
State the product-contract result.
## Actual result
State both matching reproductions.
## Initial hypothesis
Name one likely cause and the evidence that would confirm or reject it.
## Retest set
- Original path:
- Related path 1:
- Related path 2:
## Close condition
The original path and related paths pass on one identified repair commit.
The report contains before-and-after evidence.

Then use this sequence:

  1. Reproduce once more without editing source.
  2. Trace the first point where expected and actual values separate.
  3. State one hypothesis.
  4. Make the smallest change that tests that hypothesis.
  5. Repeat the original reset and path.
  6. Run the related paths named before the repair.
  7. Record before-and-after evidence.
  8. Commit and push the focused repair.
  9. Close the defect only when its close condition is met.
  10. Return the paused QA issue to In progress and continue its remaining paths.

For the reference task tracker:

  • Expected: Changing a task checkbox re-renders the list and restores focus to the checkbox for the same task ID.
  • Actual: The summary changes, but document.activeElement becomes body after the render.
  • First separation: State and summary are correct; focus restoration is missing after replacement DOM nodes are appended.
  • Hypothesis: The change handler calls renderTasks() without the changed task ID, or the renderer never focuses the matching replacement checkbox.
  • Focused check: Inspect the handler argument and the task.id === focusTaskId branch before editing unrelated CSS.
  • Retest set: Changed checkbox, another checkbox, valid form submission, backward keyboard path.

This trace does not prescribe a repair for a different architecture. Follow the evidence in the tested application.

Checkpoint: Unexpected behavior has an evidence path

What now works
The exploratory charter has complete evidence; every unexpected result is classified; confirmed defects, if any, have a focused issue, tested hypothesis, repair commit, same-path retest, and related regression results.
Files changed
interactive-test-report.md, GitHub QA and defect issues, focused repair files when needed
What remains
Close the completed QA issues, record the final tested commit and limits, commit the report, and preserve the next quality action.
Next action
Run the complete scripted matrix once on the final candidate commit, then complete Final evidence.
If it does not work
If repair attempts multiply, return to the last confirmed commit, reproduce the original conflict, and narrow the first point of divergence before another edit.

After all confirmed repairs are committed, reset the application and run all fifteen scripted cases on the candidate commit. Do not combine old pass evidence from one commit with repaired source from another.

Complete Final evidence:

interactive-test-report.md — final evidence
## Final evidence
- Final tested commit: FULL-COMMIT-HASH
- Required cases: 15 Pass, or list each evidence-backed non-Pass status
- Exploratory charter: Three variations complete, or stopped at DEFECT-ID
- Repaired defects: None, or issue IDs and repair commits
- Accepted limitations: None, or exact limits and effects
- Outside scope: Named browsers, assistive technologies, network, server load,
and security checks not performed
- Next active quality item: Improve technical SEO; final regression remains Ready

Close the source-and-Console issue only when its report evidence passes. The project should now show the four executed QA issues as Done, no defect left active, and QA: Run final regression and review evidence as Ready. Final regression remains open because the SEO and analytics lessons will change the product after this test cycle.

Update the resume note in quality-plan.md with the tested commit and exact next action.

Self-check

Complete these checks against the required result.

  1. Confirm that the report identifies one full commit, environment, launch method, date, and synthetic-data boundary.
  2. Follow the reset procedure and confirm that it restores the documented state without an undocumented tool action.
  3. Compare every expected result with the product contract rather than the current implementation.
  4. Confirm that all fifteen cases have actual results, statuses, and evidence from their named conditions.
  5. Repeat empty, whitespace-only, valid, repeated, long, and HTML-looking input paths and confirm that state and DOM results agree.
  6. Use only the keyboard and confirm the primary and secondary outcomes, visible focus, intended focus targets, and status updates.
  7. Repeat the primary interaction near 320px and at 200% browser zoom and confirm no content, control, status, or focus result is lost.
  8. Confirm that HTML, CSS, startup, and interaction-triggered Console messages are resolved or evidence-backed.
  9. Inspect the exploratory charter and confirm that it stopped after its three named variations or the first confirmed defect.
  10. Open every defect record and confirm two reproductions, a tested hypothesis, focused change, original-path retest, and related regression evidence.
  11. When no defect was confirmed, confirm that the report states no repair was required and does not claim broader quality than the tested scope.
  12. Confirm that the board has no more than one In progress item and keeps final regression Ready for later product changes.
  13. Run git status and confirm that report and repair commits are pushed and the working tree is clean.
Symptom Likely cause Focused check
Test passes only after previous case Cases share state without a reset Restore the named precondition before independent paths
Expected result matches current bug Behavior was copied instead of derived Return to the product contract and assignment requirement
One click creates two records Listener is registered more than once or the action fires twice Count event results and inspect registration location
Correct summary, wrong record Handler uses position or stale identity Compare stable IDs before and after render
Keyboard changes state but focus vanishes Render replaces the focused node without restoration Inspect activeElement and the replacement target
Status is visible but not exposed No suitable semantic role or property identifies the update Inspect the accessibility tree without moving focus
Failure cannot be repeated Reset, timing, environment, or input differs Record both runs and isolate the changed condition
Controlled result remains after testing The development setting was not restored or verified Restore the normal value, reload, inspect the setting, and repeat one normal path
Repair changes several systems Hypothesis and source boundary are too broad Restore the last baseline and test one cause
Old passes remain after a fix Regression evidence belongs to an earlier commit Rerun the focused set on the repair commit
Everything is marked Pass Actual evidence was not written before status Reopen each row and record observation first

Commit focused source repairs separately after their retests. When the final matrix is complete, record the evidence files:

Commit and push interactive test evidence
git status
git diff -- interactive-test-report.md quality-plan.md
git add interactive-test-report.md quality-plan.md
git diff --staged
git commit -m "Document interactive application tests"
git push
git status

Confirm that GitHub shows the final report commit after any focused repair commits and that the local working tree is clean.

The required lesson is complete when one identified commit passes the fifteen scripted paths, the exploratory charter is bounded and recorded, confirmed defects have focused retests, and the board preserves final regression for later product changes.

Continue to Improve technical SEO to inspect how crawlers discover, interpret, and select the application’s public pages.

If you stop here, leave yourself this resume note: The interactive test report identifies the final tested commit and open limits. Next, open the technical SEO lesson and record the current crawl and index signals before changing them.