Skip to main content

ByLast reviewed

Testing & Validation

Comprehensive guide to testing BiModal sites for humans and agents

Testing a BiModal site requires validating two audiences: human users (including those using assistive technologies) and AI agents. This guide covers testing methodologies, tools, and best practices to ensure your site works for everyone.

Accessibility Testing

Accessibility testing ensures your site works for users with disabilities and assistive technologies. These same features benefit AI agents.

Keyboard Navigation Testing

The Golden Rule:

Unplug your mouse. Can you complete every task using only the keyboard?

Test Procedure:

  1. Use Tab to navigate forward through interactive elements
  2. Use Shift + Tab to navigate backward
  3. Use Enter to activate links and buttons
  4. Use Space to activate buttons and checkboxes
  5. Use Arrow keys for radio buttons and dropdown menus
  6. Use Esc to close modals and dropdowns

What to Check:

  • ✓ All interactive elements are reachable via Tab
  • ✓ Focus order is logical and follows visual layout
  • ✓ Focus indicator is clearly visible
  • ✓ No keyboard traps (can always Tab away)
  • ✓ Skip links work (jump to main content)
  • ✓ Dropdowns and modals close with Esc

Screen Reader Testing

macOS: VoiceOver

Start: Cmd + F5

Navigate: Ctrl + Option + Arrow Keys

Read: Ctrl + Option + A

Windows: NVDA (Free)

Download: nvaccess.org

Navigate: Arrow keys or H for headings

Read: Insert + Down Arrow

What to Listen For:

  • ✓ Page title is read first
  • ✓ Headings are announced with level (e.g., "Heading level 2")
  • ✓ Links describe their destination
  • ✓ Images have descriptive alt text (not filenames)
  • ✓ Form fields have labels that are read aloud
  • ✓ Buttons describe their action
  • ✓ Error messages are announced
  • ✓ Dynamic content updates are announced

Automated Accessibility Testing

axe DevTools (Browser Extension)

Industry-standard tool that finds ~57% of WCAG issues automatically.

Install: Chrome Web Store or Firefox Add-ons

Usage: Open DevTools → axe DevTools tab → Scan Page

Target: Zero violations in each severity category

Lighthouse (Built into Chrome)

Google's audit tool for performance, accessibility, SEO, and best practices.

Usage: DevTools → Lighthouse tab → Generate Report

Target: 90+ accessibility score

Bonus: Also tests performance and SEO

WAVE (WebAIM)

Visual feedback tool that shows accessibility issues directly on the page.

URL: wave.webaim.org

Usage: Enter URL or use browser extension

Advantage: Shows errors in context on the page

⚠️ Important Note:

Automated tools catch only 30-50% of accessibility issues. Manual testing with keyboard and screen readers is essential for full compliance.

Agent Testing

Test how AI agents will experience your site by simulating agent behavior.

The Curl Test

The Ultimate Agent Test:

If curl can't see it, most agents can't either. This test reveals what agents actually receive from your server.

# Fetch your page as an agent would
curl https://yoursite.com

# What to look for:
# ✓ All content is present in the HTML
# ✓ No "Loading..." or empty divs
# ✓ Prices, descriptions visible
# ✓ Forms have proper action attributes
# ✗ Content that only appears after JS runs

Pass Criteria:

  • ✓ All text content is readable in the HTML response
  • ✓ Product information (name, price, description) is present
  • ✓ Navigation links are visible
  • ✓ Forms have proper action URLs
  • ✓ No empty containers waiting for JavaScript

JavaScript Disabled Test

How to Disable JavaScript:

Chrome: DevTools → Settings (⚙️) → Debugger → "Disable JavaScript"

Firefox: about:config → javascript.enabled → false

Safari: Develop menu → Disable JavaScript

What Should Still Work:

  • ✓ All content is visible
  • ✓ Navigation works (standard links)
  • ✓ Forms submit (even if not via AJAX)
  • ✓ Pages are readable and usable
  • ✓ Core functionality is available

What Can Break (Acceptable):

  • • Interactive features (image galleries, live search)
  • • Client-side validation (server validation must work)
  • • Smooth animations and transitions
  • • Real-time updates

Progressive Enhancement Check: If your site is completely broken without JavaScript, it fails the BiModal test. Core functionality must work without JS.

Data Extraction Test

Test whether agents can easily extract structured data from your pages.

Test data attribute extraction:
// Open browser console and run:

// 1. Find all product cards
const products = document.querySelectorAll('[data-agent-component="product-card"]');
console.log('Found', products.length, 'products');

// 2. Extract product data
products.forEach(product => {
  const name = product.querySelector('[data-agent-content="product-name"]')?.textContent;
  const price = product.querySelector('[data-agent-content="product-price"]')?.textContent;
  console.log({ name, price });
});

// 3. Find available actions
const actions = document.querySelectorAll('[data-agent-action]');
console.log('Available actions:',
  Array.from(actions).map(el => el.dataset.agentAction)
);

Expected Results:

  • ✓ All key components found via data-agent-component
  • ✓ Content values extractable via data-agent-content
  • ✓ Actions identifiable via data-agent-action
  • ✓ Data attributes match visible content

Structured Data Validation

Google Rich Results Test

Official Google tool for validating Schema.org markup.

URL: search.google.com/test/rich-results

Usage: Enter URL or paste code

Checks: Product, Article, FAQ, Event, etc.

Target: "Page is eligible for rich results" with no errors

Schema.org Validator

Official Schema.org markup validator.

URL: validator.schema.org

Usage: Paste JSON-LD code

Checks: Valid Schema.org syntax

Target: No errors, valid JSON-LD structure

HTML Validator

W3C's official HTML validation service.

URL: validator.w3.org

Usage: Enter URL or upload file

Checks: Valid HTML5 syntax

Target: No errors (warnings acceptable)

Microdata Testing

Test inline microdata (itemScope, itemProp) if used.

Tool: Google's Rich Results Test

Usage: Automatically detects microdata

Checks: Proper nesting and values

Note: JSON-LD is preferred, but microdata also works

Performance Testing

Core Web Vitals

Google's metrics for user experience. Good scores benefit both humans and search rankings.

LCP

Largest Contentful Paint

<2.5s

Good

FID / INP

Interaction Delay

<100ms

Good

CLS

Cumulative Layout Shift

<0.1

Good

How to Test:

  • Lighthouse: Chrome DevTools → Lighthouse → Performance
  • PageSpeed Insights: pagespeed.web.dev (tests real user data)
  • Chrome DevTools: Performance panel → Record page load

BiModal Performance Advantage

Server-rendered BiModal sites typically score 90+ on Lighthouse performance, while client-side-rendered SPAs struggle to break 60. Progressive enhancement naturally leads to better performance.

Manual Testing Checklist

A comprehensive checklist for manual BiModal testing. Print this or save it as a template.

HTML & Semantics

Images & Media

Forms

Accessibility

Agent-Friendly

Performance

Automated Testing

Integrate BiModal testing into your CI/CD pipeline.

Pa11y (Accessibility Testing)

# Install
npm install --save-dev pa11y

# Test a URL
npx pa11y https://yoursite.com

# CI Integration (package.json)
{
  "scripts": {
    "test:a11y": "pa11y https://yoursite.com"
  }
}

Lighthouse CI

# Install
npm install --save-dev @lhci/cli

# Configuration (lighthouserc.json)
{
  "ci": {
    "collect": {
      "url": ["https://yoursite.com"]
    },
    "assert": {
      "preset": "lighthouse:recommended",
      "assertions": {
        "categories:accessibility": ["error", {"minScore": 0.9}]
      }
    }
  }
}

# Run
npx lhci autorun

Custom BiModal Tests (Playwright)

// bimodal.spec.ts
import { test, expect } from '@playwright/test';

test('Content visible without JavaScript (FR-1)', async ({ browser }) => {
  const ctx = await browser.newContext({ javaScriptEnabled: false });
  const page = await ctx.newPage();
  await page.goto('https://yoursite.com/products');

  // Core content must be in initial HTML
  await expect(page.locator('h1')).toBeVisible();
  const agentComponents = await page.locator('[data-agent-component]').count();
  expect(agentComponents).toBeGreaterThan(0);
  await ctx.close();
});

test('data-agent-* attributes present', async ({ page }) => {
  await page.goto('https://yoursite.com/products');

  // Check for agent components
  const products = await page.locator('[data-agent-component="product-card"]').count();
  expect(products).toBeGreaterThan(0);

  // Check for content fields
  const prices = await page.locator('[data-agent-content="product-price"]').count();
  expect(prices).toBeGreaterThan(0);
});

test('Structured data valid', async ({ page }) => {
  await page.goto('https://yoursite.com/products/sample');

  const jsonLd = await page.locator('script[type="application/ld+json"]').first().textContent();
  const data = JSON.parse(jsonLd!);

  expect(data['@context']).toContain('schema.org');
  expect(data['@type']).toBeTruthy();
  expect(data.name).toBeTruthy();
});

Continuous Monitoring

Set up ongoing monitoring to catch regressions and maintain BiModal compliance.

Real User Monitoring

Monitor actual user experiences in production.

Tools:
  • • Google Analytics 4 (Core Web Vitals)
  • • Sentry (Error tracking)
  • • LogRocket (Session replay)
What to Track:
  • • Core Web Vitals scores
  • • JavaScript errors
  • • Form submission success rates
  • • Browser/device breakdown

Scheduled Testing

Run automated tests on a schedule to catch issues early.

Frequency:
  • • Daily: Accessibility scans
  • • Weekly: Full Lighthouse audits
  • • Per deploy: CI/CD integration
Tools:
  • • GitHub Actions
  • • Cron jobs + Pa11y
  • • Lighthouse CI

Complete Tools Reference

Accessibility Testing

axe DevTools

Browser extension, automated scanning

WAVE

Visual feedback tool

Lighthouse

Built into Chrome DevTools

Pa11y

Command-line accessibility testing

VoiceOver / NVDA

Screen reader testing

Validation

W3C HTML Validator

validator.w3.org

Google Rich Results Test

Schema.org validation

Schema.org Validator

validator.schema.org

CSS Validator

jigsaw.w3.org/css-validator

Performance

PageSpeed Insights

Real user Core Web Vitals

WebPageTest

Detailed performance analysis

Lighthouse CI

Continuous performance monitoring

Chrome DevTools

Performance profiling

Automated Testing

Playwright

End-to-end testing

Cypress

Browser automation

Jest

Unit testing

Testing Library

Component testing

Agent-Level Testing Matrix

Different agent types access your site in different ways. Test each capability level to understand which agent classes can successfully interact with your site.

LevelAgent TypeTest CommandExpected ResultRequires
0HTTP / curl

Raw HTTP scrapers

curl -s URL | grep -c 'data-'Returns count > 0. All primary content in HTML.FR-1 (Layer 1)
1Structured data

Knowledge graph agents

curl -s URL | grep -c 'ld+json'Returns count > 0. JSON-LD with correct @type.Layers 1–3
2Browser automation

Playwright, Puppeteer agents

Playwright test (see below)data-agent-* attributes accessible. Actions triggerable.Layers 1–2
3Semantic parser

HTML DOM analysis agents

curl -s URL | grep '<main\|<nav'HTML5 landmarks, heading hierarchy present.Layers 1–2
4API client

REST/GraphQL API agents

curl -s URL/api/openapi.json | jq .infoReturns valid OpenAPI spec with endpoints.Layers 1–4
5Protocol agent

MCP / A2A protocol agents

curl -s URL/.well-known/agent.jsonHTTP 200 with valid Agent Card JSON.Layers 1–5

Automated Agent-Level Test Suite

Save as test-agent-levels.sh and run: bash test-agent-levels.sh https://yoursite.com

#!/bin/bash
# test-agent-levels.sh
# Tests all 6 agent capability levels (0-5) against a BiModal site
# Usage: bash test-agent-levels.sh https://yoursite.com

URL="${1:-https://yoursite.com}"
PASS=0
FAIL=0

ok() { echo "  PASS  $1"; ((PASS++)); }
fail() { echo "  FAIL  $1"; ((FAIL++)); }
check_count() {
  local desc="$1" cmd="$2"
  local n; n=$(eval "$cmd" 2>/dev/null | tr -d '[:space:]')
  [ "$n" -gt 0 ] 2>/dev/null && ok "$desc ($n found)" || fail "$desc"
}
check_http() {
  local desc="$1" url="$2"
  local code; code=$(curl -s -o /dev/null -w "%{http_code}" "$url")
  [ "$code" = "200" ] && ok "$desc" || fail "$desc (HTTP $code)"
}

echo ""
echo "BiModal Design — Agent Level Test Suite"
echo "Target: $URL"
echo "$(date)"
echo "============================================"

echo ""
echo "LEVEL 0: HTTP / curl access"
check_count "data-agent-* present in HTML"   "curl -s '$URL' | grep -c 'data-'"
check_count "<title> present"   "curl -s '$URL' | grep -c '<title'"
check_count "No empty-root-only SPA"   "curl -s '$URL' | grep -v 'id="root">' | grep -c '<main|<article|<section'"

echo ""
echo "LEVEL 1: Structured data (Schema.org)"
check_count "JSON-LD present"   "curl -s '$URL' | grep -c 'application/ld+json'"
check_count "schema.org reference"   "curl -s '$URL' | grep -c 'schema.org'"

echo ""
echo "LEVEL 2: Browser automation attributes"
check_count "data-agent-page attribute"   "curl -s '$URL' | grep -c 'data-agent-page'"
check_count "data-agent-component attributes"   "curl -s '$URL' | grep -c 'data-agent-component'"
check_count "data-agent-action attributes"   "curl -s '$URL' | grep -c 'data-agent-action'"

echo ""
echo "LEVEL 3: Semantic structure"
check_count "HTML5 <main> element"   "curl -s '$URL' | grep -c '<main'"
check_count "HTML5 <nav> element"   "curl -s '$URL' | grep -c '<nav'"
check_count "Skip-to-content link"   "curl -s '$URL' | grep -c 'skip-to-content|#main-content'"
check_count "Single <h1>"   "curl -s '$URL' | grep -c '<h1'"

echo ""
echo "LEVEL 4: API surface"
check_http "OpenAPI spec accessible" "$URL/api/openapi.json"
check_count "<link rel=api> in head"   "curl -s '$URL' | grep -c 'rel=.api.'"

echo ""
echo "LEVEL 5: Agent protocols"
check_http "Agent Card (/.well-known/agent.json)" "$URL/.well-known/agent.json"
check_http "robots.txt accessible" "$URL/robots.txt"

echo ""
echo "============================================"
echo "Results: $PASS passed, $FAIL failed"
echo ""
if [ $FAIL -eq 0 ]; then
  echo "All agent levels fully supported (Level 5 — Agent Native)"
elif [ $FAIL -le 3 ]; then
  echo "Most levels supported — fix FAIL items above"
else
  echo "Significant gaps — review BiModal implementation guide"
fi

Playwright: Level 2 Browser Automation Tests

Level 2 agents use browser automation to interact with your site. These Playwright tests verify that data-agent-* attributes are present and actions are triggerable.

// tests/agent-level-2.spec.ts
import { test, expect } from '@playwright/test';

const BASE_URL = process.env.BASE_URL ?? 'https://yoursite.com';

test.describe('Level 2: Browser Automation (data-agent-* attributes)', () => {
  test('product listing page has required agent attributes', async ({ page }) => {
    await page.goto(`${BASE_URL}/products`);

    // Page-level attributes
    const main = page.locator('[data-agent-page="product-listing"]');
    await expect(main).toBeVisible();

    // Component attributes present
    const productCards = page.locator('[data-agent-component="product-card"]');
    await expect(productCards.first()).toBeVisible();

    // Content fields extractable
    const firstProductName = page
      .locator('[data-agent-component="product-card"]')
      .first()
      .locator('[data-agent-content="product-name"]');
    await expect(firstProductName).toBeVisible();
    const nameText = await firstProductName.textContent();
    expect(nameText?.length).toBeGreaterThan(0);
  });

  test('agent can find and trigger add-to-cart action', async ({ page }) => {
    await page.goto(`${BASE_URL}/products`);

    // Agent locates the first product's add-to-cart action
    const addToCart = page
      .locator('[data-agent-action="add-to-cart"]')
      .first();
    await expect(addToCart).toBeVisible();

    // Action is triggerable
    await addToCart.click();
    // Assert outcome (cart count increments, etc.)
  });

  test('navigation actions are discoverable', async ({ page }) => {
    await page.goto(BASE_URL);

    const nav = page.locator('[data-agent-component="navigation"]');
    await expect(nav).toBeVisible();

    // All expected navigation actions present
    for (const action of ['go-home', 'view-products', 'get-support']) {
      const link = nav.locator(`[data-agent-action="${action}"]`);
      await expect(link).toBeVisible(`action "${action}" not found in nav`);
    }
  });

  test('content visible without JavaScript (Level 0 regression)', async ({ browser }) => {
    const context = await browser.newContext({ javaScriptEnabled: false });
    const page = await context.newPage();
    await page.goto(`${BASE_URL}/products`);

    // Core content must be present even without JS
    await expect(page.locator('h1')).toBeVisible();
    const agentAttrs = await page.locator('[data-agent-component]').count();
    expect(agentAttrs).toBeGreaterThan(0);

    await context.close();
  });

  test('structured data extractable from DOM', async ({ page }) => {
    await page.goto(`${BASE_URL}/products/sample`);

    const jsonLd = await page
      .locator('script[type="application/ld+json"]')
      .first()
      .textContent();
    expect(jsonLd).toBeTruthy();

    const data = JSON.parse(jsonLd!);
    expect(data['@context']).toContain('schema.org');
    expect(data['@type']).toBeTruthy();
  });
});

Testing is Essential

Regular testing ensures your BiModal site works for everyone—humans with disabilities, users on slow connections, and AI agents at every capability level. Build testing into your workflow from day one.

Recommended Testing Cadence:

  • • Every deploy: Automated agent-level test suite + accessibility tests
  • • Weekly: Manual keyboard + screen reader testing
  • • Monthly: Full BiModal compliance audit (all 5 layers)
  • • Quarterly: User testing with people with disabilities