// 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
`);
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');
});
});