How to Test Ratings And Reviews on Web (Complete Guide)
Ratings and reviews are often the first signal users see when deciding whether to trust a product, service, or content item. A broken star‑scale, a missing review text, or a misleading average can ins
Why Ratings and Reviews Testing Matters
Ratings and reviews are often the first signal users see when deciding whether to trust a product, service, or content item. A broken star‑scale, a missing review text, or a misleading average can instantly erode confidence and drive abandonment. In e‑commerce, a 0.1‑point drop in displayed rating can translate to a measurable dip in conversion rates; in media platforms, inaccurate aggregates can skew recommendation algorithms and affect content visibility.
From a quality perspective, the ratings‑and‑reviews subsystem touches many layers: UI rendering, state management, API contracts, caching, moderation pipelines, and accessibility. Because the component is frequently updated—new UI designs, A/B tests, localization swaps—regression risk is high. Moreover, the feature is a common target for abuse (spam, injection, credential stuffing) and for regulatory scrutiny (WCAG, GDPR, COPPA). Testing it thoroughly therefore protects both business metrics and user safety.
Core Components and Typical Failure Modes
UI Layer
- Star widget: clickable or tappable stars, half‑star support, hover/focus states, ARIA labels.
- Review list: infinite scroll or pagination, loading skeletons, empty state, “Show more” button.
- Write‑review modal/form: text area, rating selector, optional photo upload, submit button, validation messages.
Common UI bugs: stars not updating after AJAX success, focus trapped inside modal, missing focus outline, star icons misaligned on high‑DPI screens, review text overflowing container, modal not closing on ESC.
Service Layer
- Rating submission endpoint (
POST /api/reviews) expects JSON{rating: number, comment?: string, userId?: string, productId?: string}. - Rating aggregation endpoint (
GET /api/products/:id/ratings) returns{average: number, count: number, distribution: {1: n, 2: n, …}}. - Moderation queue (
GET /api/reviews?status=pending) for admin review.
Typical service bugs: race condition when multiple users submit simultaneously causing lost increments, incorrect average calculation due to integer division, stale cache serving outdated aggregates, missing authorization checks allowing any user to delete another’s review, SQL injection via comment field.
Data Layer
- Reviews table: columns
id, product_id, user_id, rating, comment, created_at, moderation_status. - Aggregates table (often denormalized):
product_id, average_rating, total_reviews, last_updated.
Data‑layer issues: missing foreign‑key constraints leading to orphan reviews, index starvation on product_id causing slow list loads, truncation of long comments, character‑set mismatches producing garbled text, GDPR‑right‑to‑be‑forgotten not cascading to aggregates.
Cross‑Cutting Concerns
- Accessibility: ARIA live regions for announcement of new reviews, sufficient contrast for star colors, keyboard operability of rating widget.
- Performance: lazy‑loading of review avatars, debounced scroll handling, server‑side pagination to avoid payload bloat.
- Security: CSRF tokens on submission, rate‑limiting per IP/user, sanitization of comment HTML, CSP to block inline scripts from user‑generated content.
Understanding these pieces lets you map test cases to the exact layer where a defect would surface.
Test Matrix: Happy Path, Error Paths, Edge Cases, Accessibility, Security
| Category | Sub‑case | Description | Expected Result | Automation Feasibility |
|---|---|---|---|---|
| Happy Path | HP‑1 | User selects 5 stars, writes a comment, clicks Submit. | Review appears in list, average updates, success toast shown. | High (e2e) |
| HP‑2 | User clicks a star, then changes selection to 3 stars before submitting. | Final rating is 3, UI reflects change instantly. | High | |
| HP‑3 | User opens write‑review modal, closes via ESC or backdrop click. | Modal dismisses, no draft saved. | High | |
| HP‑4 | Pagination: user scrolls to bottom, next page loads via infinite scroll. | New reviews appended, no duplicate entries. | Medium (needs scroll simulation) | |
| Error Paths | ER‑1 | Submit with empty comment when comment is required. | Inline validation error, form not submitted. | High |
| ER‑2 | Submit rating outside allowed range (e.g., 6). | API returns 400, UI shows error. | High | |
| ER‑3 | Network fails during submission (simulate 500). | Error toast, retry button appears, no partial UI update. | Medium (mock service) | |
| ER‑4 | Concurrent submissions from two tabs for same product. | Both reviews saved, average reflects sum, no lost increments. | Low (needs deterministic timing) | |
| Edge Cases | ED‑1 | Very long comment ( > 5000 chars ) submitted. | Accepted if limit permits, truncated UI with “Read more”. | High |
| ED‑2 | Comment containing HTML/script tags. | Sanitized, rendered as plain text. | High | |
| ED‑3 | User submits review, then immediately deletes account. | Review remains (or is anonymized per policy), average adjusts accordingly. | Medium | |
| ED‑4 | Rating widget used on high‑contrast OS theme. | Stars remain visible, contrast ratio ≥ 4.5:1. | Medium (axe) | |
| ED‑5 | Locale switches to right‑to‑left language (Arabic). | Stars align correctly, review text flows RTL. | Medium | |
| Accessibility | AC‑1 | Screen reader announces star rating change on focus. | ARIA live region updates with new value. | High (axe, jest-axe) |
| AC‑2 | Keyboard user can navigate stars via ArrowLeft/Right and select with Enter/Space. | Focus moves, selection updates, form submits on Enter. | High | |
| AC‑3 | Review list has sufficient touch target size (≥44 dp) for “Load more” button. | No missed taps on mobile viewport. | Medium (manual) | |
| AC‑4 | Color‑blind mode: star outlines distinguishable from filled state. | Visual difference persists. | Low (manual) | |
| Security / Privacy | SE‑1 | Submit review with SQL injection payload in comment. | Payload escaped, stored as plain text, no DB error. | High (OWASP ZAP) |
| SE‑2 | Submit review with XSS payload (). | Script neutralized, appears as text. | High | |
| SE‑3 | Missing CSRF token on POST /api/reviews. | Request rejected with 403. | High | |
| SE‑4 | Rate‑limit bypass: >10 submissions/min from same IP. | Subsequent requests receive 429 Too Many Requests. | Medium | |
| SE‑5 | GDPR request: delete user account. | All reviews tied to user ID are anonymized or removed; aggregates recomputed. | Low (needs data‑reset) |
*The table above is a starting point; extend it with product‑specific fields (e.g., photo upload, video embed) as needed.*
Tooling Comparison
| Tool | Primary Use | Language / Framework | Strengths for Ratings‑Reviews | Limitations |
|---|---|---|---|---|
| Cypress | End‑to‑end UI testing | JavaScript/TypeScript | Automatic waiting, easy stubbing of API calls, built‑in network control for error simulation. | Runs only in Chromium/Firefox/WebKit (no Safari native), limited cross‑origin iframe handling. |
| Playwright | End‑to‑end UI testing | JavaScript/TypeScript, Python, .Java, .NET | Multi‑browser (Chromium, Firefox, WebKit), powerful tracing, supports mobile device emulation, easy API mocking. | Slightly heavier setup, less mature community plugins than Cypress. |
| Jest + Testing Library | Unit / component testing | JavaScript/TypeScript | Fast, isolates UI logic, works with React/Vue/Svelte, good for rating widget unit tests. | Does not test full page interactions or SSR rendering. |
| axe‑core (via jest-axe, cypress-axe, playwright‑axe) | Accessibility audits | JavaScript | Detects WCAG violations, can be integrated in unit/e2e pipelines. | Only static analysis; does not test dynamic ARIA live regions without extra assertions. |
| Lighthouse | Performance & SEO audits | JavaScript (CLI) | Gives metrics on lazy‑loading, render‑blocking resources, useful for review list pagination. | Lab data only; needs CI integration for regression tracking. |
| OWASP ZAP | Dynamic security scanning | Java (stand‑alone) | Finds injection, CSRF, missing headers in rating endpoints. | Requires running server, can produce false positives; best as nightly job. |
| SUSATest Agent | Autonomous exploratory testing | Python (CLI) | Persona‑driven crawls that discover UI states missed by scripted tests, aggregates findings across sessions. | Not a replacement for deterministic regression suites; best as complementary discovery tool. |
Pick the stack that matches your team’s existing test infrastructure; many organizations combine Cypress (or Playwright) for UI flows, Jest for unit coverage, and axe for accessibility, then schedule ZAP and SUSATest runs nightly.
Manual Testing Step‑by‑Step
A disciplined manual session catches nuances that automated scripts may overlook, especially around visual polish and inter‑device behavior. Follow this checklist for each rating‑and‑reviews component.
1. Preparation
- Environment: Use a clean browser profile (no extensions) to avoid interference. Test on at least two viewports: desktop (≥1280 px) and mobile (≥360 px width).
- Data seed: Populate the test database with a known set of reviews (e.g., 3×1‑star, 2×2‑star, 4×3‑star, 5×4‑star, 6×5‑star) so you can verify average calculations.
- Tools: Enable devtools network throttling (Slow 3G), open the console for errors, and have a screen‑reader (NVDA, VoiceOver) ready.
2. Widget Interaction
- Hover/Focus – Move mouse over each star; verify tooltip or ARIA label shows the impending rating (e.g., “Select 4 out of 5 stars”).
- Click – Click the third star; confirm that stars 1‑3 fill, 4‑5 remain outline, and the hidden rating input updates to
value="3". - Keyboard – Tab to the widget; press ArrowRight to increment, ArrowLeft to decrement, Space/Enter to lock selection. Ensure focus stays within the widget and does not jump to the page background.
- Half‑star (if supported) – Click the edge of a star; verify half‑fill appears and the rating increments by 0.5.
3. Review Submission Flow
- Open the “Write a review” modal (via button or link).
- Verify modal traps focus: tabbing cycles only inside modal until closed.
- Fill rating (select 5 stars) and type a comment longer than 200 characters.
- Submit; observe network request: check payload, status 200/201, and that the UI shows a success toast.
- Confirm the new review appears at the top of the list (or per sort order) and that the average rating updates correctly (re‑calculate manually to validate).
- Close modal via ESC and clicking backdrop; ensure no draft remains (re‑open modal should show empty fields).
4. Error Handling
- Missing required comment: Leave comment blank, submit; verify inline error appears, request is not sent.
- Out‑of‑range rating: Use devtools to set rating input to
6(bypassing UI) and submit; API should return 400, UI shows error. - Network failure: In devtools Network panel, throttle to “Offline” or set a custom response 500 for the submit endpoint; verify error toast and retry button.
- Concurrent submit: Open two tabs, submit simultaneously; after both resolve, check that the review count increased by two and average reflects both entries.
5. Pagination / Infinite Scroll
- Scroll to bottom until the loading spinner appears; wait for next page to load.
- Confirm no duplicate entries appear (compare review IDs).
- Disable JavaScript and reload page; verify that server‑side pagination (if present) still works and that the “Load more” button is replaced with traditional pagination links.
6. Accessibility Checks
- Run axe via browser extension; note any violations (missing labels, insufficient contrast).
- Use a screen reader: navigate to the widget, listen for rating announcement changes as you arrow through stars.
- Verify that when a new review is appended via infinite scroll, an ARIA live region announces “New review added”.
- Check color‑blind simulators (e.g., Coblis) to ensure star states remain distinguishable.
7. Security & Privacy Spot Checks
- Attempt to submit a comment containing
; view the rendered review to confirm the script is escaped. is escaped or not executed.
-
- Use OWASP ZAP’s active scan targeting
/api/reviewsendpoint; confirm it flags missing CSRF token if present. - Log in as user A, submit a review, then log out and log in as user B; try to access
/api/reviews/:id/deletefor A’s review; expect 403. - Trigger a GDPR deletion request for a test user; after processing, verify that the user’s reviews are either removed or anonymized and that the product’s average rating recomputes without those entries.
8. Post‑Session Review
- Collect screenshots of any visual misalignments, console errors, or network anomalies.
- Log each observed defect with steps, expected vs. actual, and severity.
- If using a test management tool, tag the bug with component (UI, API, Data) and reproducibility (flaky, deterministic).
Manual testing is labor‑intensive but invaluable for catching UI‑specific regressions, accessibility slips, and subtle race conditions that only manifest under real user interaction patterns.
Automated Testing Strategies
Automation provides repeatable regression safety nets. The following layers work together to cover the matrix from the previous section.
Unit / Component Tests
- Rating widget: render the component in isolation (using
@testing-library/reactor Vue Test Utils). Simulate click, keyboard, and half‑star interactions; assert internal state updates and that the correct ARIA attributes (aria-valuenow,aria-label) are set. - Review form: unit test validation logic (e.g.,
validateCommentLength,validateRatingRange). Use table‑driven tests to cover empty, too short, too long, and special‑character inputs. - Aggregation utility: pure function that takes an array of ratings and returns
{average, count, distribution}; test edge cases like empty array (should return{average:0, count:0, distribution:{}}).
These tests run in milliseconds and give instant feedback on logic changes.
Integration / API Tests
- Use a library like
supertest(Node) orrest-assured(Java) to hit the actual endpoints against a test database. - Happy path: POST a valid review, assert 201, then GET
/api/products/:id/ratingsand verify average matches expected. - Error path: POST with missing fields, assert 400 and validation messages.
- Concurrency: spawn multiple parallel requests (e.g., using
Promise.allor Gatling) and assert that final count equals number of requests and average is correct. - Cache busting: after a POST, directly query the denormalized aggregates table to ensure it was updated; optionally introduce a delay to confirm eventual consistency if your system uses async workers.
Integration tests should run against a disposable test schema (e.g., Docker‑composed PostgreSQL) to avoid polluting staging data.
End‑to‑End (UI) Tests
Choose either Cypress or Playwright; the examples below use Playwright for its multi‑browser support.
// tests/review-flow.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Ratings & Reviews flow', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/product/123');
// Ensure we start with a clean state: clear localStorage if needed
await page.context().clearCookies();
});
test('user can submit a review and see it listed', async ({ page }) => {
// Open write‑review modal
await page.click('button[data-action="write-review"]');
await expect(page.locator('role=dialog')).toBeVisible();
// Select rating 4 via keyboard
await page.focus('input[name="rating"]');
await page.press('ArrowRight'); // 1
await page.press('ArrowRight'); // 2
await page.press('ArrowRight'); // 3
await page.press('ArrowRight'); // 4
// Fill comment
await page.fill('textarea[name="comment"]', 'Great product, works as expected.');
// Submit
await page.click('button[type="submit"]');
// Wait for success toast
await expect(page.locator('text=Review submitted')).toBeVisible({ timeout: 5000 });
// Verify review appears in list
const firstReview = page.locator('section.review').first();
await expect(firstReview).toContainText('Great product, works as expected.');
await expect(firstReview.locator('.rating')).toHaveAttribute('data-rating', '4');
// Verify average updated (assume product had 0 reviews before)
await expect(page.locator('.average-rating')).toHaveText('4.0');
});
test('error handling for missing comment', async ({ page }) => {
await page.click('button[data-action="write-review"]');
await page.focus('input[name="rating"]');
await page.press('ArrowRight'); // 1
await page.press('ArrowRight'); // 2
await page.press('ArrowRight'); // 3
await page.click('button[type="submit"]');
const error = page.locator('text=Comment is required');
await expect(error).toBeVisible();
// Ensure no network call succeeded
await expect(page.request().on('response', resp =>
resp.url().includes('/api/reviews') && resp.status() === 200)).toHaveCount(0);
});
});
Key points in the script
- Use role‑based selectors (
role=dialog,role=button) to increase resilience against class‑name changes. - Leverage
page.waitForResponseorexpect.pollto assert network calls and their outcomes. - After each action, assert UI state to catch regressions early.
- Run the suite in CI across Chromium, Firefox, and WebKit to catch browser‑specific glitches (e.g., focus outline differences).
Visual Regression
- Tools like
Applitools EyesorPercycapture snapshots of the review list and widget. - Baseline a known good state; on each PR, the tool highlights pixel differences (e.g., star icon shift, tooltip misplacement).
- Set a threshold tolerant of anti‑aliasing differences but sensitive to layout shifts.
Performance Tests
- Use Lighthouse CI (
lhci autorun) to assert that the review list page maintains a First Contentful Paint < 2 s and that lazy‑loaded review avatars do not block the main thread. - For infinite scroll, create a script that scrolls to the bottom 20 times and measures frame drops; reject if > 15 % of frames exceed 16 ms.
Accessibility Tests
- Integrate
jest-axein unit tests:expect(await axe(component)).toHaveNoViolations(); - In Playwright, after each navigation, run
await page.evaluate(() => axe.run())and assert zero violations. - For live region announcements, use
page.waitForFunction(() => window.lastAnnouncement === 'New review added').
Security Tests
- Nightly OWASP ZAP baseline scan against a staging endpoint:
zap-baseline.py -t https://staging.example.com/api/reports -r zap-report.html. - Fail the build if the report contains any high‑severity alerts (e.g., SQLi, XSS, missing CSRF).
- For rate limiting, use a tool like
k6to burst requests and assert that 429 responses appear after the threshold.
By combining these layers, you achieve fast feedback from unit tests, contract safety from integration tests, user‑flow confidence from e2e, and ongoing guardrails from visual, performance, accessibility, and security suites.
Autonomous, Persona‑Driven Exploration with SUSATest
Even the most thorough scripted suite can miss scenarios that arise from real‑world user variability—different interaction speeds, exploratory clicking, or unconventional input patterns. SUSATest’s autonomous agent addresses this gap by behaving like a set of personas that explore the application without predefined scripts.
How the Agent Works
- Seed: Provide the agent with the entry URL (e.g.,
https://shop.example.com/product/42) and an optional APK or web‑app manifest. - Persona Profiles: Each persona carries a distinct behavior model:
- *Curious* clicks every visible element, hovers, and reads tooltips.
- *Impatient* performs rapid clicks, often skipping loading states.
- *Novice* relies heavily on labels and avoids ambiguous icons.
- *Adversarial* attempts to break the system with rapid back‑button presses, malformed inputs, and unexpected navigation.
- *Accessibility* uses screen‑reader navigation, keyboard-only interaction, and high‑contrast mode toggles.
- *Power user* exploits shortcuts, opens dev tools, and tries to force edge‑case states (e.g., rapid infinite scroll).
- Exploration Loop: The agent interacts with the DOM, records each visited state (URL, DOM snapshot, accessibility tree), and decides the next action based on the persona’s policy and a reinforcement‑learning reward that favors discovering new states and triggering observable changes (network requests, DOM mutations, console errors).
- Learning: Over successive runs, the agent builds a graph of explored screens and dead ends; it avoids re‑executing low‑value actions and focuses on unexplored branches, making each session smarter than the last.
- Reporting: After a run, the agent outputs a JSON log containing:
- Detected JavaScript errors and stack traces.
- Network responses with status codes and bodies.
- Accessibility violations flagged by integrated axe checks.
- Potential security issues (e.g., form submissions missing CSRF token, reflected input in response).
- A trace of the exact interaction sequence that led to each finding.
Applying SUSATest to Ratings & Reviews
When pointed at a product page that hosts the rating widget, the agent will typically:
- **Curios stars one by one, triggering tooltip‑related AJAX pre‑fetches (if any). This surfaces bugs where hover events cause JavaScript errors or where tooltip content is not properly escaped.
- ImpatientNovice: Rapidly click the submit button multiple times before the modal finishes animating, which can reveal double‑submission race conditions or missing disabling of the button.
- Adversarial: Paste a long string containing SQL keywords and script tags into the comment field, then submit. The agent checks the response for error messages or reflected payloads, catching insufficient sanitization.
- Accessibility: Navigate using only Tab and Arrow keys, verify that focus never gets trapped, and that ARIA live regions announce rating changes. It also toggles OS‑level high contrast and checks contrast ratios via axe.
- Power user: Open dev tools, manually set the rating input to
11via console, then click submit to see if front‑end validation is bypassed and how the API responds.
Because the agent does not rely on hard‑coded selectors, it will still exercise the widget even if the team refactors the component and changes class names, as long as the semantic roles (button, textbox, etc.) remain intact.
Integrating SUSATest into Your Pipeline
- Install the CLI:
npm i -g susatest-agent(orpip install susatest-agentfor the Python flavor). - Create a persona config file (
personas.yaml) that enables the profiles you care about for a given sprint:
enabled:
- curious
- impatient
- adversarial
- accessibility
- Run a nightly job:
susatest-agent run \
--url https://staging.example.com/product/42 \
--personas personas.yaml \
--output ./susatest-reports \
--max-depth 6 \
--timeout 15m
- Publish results: The agent generates a SARIF file (
susatest.sarif) that can be ingested by GitHub Code Scanning or Azure DevOps to surface defects directly in pull‑request checks.
Benefits Over Pure Scripted Testing
- Discovery of unanticipated flows: The agent‑upon loading skeleton” state that only appears after three rapid scrolls—something a script that waits for a fixed spinner would never see.
- Persona‑specific defects: An accessibility persona might uncover that the star widget loses its
aria-labelwhen the user forces a dark‑mode CSS variable via dev tools, a scenario a functional test that only checks the default theme would miss. - Reduced maintenance: Because the agent explores based on semantics rather than brittle selectors, UI refactors that preserve accessibility tree structure cause fewer false negatives.
- Complementary data: The logs give you a rich set of real‑world interaction sequences that you can convert into deterministic regression tests (e.g., capture the exact click‑scroll pattern that triggered a 500 and add it to your Cypress suite).
Using SUSATest as a continuous exploration layer adds a safety net that catches the “unknown unknowns” that slip through even the most diligent manual and automated test plans.
Production‑Only Edge Cases and Monitoring
Some defects only manifest under real‑world load, geographic variability, or after prolonged uptime. Relying solely on pre‑release testing leaves a blind spot; observability and production‑guardrails are essential.
1. Real‑User Metrics (RUM)
- Rating submission latency: Measure the time from click‑submit to success toast via the Navigation Timing API or a custom wrapper. Set alerts if the 95th percentile exceeds 2 seconds.
- Review list scroll jank: Use the
PerformanceObserverAPI to capturelayout-shiftandlongtaskentries while users scroll through the review feed. A rising trend indicates inefficient virtualization or image‑loading issues. - Error rates: Track 4xx/5xx responses from
/api/reviewsand/api/products/:id/ratingsendpoints. Spike detection (e.g., > 0.5 % error rate for 5 min) should trigger an incident.
2. Synthetic Production Monitoring
Deploy lightweight synthetic checks that run from multiple regions every 5 minutes:
// synthetic-review-check.js (using Playwright)
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ locale: 'en-US', timezoneId: 'America/New_York' });
const page = await context.newPage();
await page.goto('https://www.example.com/product/999');
// Simulate a curious user: hover each star, then submit a short review
for (let i = 1; i <= 5; i++) {
await page.hover(`[data-star="${i}"]`);
await page.waitForTimeout(100);
}
await page.click('button[data-action="write-review"]');
await page.fill('textarea[name="comment"]', 'Looks good.');
await page.click('button[type="submit"]');
await expect(page.locator('text=Review submitted')).toBeVisible();
await browser.close();
})();
- Failures generate alerts via your incident‑management system (PagerDuty, Opsgenie).
- Include variants for different locales and device emulations (iPhone 13, Pixel 7) to catch region‑specific bugs (e.g., right‑to‑left layout breakage).
3. Feature Flags and Canary Analysis
If you roll out a new rating‑widget version behind a flag, compare key metrics between the flag‑on and flag‑off populations:
- Conversion impact: Does the new star animation affect add‑to‑cart rate?
- Error differential: Are there more 500s on the flag‑on side?
- Engagement: Do users submit more reviews with the new widget?
Use a statistical significance test (e.g., Chi‑square) to avoid reacting to noise.
4. Logging and Auditing
- Submit logs: Capture
userId,productId,rating,commentHash(to avoid PII),timestamp, andresponseCode. Store in an immutable audit stream (Kafka, Kinesis). - Moderation logs: When a review is moved from pending to approved/rejected, log the moderator ID and reason.
- GDPR requests: When a deletion request is processed, emit an event that triggers a recalculation job for affected product aggregates; monitor the job’s lag.
5. Chaos Experiments
Periodically inject faults to verify resilience:
- Latency injection: Use a service mesh (Istio, Linkerd) to add 500 ms delay to the rating API for 5 % of traffic; ensure the UI shows a loading state and does not break.
- Dependency kill: Temporarily shut down the caching layer (Redis) and confirm the system falls back to the database without overwhelming it.
- Network partition: Simulate loss of connectivity between the front‑end and the rating microservice; verify that offline‑first behavior (if implemented) queues submissions and retries on reconnect.
By instrumenting production and running deliberate fault tests, you convert latent risks into observable signals you can act on before they affect a significant user base.
Quick Reference Checklist
| Area | Item | Manual ✔ | Automated ✔ | Notes |
|---|---|---|---|---|
| UI Widget | Star hover/focus shows tooltip | Verify ARIA label updates | ||
| Keyboard navigation (ArrowLeft/Right, Space/Enter) | Ensure focus stays inside widget | |||
| Half‑star selection (if supported) | Validate value increments by 0.5 | |||
| Click updates hidden input & visual state | Prevent double‑click race | |||
| Submit Flow | Modal opens, traps focus | ESC and backdrop close | ||
| Required field validation shows inline error | Prevent submission | |||
| Successful submission shows toast & updates list | Verify average recalc | |||
| Duplicate submission prevented (disabled button or optimistic lock) | Test rapid clicks | |||
| Error Handling | Network 500 shows retry UI | Mock service or network throttling | ||
| Invalid rating (out of range) returns 400 | API contract test | |||
| Malformed comment (XSS/SQL) is sanitized | Security scan | |||
| Pagination / Infinite Scroll | New page loads without duplicates | Scroll to bottom, wait for spinner | ||
| Fallback to server‑side pagination when JS disabled | Noscript test | |||
| Accessibility | Axe reports zero violations | Run in CI and nightly | ||
| Screen reader announces rating change on star select |
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free