The Frontend Audit Guide for SQA: 22 Tests in Plain English
A QA field guide: 22 plain-English tests for catching performance, interactivity, data-integrity, accessibility, and code-quality bugs — with checklists and copy-ready bug reports.
Jun 2, 2026
•8 min read
A QA field guide: 22 plain-English tests for catching performance, interactivity, data-integrity, accessibility, and code-quality bugs — with checklists and copy-ready bug reports.
A step-by-step field guide for catching performance, interactivity, data-integrity, accessibility, and code-quality bugs — written in plain English, with validation checklists and copy-ready bug-report templates you can paste straight into your tracker.
Part 1 — Making It Feel Fast
Performance tests: images, loading, and code delivery (Tests 1–6).
1 · Image Jumping (Cumulative Layout Shift)
Have you ever tried to click a button, but right before you click it an image finishes loading and pushes the button down, making you click the wrong thing? That's what this is.
How to test:
- Open Chrome DevTools (right-click → Inspect) → Network tab → change 'No throttling' to Slow 3G.
- Refresh the page and hover your mouse over a button that sits directly below an image.
- Watch what happens as the image finishes loading.
Pass / Fail
FAIL if the button gets pushed away from your cursor when the image loads.
Bug report (copy & paste)
When the image loads, it pushes the whole page down. Users might click the wrong button by accident. The developer needs to set a fixed width/height on the image.
2 · Lazy Loading
If a page has 50 pictures, the browser shouldn't download the ones at the very bottom until the user actually scrolls down to look at them.
How to test:
- Open the Network tab.
- Load a long article with lots of images. Do NOT scroll down.
- Watch how many image files download immediately.
Pass / Fail
FAIL if 50 image files download right away. Only the 2–3 visible on screen should load first.
Bug report (copy & paste)
All images on the page download immediately, wasting the user's data and slowing the page. The developer needs to add lazy loading to the off-screen images.
3 · Background Image Processing (Async Decoding)
When a massive 4K picture loads, it takes a lot of CPU brainpower to process it, which can freeze the user's screen for a split second.
How to test:
- Scroll very fast down a page until a huge banner image comes into view.
- Watch closely for any stutter or freeze the moment the image appears.
Pass / Fail
FAIL if the scrolling suddenly stutters or freezes for a second when the image appears.
Bug report (copy & paste)
The screen freezes for a split second when the large background image appears. The developer needs to decode the image in the background (using decoding='async').
4 · Link Hover Pre-loading (Prefetching)
When a user hovers their mouse over a link, the website should secretly download the next page in the background before they even click, making navigation feel instant.
How to test:
- Open the Network tab.
- Hover your mouse over the 'Settings' button for 1 second — do not click it.
- Check if anything new appears in the Network tab during hover.
Pass / Fail
FAIL if nothing downloads during hover. Clicking the link should feel instant with no white screen.
Bug report (copy & paste)
Hovering over links doesn't secretly pre-load the next page. When I click Settings, there is a 1-second white screen. The developer needs to add link prefetching.
5 · The Ugly Font Flash (Preconnect)
Sometimes a website loads with a boring system font like Times New Roman, then half a second later 'snaps' into the custom font. This looks very unprofessional.
How to test:
- Check 'Disable Cache' in the Network tab.
- Hard refresh the page (Cmd+Shift+R or Ctrl+Shift+R).
- Watch the text closely as the page loads.
Pass / Fail
FAIL if the text briefly looks ugly or changes shape before settling into the correct font.
Bug report (copy & paste)
The custom fonts take too long to load, causing text to flash an ugly fallback font for half a second. The developer needs to prioritize font loading (Preconnect).
6 · Sending Too Much Code (Code Splitting)
A regular user shouldn't have to download the code that runs the Admin Dashboard, because they aren't an admin. The code should be split into separate chunks.
How to test:
- Log in as a normal (non-admin) user.
- Open the Network tab and click on the largest JavaScript file downloaded.
- Press Ctrl+F and search for words like 'AdminDashboard'.
Pass / Fail
FAIL if admin-specific code is found inside the normal user's downloaded JavaScript file.
Bug report (copy & paste)
Normal users are being forced to download code meant for admins, making the app slow. The developer needs to split the code so each role only downloads what it needs.
Part 2 — Making It Feel Smooth
Interactivity tests: input handling and UI responsiveness (Tests 7–12).
7 · Search Lag (Debouncing)
If you type 'apple' into a search bar, the website shouldn't search for 'a', then 'ap', then 'app'. It should wait until you finish typing to do the search.
How to test:
- Open the Network tab.
- Type quickly into the search bar — e.g. 'macbook pro' — without pausing.
- Count how many API requests appear in the Network tab.
Pass / Fail
FAIL if 10 separate API requests fire. It should send only 1 request after you stop typing.
Bug report (copy & paste)
Typing fast causes the search bar to lag and sends too many requests. The developer needs to debounce the search bar to wait 300 milliseconds before searching.
8 · Scroll Lag (Throttling)
If a scroll tracker runs 1,000 times per second (e.g. to change a header's colour), your computer will lag. It should be capped to run far less frequently.
How to test:
- Scroll up and down the page furiously using your mouse wheel or trackpad.
- Pay close attention to whether the scrolling feels choppy or smooth throughout.
Pass / Fail
FAIL if the scrolling feels choppy or stuttery.
Bug report (copy & paste)
Scrolling fast causes the screen to lag and stutter. The scroll tracker is running too many times per second. The developer needs to throttle it.
9 · Losing Your Place (Scroll Restoration)
If you scroll down 50 items, click an item, then click the Back button, you shouldn't be dumped back at the very top of the list.
How to test:
- Scroll deep down into a long list.
- Click on any item in the list.
- Click the browser's Back arrow and observe where the scroll position lands.
Pass / Fail
FAIL if it sends you back to the very top of the list instead of where you were.
Bug report (copy & paste)
Clicking Back forgets where I was scrolled. The developer needs to use the native History API for scroll restoration.
10 · Faking Instant Clicks (Optimistic UI)
When you click 'Like' on Instagram, the heart turns red instantly; it doesn't wait for the server. If the internet fails 3 seconds later, it quietly reverts.
How to test:
- Throttle the network to Slow 3G in the Network tab.
- Click a 'Like' or 'Bookmark' button.
- Time how long before the button visually changes state.
Pass / Fail
FAIL if the button makes you wait 3–4 seconds before it changes colour.
Bug report (copy & paste)
Buttons make you wait for the server before they change colour, which feels slow and broken. The developer needs to make them update instantly (Optimistic UI).
11 · Hiding Loading Spinners (Stale-While-Revalidate)
If you visit a dashboard, leave, and come back 5 minutes later, it shouldn't show a blank loading screen again. It should instantly show old data while fetching updates in the background.
How to test:
- Visit a data-heavy page and let it fully load.
- Click away to another page.
- Navigate back to the first page and observe what appears first.
Pass / Fail
FAIL if you see a big loading spinner on your second visit to the same page.
Bug report (copy & paste)
Visiting a page twice shows a loading spinner the second time. The developer should show old cached data instantly while refreshing in the background.
12 · Too Many Items (Virtualization)
Rendering a table with 10,000 rows will crash the browser. Only the ~20 rows visible on your screen should be drawn at any time; the rest are swapped in as you scroll.
How to test:
- Open a list or table with thousands of items.
- Open DevTools → Elements tab.
- Count how many <tr> or list-item tags exist in the HTML panel simultaneously.
Pass / Fail
FAIL if you see thousands of <tr> tags all at once in the DOM.
Bug report (copy & paste)
The page freezes because it's trying to draw 10,000 items at once. The developer needs to virtualize the list to only render items that are currently visible.
Part 3 — Data Bugs & Weird Glitches
Data integrity: duplicates and rendering conflicts (Tests 13–15).
13 · Double-Click Protection (Idempotency)
An impatient user mashing the 'Submit Payment' button 5 times shouldn't be charged 5 times. The system must handle repeated submissions safely.
How to test:
- Fill out a 'Create Item' or similar form.
- Rapidly double-click or mash the Submit button multiple times.
- Check the resulting list or database for duplicate entries.
Pass / Fail
FAIL if multiple identical items are created in the database.
Bug report (copy & paste)
Rapidly clicking Submit creates duplicate items. The developer must disable the button after the first click and protect the backend against repeated requests (Idempotency).
14 · Server/Browser Disagreement (Hydration Mismatch)
Sometimes the server thinks it's 12:00 PM, but the user's browser thinks it's 8:00 AM. When the page loads, they 'fight', causing the clock to visually glitch on screen.
How to test:
- Hard refresh the page (Cmd+Shift+R).
- Stare closely at things like timestamps, dates, or randomly generated numbers.
- Watch if any text visually jumps or flashes right after the page finishes loading.
Pass / Fail
FAIL if any text flashes or jumps to a different value at the moment the page completes loading.
Bug report (copy & paste)
The clock flashes '12:00' before jumping to '8:00'. The server and the browser are disagreeing on the initial value (Hydration Mismatch).
15 · Wasting Math (Memoization)
Typing one letter into a search box shouldn't force the browser to re-calculate and re-draw the entire navbar and footer; only the search-related components should update.
How to test:
- Install the React Developer Tools browser extension.
- Open DevTools → Profiler tab → click Record.
- Type one letter into a search box, then click Stop.
- Look at the flame chart for unexpected yellow/green component re-renders.
Pass / Fail
FAIL if hundreds of unrelated components light up, indicating they all re-rendered unnecessarily.
Bug report (copy & paste)
Typing one letter causes the entire page to re-calculate itself. The developer needs to cache the components that aren't changing (Memoization).
Part 4 — Accessibility & Keyboard
Keyboard navigation and focus management (Tests 16–17).
16 · Trapping the Keyboard (Focus Trapping)
If a popup is open, a keyboard user shouldn't be able to press Tab and accidentally interact with buttons hidden behind the popup.
How to test:
- Open a 'Confirm Deletion' or any modal popup. Put your mouse away.
- Press Tab 10 times and watch the blue focus-highlight box.
- See if focus stays inside the popup or escapes to background elements.
Pass / Fail
FAIL if the focus highlight escapes the popup and starts highlighting elements on the background page.
Bug report (copy & paste)
When a popup is open, I can still interact with the background page using Tab. The developer needs to trap keyboard focus inside the popup.
17 · The Never-Ending Dropdown (Roving Tabindex)
A keyboard user shouldn't have to press Tab 50 times to get past a long dropdown menu. The whole list should be one Tab stop, with arrow keys navigating inside.
How to test:
- Press Tab to move focus into a large custom dropdown list.
- Try to Tab past it to reach the next form element below.
- Count how many Tab presses are needed to escape the dropdown completely.
Pass / Fail
FAIL if you must Tab through every single item. It should be one Tab to enter, arrow keys to browse, one Tab to exit.
Bug report (copy & paste)
I am forced to press Tab 50 times to escape the dropdown. The developer needs to implement Roving Tabindex so arrow keys navigate the list instead.
Part 5 — Code Audits
Behind-the-scenes checks, usually via code review or tooling (Tests 18–22).
18 · Shaking the Tree (Tree Shaking)
If a developer imports a massive 500-page library just to use one sentence from it, the bundler should delete the other 499 pages before shipping it to users.
How to test:
- Run Webpack Bundle Analyzer (or equivalent) on the production build.
- Look for large blocks of library code flagged as unused.
- Compare bundle size with and without the library to assess impact.
Pass / Fail
FAIL if large chunks of unused library code are present in the production bundle.
Bug report (copy & paste)
The bundle contains large amounts of unused library code. The developer needs to configure Tree Shaking properly in the bundler so unused code is stripped before shipping.
19 · Erasing Test Code (Dead Code Elimination)
Developers write console.log('This is broken!') while testing. This debug code should be automatically removed when the app is shipped to real users.
How to test:
- Open the live production website.
- Open DevTools → Console tab.
- Browse around various pages and look for any developer debug messages printing.
Pass / Fail
FAIL if any console.log debug messages appear in the browser console on the live site.
Bug report (copy & paste)
Developer debug messages are visible in production. The build pipeline needs to strip all console.log and dead code before deployment.
20 · Fake Buttons (Polymorphic Components)
Sometimes a developer designs a pretty blue 'Button', but uses it as a link to another website. It must look like a button but use the correct <a> HTML tag so search engines can read it.
How to test:
- Find a styled button that links to an external URL.
- Right-click it and choose 'Inspect'.
- Check which HTML tag is actually used in the markup.
Pass / Fail
FAIL if the HTML tag is <button> instead of <a href='...'> for an external link.
Bug report (copy & paste)
External links are marked up as <button> instead of <a>. This breaks SEO and keyboard accessibility. The developer needs to use polymorphic components.
21 · Reusable Building Blocks (Inversion of Control)
Instead of building 4 different Button components just because they have different icons, you build 1 Button and let the caller pass in whatever icon they need.
How to test:
- Browse the component folder in the codebase.
- Search for near-duplicate names like ButtonWithLeftArrow, ButtonWithRightArrow, ButtonWithSpinner.
- Compare their code for meaningful differences vs. minor copy-paste variations.
Pass / Fail
FAIL if multiple near-identical components exist that only differ by a small prop like an icon or label.
Bug report (copy & paste)
There are 4 nearly-identical Button components. They should be merged into one component that accepts an icon prop (Inversion of Control).
22 · Designing for the Worst (Graceful Degradation)
The website should still show something useful even if the user is on an ancient phone or if JavaScript breaks completely; never a blank white screen.
How to test:
- Open Chrome DevTools → Settings (gear icon) → Preferences.
- Check 'Disable JavaScript'.
- Reload the page and observe what is displayed.
Pass / Fail
FAIL if the result is a completely blank white screen with no content or message.
Bug report (copy & paste)
Disabling JavaScript results in a blank white screen. The site should display a basic layout or error message even without JS (Graceful Degradation).
