// Component tests for usa-tooltip import './index.ts'; describe('USA Tooltip Component Tests', () => { it('should render tooltip with default properties', () => { cy.mount(` `); cy.get('usa-tooltip').should('exist'); cy.get('.usa-tooltip').should('exist'); cy.get('.usa-tooltip__body').should('exist'); cy.get('.usa-tooltip__trigger').should('exist'); }); it('should show tooltip on hover', () => { cy.mount(` `); // Initially hidden cy.get('.usa-tooltip__body').should('have.attr', 'aria-hidden', 'true'); cy.get('.usa-tooltip__body').should('not.have.class', 'is-visible'); // Hover to show cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.attr', 'aria-hidden', 'false'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); cy.get('.usa-tooltip__body').should('contain.text', 'Hover tooltip text'); }); it('should hide tooltip on mouse leave', () => { cy.mount(` `); // Show tooltip first cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); // Hide on mouse leave cy.get('.usa-tooltip__trigger').trigger('mouseleave'); cy.get('.usa-tooltip__body').should('not.have.class', 'is-visible'); cy.get('.usa-tooltip__body').should('have.attr', 'aria-hidden', 'true'); }); it('should show tooltip on focus', () => { cy.mount(` `); cy.get('.usa-tooltip__trigger').focus(); cy.get('.usa-tooltip__body').should('have.attr', 'aria-hidden', 'false'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); }); it('should hide tooltip on blur', () => { cy.mount(` `); // Show tooltip first cy.get('.usa-tooltip__trigger').focus(); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); // Hide on blur cy.get('.usa-tooltip__trigger').blur(); cy.get('.usa-tooltip__body').should('not.have.class', 'is-visible'); }); it('should hide tooltip on Escape key', () => { cy.mount(` `); // Show tooltip first cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); // Hide on Escape key cy.get('body').type('{esc}'); cy.get('.usa-tooltip__body').should('not.have.class', 'is-visible'); }); it('should handle different positions', () => { const positions = ['top', 'bottom', 'left', 'right']; positions.forEach(position => { cy.mount(` `); cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', `usa-tooltip__body--${position}`); cy.get('.usa-tooltip__trigger').trigger('mouseleave'); }); }); it('should emit tooltip-show event', () => { cy.mount(` `); cy.window().then((win) => { const tooltip = win.document.querySelector('usa-tooltip') as any; const showSpy = cy.stub(); tooltip.addEventListener('tooltip-show', showSpy); cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.then(() => { expect(showSpy).to.have.been.calledWith( Cypress.sinon.match.hasNested('detail.text', 'Event test tooltip') ); }); }); }); it('should emit tooltip-hide event', () => { cy.mount(` `); cy.window().then((win) => { const tooltip = win.document.querySelector('usa-tooltip') as any; const hideSpy = cy.stub(); tooltip.addEventListener('tooltip-hide', hideSpy); // Show first, then hide cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__trigger').trigger('mouseleave'); cy.then(() => { expect(hideSpy).to.have.been.calledWith( Cypress.sinon.match.hasNested('detail.text', 'Event test tooltip') ); }); }); }); it('should handle multiple trigger elements', () => { cy.mount(` Span element
Div element
`); // All elements should get trigger class cy.get('.usa-tooltip__trigger').should('have.length', 3); // Each should be able to trigger tooltip cy.get('.usa-tooltip__trigger').each(($trigger) => { cy.wrap($trigger).trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); cy.wrap($trigger).trigger('mouseleave'); cy.get('.usa-tooltip__body').should('not.have.class', 'is-visible'); }); }); it('should add tabindex to non-focusable elements', () => { cy.mount(` Non-focusable span
Non-focusable div
`); // Non-focusable elements should get tabindex cy.get('span.usa-tooltip__trigger').should('have.attr', 'tabindex', '0'); cy.get('div.usa-tooltip__trigger').should('have.attr', 'tabindex', '0'); // Button should not get tabindex (already focusable) cy.get('button.usa-tooltip__trigger').should('not.have.attr', 'tabindex'); }); it('should handle aria-describedby correctly', () => { cy.mount(` `); // Trigger should have aria-describedby pointing to tooltip cy.get('.usa-tooltip__trigger') .should('have.attr', 'aria-describedby') .then((describedBy) => { cy.get('.usa-tooltip__body').should('have.id', describedBy); }); }); it('should handle tooltip role and accessibility attributes', () => { cy.mount(` `); cy.get('.usa-tooltip__body') .should('have.attr', 'role', 'tooltip') .should('have.attr', 'aria-hidden', 'true'); }); it('should handle custom tooltip ID', () => { cy.mount(` `); cy.get('.usa-tooltip__body').should('have.id', 'custom-tooltip-123'); cy.get('.usa-tooltip__trigger').should('have.attr', 'aria-describedby', 'custom-tooltip-123'); }); it('should handle custom CSS classes', () => { cy.mount(` `); cy.get('.usa-tooltip').should('have.class', 'custom-tooltip-class'); }); it('should handle programmatic show/hide methods', () => { cy.mount(` `); cy.window().then((win) => { const tooltip = win.document.querySelector('usa-tooltip') as any; // Show programmatically tooltip.show(); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); // Hide programmatically tooltip.hide(); cy.get('.usa-tooltip__body').should('not.have.class', 'is-visible'); }); }); it('should handle toggle method', () => { cy.mount(` `); cy.window().then((win) => { const tooltip = win.document.querySelector('usa-tooltip') as any; // Toggle to show tooltip.toggle(); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); // Toggle to hide tooltip.toggle(); cy.get('.usa-tooltip__body').should('not.have.class', 'is-visible'); }); }); it('should handle tooltip positioning calculations', () => { cy.mount(`
`); cy.get('.usa-tooltip__trigger').trigger('mouseenter'); // Should have positioning styles applied cy.get('.usa-tooltip__body').should('have.class', 'usa-tooltip__body--top'); cy.get('.usa-tooltip__body').should('have.class', 'is-set'); // Check that positioning styles are applied cy.get('.usa-tooltip__body').should(($el) => { const style = $el[0].style; expect(style.left).to.not.be.empty; expect(style.margin).to.not.be.empty; }); }); it('should handle dynamic text updates', () => { cy.mount(` `); cy.get('.usa-tooltip__body').should('contain.text', 'Initial text'); cy.window().then((win) => { const tooltip = win.document.getElementById('dynamic-tooltip') as any; tooltip.text = 'Updated text'; }); cy.get('.usa-tooltip__body').should('contain.text', 'Updated text'); }); it('should handle positioning reset when hiding', () => { cy.mount(` `); // Show tooltip cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', 'is-set'); // Hide tooltip cy.get('.usa-tooltip__trigger').trigger('mouseleave'); // Positioning should be reset cy.get('.usa-tooltip__body').should(($el) => { const style = $el[0].style; expect(style.top).to.equal(''); expect(style.bottom).to.equal(''); expect(style.left).to.equal(''); expect(style.right).to.equal(''); expect(style.margin).to.equal(''); }); }); it('should prevent multiple shows when already visible', () => { cy.mount(` `); cy.window().then((win) => { const tooltip = win.document.querySelector('usa-tooltip') as any; const showSpy = cy.stub(); tooltip.addEventListener('tooltip-show', showSpy); // Trigger multiple show events cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.then(() => { // Should only fire once expect(showSpy).to.have.been.calledOnce; }); }); }); it('should handle complex trigger content', () => { cy.mount(`
🔧 Complex trigger with icon
`); cy.get('.complex-trigger').should('have.class', 'usa-tooltip__trigger'); // Should work with complex content cy.get('.complex-trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); cy.get('.usa-tooltip__body').should('contain.text', 'Complex content tooltip'); }); it('should handle keyboard navigation', () => { cy.mount(`
`); // Tab to first tooltip trigger cy.get('button').first().focus(); cy.get('.usa-tooltip__body').first().should('have.class', 'is-visible'); // Tab to second tooltip trigger cy.get('button').first().tab(); cy.get('.usa-tooltip__body').first().should('not.have.class', 'is-visible'); cy.get('.usa-tooltip__body').last().should('have.class', 'is-visible'); }); it('should handle tooltip with form elements', () => { cy.mount(`
`); // Form elements should not get tabindex (already focusable) cy.get('input.usa-tooltip__trigger').should('not.have.attr', 'tabindex'); cy.get('select.usa-tooltip__trigger').should('not.have.attr', 'tabindex'); // Should work with form elements cy.get('input').focus(); cy.get('.usa-tooltip__body').first().should('have.class', 'is-visible'); cy.get('select').focus(); cy.get('.usa-tooltip__body').first().should('not.have.class', 'is-visible'); cy.get('.usa-tooltip__body').last().should('have.class', 'is-visible'); }); it('should cleanup event listeners on disconnect', () => { cy.mount(`
`); cy.window().then((_win) => { // Verify tooltip exists and works cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); // Remove tooltip from DOM container!.removeChild(tooltip); // Should not cause errors when removed cy.get('body').type('{esc}'); // This should not cause errors }); }); it('should be accessible', () => { cy.mount(`

Accessible Tooltip Example

Hover or focus the button below for more information.

`); cy.injectAxe(); // Test with tooltip hidden cy.checkAccessibility(); // Test with tooltip visible cy.get('.usa-tooltip__trigger').focus(); cy.checkAccessibility(); }); it('should handle responsive positioning', () => { cy.mount(`
`); // Set small viewport cy.viewport(400, 400); cy.get('.usa-tooltip__trigger').trigger('mouseenter'); cy.get('.usa-tooltip__body').should('have.class', 'usa-tooltip__body--bottom'); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); }); it('should handle touch interactions', () => { cy.mount(` `); // Touch events should work similar to mouse events cy.get('.usa-tooltip__trigger').trigger('touchstart'); // Note: Actual touch behavior may vary by implementation // Focus should still work on touch devices cy.get('.usa-tooltip__trigger').focus(); cy.get('.usa-tooltip__body').should('have.class', 'is-visible'); }); });