"use client"; import React, { useState, useCallback } from "react"; import { DesktopChatModal } from "./desktop-chat-modal"; import { I18nProvider } from "./i18n-context"; import { ModalStateProvider, useModalState } from "./modal-state-context"; interface AccessibilityTestProps { onTestResult?: (testName: string, passed: boolean, details?: string) => void; } // Accessibility testing utility component function AccessibilityTester({ onTestResult }: AccessibilityTestProps) { const { modalState, openModal, closeModal } = useModalState(); const [testResults, setTestResults] = useState< Array<{ name: string; passed: boolean; details?: string; }> >([]); const runTest = useCallback( (testName: string, testFn: () => boolean, details?: string) => { try { const passed = testFn(); const result = { name: testName, passed, details }; setTestResults((prev) => [ ...prev.filter((r) => r.name !== testName), result, ]); onTestResult?.(testName, passed, details); return passed; } catch (error) { const result = { name: testName, passed: false, details: `Test failed with error: ${ error instanceof Error ? error.message : "Unknown error" }`, }; setTestResults((prev) => [ ...prev.filter((r) => r.name !== testName), result, ]); onTestResult?.(testName, false, result.details); return false; } }, [onTestResult] ); // Test keyboard navigation const testKeyboardNavigation = useCallback(() => { return runTest( "Keyboard Navigation", () => { // Check if modal can be opened if (!modalState.isOpen) { openModal(); } // Check for focusable elements const modal = document.querySelector('[role="dialog"]'); if (!modal) return false; const focusableElements = modal.querySelectorAll( 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])' ); return focusableElements.length > 0; }, "Modal contains focusable elements for keyboard navigation" ); }, [modalState.isOpen, openModal, runTest]); // Test ARIA attributes const testAriaAttributes = useCallback(() => { return runTest( "ARIA Attributes", () => { const modal = document.querySelector('[role="dialog"]'); if (!modal) return false; const hasAriaModal = modal.getAttribute("aria-modal") === "true"; const hasAriaLabelledby = modal.hasAttribute("aria-labelledby"); const hasAriaDescribedby = modal.hasAttribute("aria-describedby"); return hasAriaModal && hasAriaLabelledby && hasAriaDescribedby; }, "Modal has proper ARIA attributes (aria-modal, aria-labelledby, aria-describedby)" ); }, [runTest]); // Test focus management const testFocusManagement = useCallback(() => { return runTest( "Focus Management", () => { if (!modalState.isOpen) { openModal(); // Wait for modal to open and focus to be set setTimeout(() => { const activeElement = document.activeElement; const modal = document.querySelector('[role="dialog"]'); return modal?.contains(activeElement || null) || false; }, 200); } return true; // Initial check passes if modal is already open }, "Focus is properly managed when modal opens" ); }, [modalState.isOpen, openModal, runTest]); // Test screen reader announcements const testScreenReaderSupport = useCallback(() => { return runTest( "Screen Reader Support", () => { // Check for aria-live regions const ariaLiveElements = document.querySelectorAll("[aria-live]"); const hasTypingIndicator = document.querySelector('[role="status"]'); const hasMessageLog = document.querySelector('[role="log"]'); return ( ariaLiveElements.length > 0 && hasTypingIndicator !== null && hasMessageLog !== null ); }, "Screen reader support with aria-live regions, status indicators, and message log" ); }, [runTest]); // Test responsive design const testResponsiveDesign = useCallback(() => { return runTest( "Responsive Design", () => { const modal = document.querySelector('[role="dialog"]') as HTMLElement; if (!modal) return false; const computedStyle = window.getComputedStyle(modal); const hasMaxWidth = computedStyle.maxWidth !== "none"; const hasMaxHeight = computedStyle.maxHeight !== "none"; // Check if modal adapts to viewport size const viewportWidth = window.innerWidth; const modalWidth = modal.offsetWidth; const isResponsive = modalWidth <= viewportWidth * 0.95; // Should not exceed 95% of viewport return hasMaxWidth && hasMaxHeight && isResponsive; }, "Modal is responsive and adapts to different screen sizes" ); }, [runTest]); // Test escape key functionality const testEscapeKey = useCallback(() => { return runTest( "Escape Key", () => { if (!modalState.isOpen) { openModal(); } // Simulate escape key press const escapeEvent = new KeyboardEvent("keydown", { key: "Escape", code: "Escape", keyCode: 27, bubbles: true, cancelable: true, }); document.dispatchEvent(escapeEvent); // Check if modal closed (with a small delay for state update) setTimeout(() => { return !modalState.isOpen; }, 100); return true; // Initial test passes, actual result checked in timeout }, "Modal can be closed with Escape key" ); }, [modalState.isOpen, openModal, runTest]); // Run all tests const runAllTests = useCallback(() => { console.log("π§ͺ Running Accessibility Tests..."); const tests = [ testKeyboardNavigation, testAriaAttributes, testFocusManagement, testScreenReaderSupport, testResponsiveDesign, testEscapeKey, ]; let allPassed = true; tests.forEach((test, index) => { setTimeout(() => { const result = test(); if (!result) allPassed = false; // Log final result after all tests if (index === tests.length - 1) { setTimeout(() => { console.log( `β Accessibility Tests Completed: ${ allPassed ? "ALL PASSED" : "SOME FAILED" }` ); }, 500); } }, index * 100); // Stagger tests slightly }); }, [ testKeyboardNavigation, testAriaAttributes, testFocusManagement, testScreenReaderSupport, testResponsiveDesign, testEscapeKey, ]); return (
{result.details}
)}μλ λ²νΌμ ν΄λ¦νμ¬ μ±ν λͺ¨λ¬μ μ΄κ³ μ κ·Όμ± κΈ°λ₯μ ν μ€νΈν΄λ³΄μΈμ.
{/* This will render the actual modal for testing */}