Chrome extension JavaScript error evidence can make a bug report much easier to reproduce. Instead of asking a developer to guess what happened from a screenshot alone, QA can attach the page URL, title, timestamp, recent runtime error, unhandled promise rejection, and short tester note in one clean block.

This tutorial shows a practical Manifest V3 workflow for QA engineers, SDETs, automation testers, and AI testing learners. It does not claim to replace DevTools, observability tools, or full session replay. The goal is smaller and more useful: collect the most relevant browser-side error evidence while a tester is exploring a web app, then paste it into Jira, Azure DevOps, GitHub Issues, or an AI bug triage prompt.

Why JavaScript Error Evidence Helps QA

Many UI bugs are reported with a visible symptom: a button does nothing, a spinner never finishes, a modal closes unexpectedly, or a form silently fails. The missing detail is often the browser-side error behind the symptom. A focused evidence helper gives QA a repeatable way to capture that context without manually copying from multiple places.

For example, a good bug report can include:

  • The page URL and document title.
  • The tester’s browser viewport and timestamp.
  • The visible symptom and expected result.
  • The most recent JavaScript runtime error or unhandled promise rejection.
  • Any tester note about data, account role, feature flag, or environment.

That evidence helps developers decide whether the next step is a code fix, a data correction, an API investigation, or a test environment check.

What the Chrome Extension Should Capture

Keep the first version intentionally small. A lightweight extension should capture page runtime errors and unhandled promise rejections through a content script, pass the data to an extension context with Chrome messaging, and store recent records with the Chrome Storage API.

Use this evidence model as a starting point:

{
  "type": "runtime_error",
  "message": "Cannot read properties of undefined",
  "source": "checkout.js",
  "line": 42,
  "column": 13,
  "url": "https://staging.example.com/checkout",
  "title": "Checkout - Staging",
  "capturedAt": "2026-06-27T10:15:30.000Z",
  "testerNote": "Clicked Apply Coupon after entering expired code."
}

Important limitation: this workflow should be described as JavaScript error evidence, not a complete DevTools console export. A content script can listen for runtime error signals in the page, but it should not be sold as a way to capture every console log, all network failures, or every framework warning. If the team needs full console and network capture, pair this with DevTools, browser automation tracing, or application logging.

Manifest V3 Setup

Start with a minimal extension folder. The manifest declares the content script, extension action, and storage permission. Add host access only for the environments where QA will use the helper, such as staging or a local test domain.

{
  "manifest_version": 3,
  "name": "QA Error Evidence Helper",
  "version": "0.1.0",
  "description": "Collect JavaScript error evidence for QA bug reports.",
  "permissions": ["storage"],
  "host_permissions": ["https://staging.example.com/*"],
  "action": {
    "default_title": "QA Evidence",
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["https://staging.example.com/*"],
      "js": ["content.js"],
      "run_at": "document_start"
    }
  ]
}

For a tutorial screenshot, capture the extension loaded in chrome://extensions with Developer mode enabled, the target staging page, and the popup showing captured evidence.

Capture Runtime Errors in the Content Script

The content script should build a small record, add page metadata, and send it to the extension. Keep the record plain and JSON serializable because Chrome extension messaging and storage are designed around serializable data.

// content.js
function pageContext() {
  return {
    url: location.href,
    title: document.title,
    capturedAt: new Date().toISOString(),
    viewport: {
      width: window.innerWidth,
      height: window.innerHeight
    }
  };
}

function sendEvidence(payload) {
  chrome.runtime.sendMessage({
    kind: "qa_error_evidence",
    evidence: {
      ...pageContext(),
      ...payload
    }
  });
}

window.addEventListener("error", (event) => {
  sendEvidence({
    type: "runtime_error",
    message: event.message || "Unknown runtime error",
    source: event.filename || "unknown",
    line: event.lineno || null,
    column: event.colno || null
  });
});

window.addEventListener("unhandledrejection", (event) => {
  sendEvidence({
    type: "unhandled_rejection",
    message: String(event.reason && event.reason.message ? event.reason.message : event.reason)
  });
});

This is enough for a useful first pass. QA can later add a side panel, a copy button, or integration with the team’s bug template.

Store Recent Evidence for the Popup

A service worker or extension page can receive messages and persist the latest records. Keep a short list so the popup stays useful and does not become a noisy log viewer.

// service-worker.js
chrome.runtime.onMessage.addListener((message) => {
  if (message.kind !== "qa_error_evidence") return;

  chrome.storage.local.get({ evidence: [] }, (result) => {
    const next = [message.evidence, ...result.evidence].slice(0, 10);
    chrome.storage.local.set({ evidence: next });
  });
});

If you use this service worker, include it in the manifest. If you prefer a popup-only prototype, the popup can also read from chrome.storage.local and render the latest items.

Step-by-Step QA Workflow

  1. Load the unpacked extension in a Chrome test profile.
  2. Open the staging page or local page covered by the extension host permission.
  3. Clear old evidence from the popup before starting a new test session.
  4. Perform the user flow exactly as the test case or exploratory charter describes.
  5. When the visible bug appears, open the extension popup and review the captured record.
  6. Add a tester note with the action, data, role, and expected result.
  7. Copy the evidence into the bug report and attach the screenshot or screen recording.
  8. Reproduce once more if the issue is high severity or intermittent.

This keeps the extension tied to QA judgment. The extension gathers evidence; the tester still decides whether the issue is reproducible, severe, blocked by missing data, or better handled as an automation follow-up.

Try This Bug Report Template

Title: [Area] Action fails on [page] with JavaScript error

Environment:
- URL:
- Browser/profile:
- User role:
- Test data:

Steps to reproduce:
1.
2.
3.

Expected result:

Actual result:

JavaScript error evidence:
- Type:
- Message:
- Source:
- Line/column:
- Captured at:

Attachments:
- Screenshot:
- Screen recording:
- Network trace if needed:

Common Mistakes to Avoid

  • Calling it full console capture: be precise. This helper captures runtime errors and unhandled promise rejections, not every DevTools console event.
  • Requesting broad host permissions: keep permissions limited to test environments where the team actually needs the helper.
  • Storing sensitive data: avoid capturing tokens, passwords, cookies, or customer records in tester notes.
  • Skipping reproduction: one captured error is evidence, not proof that the root cause is known.
  • Saving unlimited logs: cap records and add a clear button so stale evidence does not pollute new reports.

Screenshot Checklist

  • Extension setup: capture the unpacked extension enabled in Chrome’s extension page.
  • Bug symptom: capture the web page state immediately after the failure.
  • Evidence popup: capture the latest error record with URL, timestamp, and message.
  • Bug report draft: capture the final report with steps, expected result, actual result, and attached evidence.

Best Practices for QA Teams

Use the helper in a separate Chrome profile so test extensions and staging permissions do not mix with personal browsing. Keep the source code in the same repository as other QA tools, and review it like any internal testing utility. Add a short README explaining what the extension captures, what it does not capture, and which environments are allowed.

When using AI to help summarize the evidence, paste only sanitized records. Ask the model to classify the failure, list missing evidence, and suggest next debugging steps. Do not ask it to invent a root cause from one client-side error.

FAQ

Can this replace DevTools for QA debugging?

No. It is a lightweight evidence helper. DevTools is still better for deep debugging, network inspection, performance analysis, and source-level investigation.

Can the extension capture every console log?

This tutorial should not be treated as complete console capture. It focuses on page runtime errors and unhandled promise rejections that are useful for bug reports.

Should QA use this in production?

Only with clear approval and strict privacy rules. Most teams should start in staging, QA, or local environments where host permissions and test data are controlled.

What should be included in the bug report?

Include reproducible steps, expected and actual results, environment details, the error evidence, and a screenshot or recording that shows the visible symptom.

References

Conclusion

Chrome extension JavaScript error evidence gives QA teams a repeatable way to attach useful browser-side context to bug reports. Keep the first version small, verify the captured record against the visible symptom, and use the evidence to speed up triage without overstating what the extension can prove.