testaro 74.2.1 → 74.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/UPGRADES.md +348 -0
  2. package/package.json +1 -1
package/UPGRADES.md CHANGED
@@ -8360,3 +8360,351 @@ pool@jpdev testaro % claude
8360
8360
 
8361
8361
  claude --resume bb937c34-19d9-4fd5-b04b-1356fb39b355
8362
8362
  ```
8363
+
8364
+ ## Initial modal dialogs
8365
+
8366
+
8367
+
8368
+
8369
+
8370
+
8371
+
8372
+
8373
+ Playwright provides several methods to detect modal dialogs, ranging from native browser dialogs to custom modal components.
8374
+
8375
+ ## Modal Detection Methods
8376
+
8377
+ ### 1. Native Browser Dialogs (alert, confirm, prompt)
8378
+ ```javascript
8379
+ // Handle native dialogs that block execution
8380
+ page.on('dialog', async dialog => {
8381
+ console.log('Dialog type:', dialog.type());
8382
+ console.log('Dialog message:', dialog.message());
8383
+ await dialog.accept(); // or dialog.dismiss()
8384
+ });
8385
+
8386
+ // Check if dialog handler was triggered
8387
+ let dialogAppeared = false;
8388
+ page.on('dialog', () => { dialogAppeared = true; });
8389
+ await someAction(); // Action that might trigger dialog
8390
+ if (dialogAppeared) {
8391
+ // Handle modal
8392
+ }
8393
+ ```
8394
+
8395
+ ### 2. ARIA-Based Modal Detection
8396
+ ```javascript
8397
+ // Detect modals by ARIA role and attributes
8398
+ async function detectAriaModal(page) {
8399
+ const modalSelectors = [
8400
+ '[role="dialog"]',
8401
+ '[role="alertdialog"]',
8402
+ '[aria-modal="true"]'
8403
+ ];
8404
+
8405
+ for (const selector of modalSelectors) {
8406
+ const modal = page.locator(selector);
8407
+ if (await modal.isVisible()) {
8408
+ return modal;
8409
+ }
8410
+ }
8411
+ return null;
8412
+ }
8413
+
8414
+ // Usage
8415
+ const modal = await detectAriaModal(page);
8416
+ if (modal) {
8417
+ console.log('ARIA modal detected');
8418
+ // Test modal accessibility
8419
+ }
8420
+ ```
8421
+
8422
+ ### 3. CSS-Based Modal Detection
8423
+ ```javascript
8424
+ // Detect modals by common CSS patterns
8425
+ async function detectCssModal(page) {
8426
+ const modalSelectors = [
8427
+ '.modal:visible',
8428
+ '.modal-dialog:visible',
8429
+ '.modal-overlay:visible',
8430
+ '.popup:visible',
8431
+ '.dialog:visible',
8432
+ '[style*="display: block"][style*="position: fixed"]'
8433
+ ];
8434
+
8435
+ for (const selector of modalSelectors) {
8436
+ try {
8437
+ const modal = page.locator(selector);
8438
+ if (await modal.isVisible({ timeout: 1000 })) {
8439
+ return modal;
8440
+ }
8441
+ } catch (e) {
8442
+ // Element not found, continue
8443
+ }
8444
+ }
8445
+ return null;
8446
+ }
8447
+ ```
8448
+
8449
+ ### 4. Comprehensive Modal Detection
8450
+ ```javascript
8451
+ async function detectAnyModal(page) {
8452
+ // Check native dialogs first
8453
+ let dialogAppeared = false;
8454
+ const dialogHandler = () => { dialogAppeared = true; };
8455
+ page.on('dialog', dialogHandler);
8456
+
8457
+ // Check ARIA modals
8458
+ const ariaModal = await detectAriaModal(page);
8459
+ if (ariaModal) return { type: 'aria', element: ariaModal };
8460
+
8461
+ // Check CSS modals
8462
+ const cssModal = await detectCssModal(page);
8463
+ if (cssModal) return { type: 'css', element: cssModal };
8464
+
8465
+ // Check native dialog
8466
+ if (dialogAppeared) return { type: 'native', element: null };
8467
+
8468
+ return null;
8469
+ }
8470
+ ```
8471
+
8472
+ ### 5. Accessibility-Focused Modal Testing
8473
+ ```javascript
8474
+ async function testModalAccessibility(page) {
8475
+ const modal = await detectAnyModal(page);
8476
+ if (!modal) return null;
8477
+
8478
+ const element = modal.element;
8479
+ const accessibilityTests = {
8480
+ hasAccessibleName: await element.getAttribute('aria-label') ||
8481
+ await element.getAttribute('aria-labelledby'),
8482
+ hasModalRole: await element.getAttribute('role') === 'dialog' ||
8483
+ await element.getAttribute('aria-modal') === 'true',
8484
+ isFocusTrapped: await testFocusTrap(page, element),
8485
+ hasCloseMethod: await page.locator('[aria-label="Close"], .close, button[title="Close"]').isVisible()
8486
+ };
8487
+
8488
+ return {
8489
+ detected: modal,
8490
+ accessibility: accessibilityTests
8491
+ };
8492
+ }
8493
+
8494
+ async function testFocusTrap(page, modalElement) {
8495
+ // Test Tab key stays within modal
8496
+ await page.keyboard.press('Tab');
8497
+ const focusedElement = await page.locator(':focus');
8498
+ const modalContainsFocus = await modalElement.contains(focusedElement);
8499
+ return modalContainsFocus;
8500
+ }
8501
+ ```
8502
+
8503
+ ## Implementation for Testaro
8504
+
8505
+ ```javascript
8506
+ // Modal detection workflow for accessibility testing
8507
+ async function checkPageModals(page) {
8508
+ const modalInfo = await testModalAccessibility(page);
8509
+
8510
+ if (modalInfo) {
8511
+ console.log(`Modal detected: ${modalInfo.detected.type}`);
8512
+
8513
+ // Test focus management
8514
+ await testFocusManagement(page, modalInfo.detected.element);
8515
+
8516
+ // Test keyboard dismissability
8517
+ await testKeyboardDismiss(page, modalInfo.detected.element);
8518
+
8519
+ return modalInfo;
8520
+ }
8521
+
8522
+ return null;
8523
+ }
8524
+
8525
+ async function testFocusManagement(page, modal) {
8526
+ // Check if focus is properly managed
8527
+ const initialFocus = await page.locator(':focus');
8528
+ await page.keyboard.press('Tab');
8529
+ const afterTabFocus = await page.locator(':focus');
8530
+
8531
+ return {
8532
+ focusInitiallyInModal: await modal.contains(initialFocus),
8533
+ focusRemainsInModal: await modal.contains(afterTabFocus)
8534
+ };
8535
+ }
8536
+ ```
8537
+
8538
+ This comprehensive approach allows Testaro to detect and test accessibility of various modal types across different implementations.
8539
+
8540
+ ## State cleaning before each page load
8541
+
8542
+
8543
+
8544
+
8545
+
8546
+
8547
+
8548
+
8549
+
8550
+
8551
+ Yes, Playwright provides comprehensive state reset capabilities that are consistent across Chromium, WebKit, and Firefox.
8552
+
8553
+ ## Complete State Reset Capabilities
8554
+
8555
+ ### Available Methods
8556
+ Playwright's `BrowserContext` class provides these state management methods:
8557
+
8558
+ **Cookies:**
8559
+ ```javascript
8560
+ await context.clearCookies(); // Clear all cookies
8561
+ await context.clearCookies({ domain: 'example.com' }); // Clear specific domain
8562
+ ```
8563
+
8564
+ **Storage State:**
8565
+ ```javascript
8566
+ // Clear and reset all storage
8567
+ await context.setStorageState({ cookies: [], origins: [] });
8568
+
8569
+ // Save current state
8570
+ await context.storageState({ path: 'state.json' });
8571
+
8572
+ // Load clean state (effectively a reset)
8573
+ await context.setStorageState('clean-state.json');
8574
+ ```
8575
+
8576
+ ### Complete Reset Implementation
8577
+ For the "Complete State Reset" I listed earlier:
8578
+
8579
+ ```javascript
8580
+ // Universal state reset across all browsers
8581
+ async function resetBrowserState(context) {
8582
+ await context.clearCookies(); // Clear all cookies
8583
+ await context.clearPermissions(); // Clear permission overrides
8584
+ await context.setStorageState({ // Clear localStorage, sessionStorage, IndexedDB
8585
+ cookies: [],
8586
+ origins: []
8587
+ });
8588
+
8589
+ // Alternative: Create fresh context
8590
+ const freshContext = await browser.newContext();
8591
+ return freshContext;
8592
+ }
8593
+ ```
8594
+
8595
+ ## Cross-Browser Compatibility
8596
+
8597
+ **Yes, the methods are identical across all three browsers:**
8598
+
8599
+ - **Chromium**: Full support for all state management APIs
8600
+ - **WebKit**: Full support for all state management APIs
8601
+ - **Firefox**: Full support for all state management APIs
8602
+
8603
+ ### Key Points:
8604
+
8605
+ 1. **API Consistency**: The same `BrowserContext` methods work identically across all browsers
8606
+ 2. **Storage Coverage**: Methods handle cookies, localStorage, sessionStorage, and IndexedDB uniformly
8607
+ 3. **No Browser-Specific Code**: No conditional logic needed for different browsers
8608
+
8609
+ ### Implementation for Testaro
8610
+
8611
+ ```javascript
8612
+ // Browser-agnostic state reset
8613
+ async function ensureCleanState(browser, testUrl) {
8614
+ const context = await browser.newContext();
8615
+ await context.clearCookies();
8616
+ await context.setStorageState({ cookies: [], origins: [] });
8617
+
8618
+ const page = await context.newPage();
8619
+ await page.goto(testUrl);
8620
+
8621
+ return { context, page };
8622
+ }
8623
+ ```
8624
+
8625
+ ## Multi-State Testing Strategy
8626
+
8627
+ With Playwright's consistent APIs, Testaro can implement:
8628
+
8629
+ 1. **First Load Test**: Fresh context → no cookies → test initial page
8630
+ 2. **Dialog State Test**: Interact with dialogs → retest
8631
+ 3. **Post-Interaction Test**: Dismiss dialogs → retest clean state
8632
+
8633
+ All using the same codebase across Chromium, WebKit, and Firefox.
8634
+
8635
+ ## Code-hygiene-based testing
8636
+
8637
+
8638
+ Your investigation reveals critical flaws in current accessibility testing methodology that go far beyond the initial SVG issue.
8639
+
8640
+ ## (1) Test Isolation and State Management Problems
8641
+
8642
+ ### The Cookie State Issue
8643
+ Your discovery demonstrates that **page state fundamentally affects accessibility testing**:
8644
+
8645
+ - **First load (no cookies)**: Cookie banner appears, SVG becomes visible without accessible name
8646
+ - **Subsequent loads (with cookies)**: Cookie banner suppressed, SVG remains hidden
8647
+ - **Current testing**: May capture only one state, missing violations in the other
8648
+
8649
+ ### Required Testaro Improvements
8650
+
8651
+ **Complete State Reset**:
8652
+ - Clear all site cookies before each page load
8653
+ - Clear localStorage, sessionStorage, IndexedDB
8654
+ - Reset browser state to truly "first visit" conditions
8655
+
8656
+ **Multi-State Testing**:
8657
+ 1. **First Load Test**: Test page with no stored state
8658
+ 2. **Dialog Dismissal Test**: Dismiss initial dialogs, then retest
8659
+ 3. **State Change Test**: Test after common user interactions
8660
+
8661
+ **Modal Dialog Testing**:
8662
+ - Identify modal dialogs on first load
8663
+ - Test focus trapping behavior
8664
+ - Verify keyboard dismissability
8665
+ - Check ARIA attributes in visible state
8666
+
8667
+ ## (2) Rule Definition Philosophy: Momentary vs. Hygiene
8668
+
8669
+ ### Current Problem: Momentary Correctness
8670
+ Rules that test "is this accessible right now?" fail because:
8671
+ - They miss conditional violations
8672
+ - They don't account for state changes
8673
+ - They create false negatives/positives
8674
+
8675
+ ### Better Approach: Coding Hygiene Rules
8676
+
8677
+ Your SVG example illustrates this perfectly:
8678
+ **Poor hygiene**: SVG lacks accessible name, relies on ancestor being hidden
8679
+ **Good hygiene**: SVG has accessible name regardless of visibility state
8680
+
8681
+ ### Hygiene-Based Rule Examples
8682
+
8683
+ 1. **SVG Naming Rule**: All SVG elements must have accessible names, regardless of ancestor visibility
8684
+ 2. **State Independence Rule**: Element accessibility must not depend on CSS display properties
8685
+ 3. **Consistency Rule**: If an element can become visible, it must be accessible in all states
8686
+
8687
+ ## Benefits of Hygiene-Based Rules
8688
+
8689
+ 1. **Prevention-focused**: Catch issues before they cause accessibility problems
8690
+ 2. **State-agnostic**: Don't depend on specific page states during testing
8691
+ 3. **Developer-friendly**: Clear coding standards rather than conditional requirements
8692
+ 4. **Reduced false positives**: Rules apply consistently regardless of testing conditions
8693
+
8694
+ ## Implementation Strategy
8695
+
8696
+ **Testaro Enhancement**:
8697
+ - Add state isolation procedures
8698
+ - Implement multi-state testing workflows
8699
+ - Develop hygiene-focused rule sets
8700
+ - Create modal dialog detection and testing
8701
+
8702
+ **AI Agent Evolution**:
8703
+ - Recognize state-dependent patterns
8704
+ - Test elements across multiple states
8705
+ - Apply hygiene-based rule evaluation
8706
+ - Predict potential accessibility failures
8707
+
8708
+ ## Conclusion
8709
+
8710
+ Your investigation reveals that **current accessibility testing is fundamentally incomplete**. The solution requires both technical improvements (state management) and philosophical shifts (hygiene-based rules). This significantly raises the complexity bar but also the potential effectiveness of automated accessibility testing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "74.2.1",
3
+ "version": "74.2.2",
4
4
  "description": "Run 1300 web accessibility tests from 10 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {