import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import './usa-accordion.ts';
import type { USAAccordion } from './usa-accordion.js';
import { testComponentAccessibility, USWDS_A11Y_CONFIG } from './accessibility-utils.js';
/**
* USAAccordion USWDS Integration Validation
*
* Risk Level: HIGH
* Risk Factors: button-content-restructuring, dynamic-show-hide, aria-state-changes, event-delegation
* USWDS Module: usa-accordion
*
* Generated based on tooltip troubleshooting patterns to prevent:
* - dom transformation
* - multi phase-attributes
* - light dom-slots
*/
describe('USAAccordion USWDS Integration Validation', () => {
let element: USAAccordion;
let testContainer: HTMLElement;
beforeEach(() => {
testContainer = document.createElement('div');
testContainer.id = 'accordion-test-container';
document.body.appendChild(testContainer);
element = document.createElement('usa-accordion') as USAAccordion;
testContainer.appendChild(element);
});
afterEach(() => {
testContainer.remove();
});
describe('DOM Transformation Validation', () => {
it('should handle USWDS DOM transformation correctly', async () => {
// Add test content that USWDS will transform
const testContent = document.createElement('button');
testContent.classList.add('usa-accordion');
testContent.textContent = 'Test accordion';
element.appendChild(testContent);
await element.updateComplete;
// Simulate USWDS transformation (accordion specific)
const preTransformElement = element.querySelector('.usa-accordion');
expect(preTransformElement).toBeTruthy();
// Simulate USWDS changing class structure
preTransformElement?.classList.remove('usa-accordion');
preTransformElement?.classList.add('usa-accordion__trigger');
// Component should handle both pre and post-transformation states
const postTransformElement = element.querySelector('.usa-accordion__trigger');
expect(postTransformElement).toBeTruthy();
expect(postTransformElement).toBe(preTransformElement);
});
it('should apply attributes before USWDS initialization', async () => {
// Set accordion items with proper expanded state
element.items = [
{ id: 'test-item', title: 'Test Item', content: 'Test Content', expanded: false }
];
await element.updateComplete;
// Check that the accordion button has the correct aria-expanded attribute
const button = element.querySelector('.usa-accordion__button');
expect(button?.getAttribute("aria-expanded")).toBe("false");
});
});
describe('Multi-Phase Attribute Application', () => {
it('should handle attribute timing correctly', async () => {
const events: string[] = [];
// Mock component lifecycle
const mockLifecycle = {
connectedCallback() {
events.push('connected');
// Should apply attributes immediately
events.push('apply-attributes');
},
firstUpdated() {
events.push('first-updated');
// Should delay USWDS initialization
setTimeout(() => events.push('initialize-uswds'), 10);
}
};
mockLifecycle.connectedCallback();
mockLifecycle.firstUpdated();
// Wait for async initialization
await new Promise(resolve => setTimeout(resolve, 20));
// Validate proper sequence
expect(events).toContain('connected');
expect(events).toContain('apply-attributes');
expect(events).toContain('initialize-uswds');
// Critical: attributes applied before USWDS initialization
const applyIndex = events.indexOf('apply-attributes');
const initIndex = events.indexOf('initialize-uswds');
expect(applyIndex).toBeLessThan(initIndex);
});
it('should handle property updates through all phases', async () => {
element.expanded = true;
await element.updateComplete;
expect(element.expanded).toBe(true);
});
});
describe('Light DOM Slot Behavior', () => {
it('should access slot content correctly in light DOM', () => {
// Add complex slot content
const slotContent = `
Slotted content
`;
element.innerHTML = slotContent;
// Strategy 1: Direct children access
const directChildren = Array.from(element.children).filter(
child => child.nodeType === Node.ELEMENT_NODE && child.tagName !== 'SLOT'
);
expect(directChildren.length).toBeGreaterThan(0);
// Strategy 2: Slot children access
const slotElement = element.querySelector('slot');
const slotChildren = slotElement ? Array.from(slotElement.children) : [];
// Should find content using light DOM patterns
const totalElements = directChildren.length + slotChildren.length;
expect(totalElements).toBeGreaterThan(0);
});
it('should handle content updates dynamically', async () => {
// Accordion component renders its own structure, so we test via items property
element.items = [
{ id: 'initial', title: 'Initial Item', content: 'Initial content' }
];
await element.updateComplete;
const initialItems = element.items.length;
expect(initialItems).toBe(1);
// Add new content via items property
element.items = [
...element.items,
{ id: 'new', title: 'New Item', content: 'New content' }
];
await element.updateComplete;
expect(element.items.length).toBe(2);
// Remove content via items property
element.items = element.items.filter(item => item.id !== 'initial');
await element.updateComplete;
expect(element.items.length).toBe(1);
});
});
});