<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GatekeeperQA</title>
    <description>The latest articles on DEV Community by GatekeeperQA (@gatekeeperqa).</description>
    <link>https://dev.to/gatekeeperqa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4152636%2F055026c9-187f-451a-99e8-dc632ec72cd7.png</url>
      <title>DEV Community: GatekeeperQA</title>
      <link>https://dev.to/gatekeeperqa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gatekeeperqa"/>
    <language>en</language>
    <item>
      <title>Your accessibility check failed in CI. Keep the evidence before fixing it.</title>
      <dc:creator>GatekeeperQA</dc:creator>
      <pubDate>Tue, 20 Oct 2026 17:00:58 +0000</pubDate>
      <link>https://dev.to/gatekeeperqa-team/your-accessibility-check-failed-in-ci-keep-the-evidence-before-fixing-it-3pf5</link>
      <guid>https://dev.to/gatekeeperqa-team/your-accessibility-check-failed-in-ci-keep-the-evidence-before-fixing-it-3pf5</guid>
      <description>&lt;p&gt;A red accessibility check tells you that a gate failed. The useful next questions are: which element triggered it, what page state was tested, and what evidence will you compare after the change?&lt;/p&gt;

&lt;p&gt;The workflow below keeps the original report, generates a separate retest report, and records manual observations alongside the automated result.&lt;/p&gt;

&lt;p&gt;Disclosure: I maintain GatekeeperQA, the tool used here. The local CLI runs without a hosted account. Hosted storage and review features are separate, with plan and retention limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep two reports, not one overwritten folder
&lt;/h2&gt;

&lt;p&gt;With Node.js 24 and an existing &lt;code&gt;package.json&lt;/code&gt;, install the pinned CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; @gatekeeperqa/cli@0.3.0
npx &lt;span class="nt"&gt;--no-install&lt;/span&gt; playwright &lt;span class="nb"&gt;install &lt;/span&gt;chromium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;gatekeeperqa.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"urls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3000/"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"failOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"critical"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"serious"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"warnOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"moderate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"minor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeoutMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start your app and wait until it is ready, then scan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;--no-install&lt;/span&gt; gatekeeperqa &lt;span class="nt"&gt;--config&lt;/span&gt; gatekeeperqa.json &lt;span class="nt"&gt;--output&lt;/span&gt; reports/before
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After implementing your change, run the same configuration against the updated app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;--no-install&lt;/span&gt; gatekeeperqa &lt;span class="nt"&gt;--config&lt;/span&gt; gatekeeperqa.json &lt;span class="nt"&gt;--output&lt;/span&gt; reports/after
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use fresh directories for each attempt. A setup failure must not leave you interpreting an older report as the latest result.&lt;/p&gt;

&lt;p&gt;Open each directory's &lt;code&gt;report.html&lt;/code&gt;. Completed scans also produce JSON, Markdown and JUnit XML. The CLI does not directly export a PDF.&lt;/p&gt;

&lt;p&gt;This configuration checks an explicitly listed page in its initially loaded state. It does not crawl the site or exercise login, dialogs, checkout, or other interactions. Use only targets you own or have permission to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  In GitHub Actions, save evidence before enforcing the gate
&lt;/h2&gt;

&lt;p&gt;If the scan exits nonzero, a normal subsequent step can be skipped. Separate evidence collection from the step that marks the job failed.&lt;/p&gt;

&lt;p&gt;GatekeeperQA's &lt;a href="https://gatekeeperqa.com/guides/developer-quick-start/" rel="noopener noreferrer"&gt;complete GitHub Actions setup&lt;/a&gt; installs the published package, captures the scan exit code, uploads available report artifacts, and then enforces that result.&lt;/p&gt;

&lt;p&gt;The important sequence is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the scan and retain its exit code.&lt;/li&gt;
&lt;li&gt;Upload the evidence even when the quality gate fails.&lt;/li&gt;
&lt;li&gt;Fail the job when the captured result requires it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do not turn a failed scan into a successful check just to keep the artifacts. Setup failures may have no report; inspect the logs in that case.&lt;/p&gt;

&lt;p&gt;In this CLI version, PASS and WARN exit with &lt;code&gt;0&lt;/code&gt;, FAIL with &lt;code&gt;1&lt;/code&gt;, and setup/configuration errors with &lt;code&gt;2&lt;/code&gt;. WARN still needs review. A gate result is not a compliance certificate.&lt;/p&gt;

&lt;p&gt;Also check what the workflow actually targets. Scanning production does not test code that exists only in a pull request. For PR validation, run the checked-out app or scan that PR's deployed preview after it is ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retest the same element and state
&lt;/h2&gt;

&lt;p&gt;Consider an icon-only button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Before: no accessible name --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"checkout"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;focusable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- icon --&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- After: visible text names the action --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"checkout"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;focusable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- icon --&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
  Continue to checkout
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an illustrative fix, not a customer assessment. A subsequent scan may stop reporting the naming issue, but that alone does not verify keyboard activation, focus behavior, or the resulting checkout state.&lt;/p&gt;

&lt;p&gt;Before closing the ticket, confirm that the button still exists and was included in the retest. Record the builds, URL, state, engine version and configuration. If those changed, explain the difference.&lt;/p&gt;

&lt;p&gt;Write “no longer detected in this scan” when that is what you established. Record keyboard and screen-reader observations separately; leave checks you did not perform marked as not tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the next reviewer a reproducible handoff
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original report and finding:
Original build:
Updated build:
Page and starting state:
Element location and rule:
Automated retest result:
Keyboard observations:
Screen reader/browser and observations:
Checks not performed:
Reviewer and date:
Remaining issues:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GatekeeperQA's hosted review workflow can keep saved notes and prepare an editable GitHub issue draft. Its private finding links open the specific element in a retained report. Those links require the report owner's sign-in; pasting one into a team ticket does not grant teammates access. Include appropriately redacted evidence that your intended reviewer can actually read.&lt;/p&gt;

&lt;p&gt;You can also keep this information in your existing tracker and retain the local reports. The workflow is useful independently of hosted storage.&lt;/p&gt;

&lt;p&gt;For a recorded walkthrough, see the &lt;a href="https://gatekeeperqa.com/guides/developer-walkthrough/" rel="noopener noreferrer"&gt;developer guide&lt;/a&gt;. For a quick look without registration, open the &lt;a href="https://gatekeeperqa.com/interactive-sample.html" rel="noopener noreferrer"&gt;interactive sample&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does your team's accessibility handoff break down: locating the element, reproducing the state, or deciding what has really been verified?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Prepared with AI assistance and checked against the project's CLI documentation and reporting implementation. Automated testing covers only part of accessibility; this is not a completed accessibility assessment.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>testing</category>
    </item>
    <item>
      <title>How to retest an accessibility fix and write useful evidence</title>
      <dc:creator>GatekeeperQA</dc:creator>
      <pubDate>Wed, 30 Sep 2026 16:35:05 +0000</pubDate>
      <link>https://dev.to/gatekeeperqa-team/how-to-retest-an-accessibility-fix-and-write-useful-evidence-o5f</link>
      <guid>https://dev.to/gatekeeperqa-team/how-to-retest-an-accessibility-fix-and-write-useful-evidence-o5f</guid>
      <description>&lt;p&gt;A developer fixes an unnamed button. The next scan no longer reports it. Before closing the ticket, what should you verify?&lt;/p&gt;

&lt;p&gt;Repeat the original check, test the interaction, and record the evidence. This fictional checkout example shows a focused retest workflow you can use in your existing issue tracker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with one clear fix
&lt;/h2&gt;

&lt;p&gt;An icon-only button has no accessible name. Adding visible text makes its purpose available to users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Before --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"checkout"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;focusable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- Cart icon --&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- After --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"checkout"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;focusable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- Cart icon --&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
  Continue to checkout
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The label addresses the naming problem. The application still needs to handle activation correctly. W3C's &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/button/" rel="noopener noreferrer"&gt;button pattern&lt;/a&gt; describes naming, keyboard activation and focus behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  1 Repeat the automated check
&lt;/h2&gt;

&lt;p&gt;Open the same page and state, such as a cart containing an item. Record the original and updated build identifiers. Keep the engine version and scan settings comparable, or document what changed.&lt;/p&gt;

&lt;p&gt;Confirm the retest completed and included the affected button. An empty cart, missing component or failed scan cannot verify the fix.&lt;/p&gt;

&lt;p&gt;A useful result is specific: “The accessible-name finding was not detected for the checkout button in the populated-cart state.” Use that wording only when your evidence supports it. Keep both reports so another reviewer can compare them.&lt;/p&gt;

&lt;h2&gt;
  
  
  2 Test the interaction
&lt;/h2&gt;

&lt;p&gt;For this button, check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard:&lt;/strong&gt; Reach it with Tab and Shift+Tab. Check visible focus and navigation order. Test Enter and Space separately from the same starting state; each should perform the intended action once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screen reader:&lt;/strong&gt; Check the announced name and button role. Record the browser, screen reader and versions used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resulting state:&lt;/strong&gt; Follow the checkout action. If it opens a dialog, check focus inside it and after closing it. Exercise applicable loading and error states, including how the user recovers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These checks verify a specific interaction. They do not establish whole-site accessibility. W3C explains why &lt;a href="https://www.w3.org/WAI/test-evaluate/" rel="noopener noreferrer"&gt;automated tools need human evaluation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Keep the evidence with the ticket
&lt;/h2&gt;

&lt;p&gt;Record each check as passed, failed or not tested according to what you actually verified. These statuses describe the page assessment. Keep automated results and manual observations separate.&lt;/p&gt;

&lt;p&gt;Use this compact template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page, component and starting state:
Original issue and evidence:
Expected behavior:
Fix build or commit:
Retest date and reviewer:
Browser and assistive technology versions:
Scan engine, settings and result:
Keyboard and screen-reader observations:
Other states checked and coverage gaps:
Remaining issues and linked tickets:
Decision against acceptance criteria:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the label is fixed but focus remains broken, record that remaining issue and assign it. Close the ticket against its acceptance criteria, with enough detail for another tester to repeat the check. Redact personal information and secrets before sharing evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the workflow to use
&lt;/h2&gt;

&lt;p&gt;I maintain GatekeeperQA. &lt;strong&gt;GatekeeperQA is ready to use for accessibility reporting and retest tracking&lt;/strong&gt;, with findings, reviewer notes, ticket copying and retest comparisons.&lt;/p&gt;

&lt;p&gt;Explore the free &lt;a href="https://gatekeeperqa.com/interactive-sample" rel="noopener noreferrer"&gt;interactive sample&lt;/a&gt; without signing up, or &lt;a href="https://scan.gatekeeperqa.com/" rel="noopener noreferrer"&gt;scan a public page&lt;/a&gt; you own or have permission to test. Usage and shared-capacity limits apply.&lt;/p&gt;

&lt;p&gt;Try it in your workflow. Your feedback helps shape what we build next.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: Drafted with AI assistance. This fictional example is not a client assessment.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
    </item>
  </channel>
</rss>
