// Comprehensive Behavioral Tests for usa-date-picker
// Focus on visual rendering, computed styles, positioning, and actual user-visible behavior
import './index.ts';
describe('USA Date Picker - Comprehensive Behavioral Tests', () => {
beforeEach(() => {
// Ignore script errors from USWDS JavaScript attempts
cy.on('uncaught:exception', (err, runnable) => {
if (err.message.includes('Script error')) {
return false;
}
});
});
describe('Visual Rendering and Display Verification', () => {
it('should have calendar popup that is actually visible when opened', () => {
cy.mount(``);
// Verify initial state - calendar should not be visible
cy.get('.usa-date-picker__calendar').should('not.exist');
// Click button to open calendar
cy.get('.usa-date-picker__button').click();
// Calendar should exist and be visually rendered
cy.get('.usa-date-picker__calendar').should('exist').and('be.visible');
// Verify calendar has actual content rendered
cy.get('.usa-date-picker__calendar__table').should('be.visible');
cy.get('.usa-date-picker__calendar__date').should('have.length.greaterThan', 0);
cy.get('.usa-date-picker__calendar__date').first().should('be.visible');
// Verify calendar has clickable date elements
cy.get('.usa-date-picker__calendar__date').first().should('not.have.css', 'pointer-events', 'none');
});
it('should verify calendar popup has correct visual dimensions and is not collapsed', () => {
cy.mount(``);
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Verify calendar has reasonable dimensions (not collapsed to 0)
cy.get('.usa-date-picker__calendar').then(($calendar) => {
const rect = $calendar[0].getBoundingClientRect();
expect(rect.width).to.be.greaterThan(200); // Calendar should have reasonable width
expect(rect.height).to.be.greaterThan(200); // Calendar should have reasonable height
});
// Verify calendar table has reasonable dimensions
cy.get('.usa-date-picker__calendar__table').then(($table) => {
const rect = $table[0].getBoundingClientRect();
expect(rect.width).to.be.greaterThan(150);
expect(rect.height).to.be.greaterThan(150);
});
});
it('should verify calendar dates are properly rendered and clickable', () => {
cy.mount(``);
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Check that date buttons have text content
cy.get('.usa-date-picker__calendar__date').each(($date) => {
cy.wrap($date).should('contain.text', /\d+/); // Should contain numbers
cy.wrap($date).should('have.css', 'cursor', 'pointer'); // Should be clickable
});
// Verify dates have proper dimensions (not collapsed)
cy.get('.usa-date-picker__calendar__date').first().then(($date) => {
const rect = $date[0].getBoundingClientRect();
expect(rect.width).to.be.greaterThan(20);
expect(rect.height).to.be.greaterThan(20);
});
});
it('should verify calendar navigation elements are visible and functional', () => {
cy.mount(``);
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Previous/next month buttons should be visible and clickable
cy.get('.usa-date-picker__calendar__previous-month')
.should('be.visible')
.should('contain.text', '‹')
.should('have.css', 'cursor', 'pointer');
cy.get('.usa-date-picker__calendar__next-month')
.should('be.visible')
.should('contain.text', '›')
.should('have.css', 'cursor', 'pointer');
// Month label should be visible with text
cy.get('.usa-date-picker__calendar__month-label')
.should('be.visible')
.should('contain.text', /\w+\s+\d{4}/); // Should contain month name and year
});
it('should detect if calendar is hidden by CSS display or visibility issues', () => {
cy.mount(``);
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Verify calendar is not hidden by common CSS issues
cy.get('.usa-date-picker__calendar').should('not.have.css', 'display', 'none');
cy.get('.usa-date-picker__calendar').should('not.have.css', 'visibility', 'hidden');
cy.get('.usa-date-picker__calendar').should('not.have.css', 'opacity', '0');
cy.get('.usa-date-picker__calendar').should('not.have.css', 'height', '0px');
cy.get('.usa-date-picker__calendar').should('not.have.css', 'width', '0px');
cy.get('.usa-date-picker__calendar').should('not.have.css', 'overflow', 'hidden');
});
});
describe('Computed Styles and CSS Verification', () => {
it('should verify calendar has proper z-index for layering above other content', () => {
// Add some background content to test layering
cy.mount(`
`);
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Calendar should have a high z-index to appear above other content
cy.get('.usa-date-picker__calendar').then(($calendar) => {
const zIndex = window.getComputedStyle($calendar[0]).zIndex;
// Z-index should be numeric and reasonably high (USWDS uses specific values)
expect(parseInt(zIndex) || 0).to.be.greaterThan(100);
});
});
it('should verify calendar positioning is correct (not off-screen)', () => {
cy.mount(``);
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Calendar should be positioned within viewport
cy.get('.usa-date-picker__calendar').then(($calendar) => {
const rect = $calendar[0].getBoundingClientRect();
const viewportWidth = Cypress.config('viewportWidth');
const viewportHeight = Cypress.config('viewportHeight');
// Calendar should be visible within viewport bounds
expect(rect.left).to.be.greaterThan(-10); // Allow small margin
expect(rect.top).to.be.greaterThan(-10);
expect(rect.right).to.be.lessThan(viewportWidth + 10);
expect(rect.bottom).to.be.lessThan(viewportHeight + 10);
});
});
it('should verify calendar has USWDS styling applied correctly', () => {
cy.mount(``);
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Verify USWDS classes are applied and have actual styles
cy.get('.usa-date-picker__calendar').then(($calendar) => {
const computedStyle = window.getComputedStyle($calendar[0]);
// Calendar should have background color (not transparent)
expect(computedStyle.backgroundColor).to.not.equal('rgba(0, 0, 0, 0)');
expect(computedStyle.backgroundColor).to.not.equal('transparent');
// Calendar should have border or shadow for visual separation
const hasBorder = computedStyle.border !== 'none' && computedStyle.border !== '0px';
const hasShadow = computedStyle.boxShadow !== 'none';
expect(hasBorder || hasShadow).to.be.true;
});
// Verify calendar dates have proper styling
cy.get('.usa-date-picker__calendar__date').first().then(($date) => {
const computedStyle = window.getComputedStyle($date[0]);
// Date buttons should have background or border
const hasBackground = computedStyle.backgroundColor !== 'rgba(0, 0, 0, 0)';
const hasBorder = computedStyle.border !== 'none';
expect(hasBackground || hasBorder).to.be.true;
});
});
it('should verify button icon is visible via CSS background-image', () => {
cy.mount(``);
// Button should have background-image for icon (USWDS pattern)
cy.get('.usa-date-picker__button').then(($button) => {
const computedStyle = window.getComputedStyle($button[0]);
// Should have background-image for icon
expect(computedStyle.backgroundImage).to.not.equal('none');
expect(computedStyle.backgroundImage).to.include('url(');
// Button should have reasonable dimensions for icon display
const rect = $button[0].getBoundingClientRect();
expect(rect.width).to.be.greaterThan(20);
expect(rect.height).to.be.greaterThan(20);
});
});
});
describe('Interaction Triggers and Focus Management', () => {
it('should verify calendar opens on multiple trigger methods', () => {
cy.mount(``);
// Test 1: Mouse click on button
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Close calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('not.be.visible');
// Test 2: Keyboard activation (Space)
cy.get('.usa-date-picker__button').focus().type(' ');
cy.get('.usa-date-picker__calendar').should('be.visible');
// Close and test Enter
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('not.be.visible');
// Test 3: Keyboard activation (Enter)
cy.get('.usa-date-picker__button').focus().type('{enter}');
cy.get('.usa-date-picker__calendar').should('be.visible');
});
it('should verify F4 key opens calendar from input field', () => {
cy.mount(``);
// Focus input and press F4
cy.get('.usa-input').focus().type('{f4}');
cy.get('.usa-date-picker__calendar').should('be.visible');
// Verify calendar is actually functional after F4 open
cy.get('.usa-date-picker__calendar__date').should('be.visible');
cy.get('.usa-date-picker__calendar__date').should('have.length.greaterThan', 0);
});
it('should verify Down Arrow key opens calendar from input field', () => {
cy.mount(``);
// Focus input and press Down Arrow
cy.get('.usa-input').focus().type('{downarrow}');
cy.get('.usa-date-picker__calendar').should('be.visible');
// Verify calendar content is rendered
cy.get('.usa-date-picker__calendar__table').should('be.visible');
});
it('should verify focus management when calendar opens and closes', () => {
cy.mount(``);
// Initial focus on input
cy.get('.usa-input').focus();
cy.get('.usa-input').should('be.focused');
// Open calendar via button
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Select a date
cy.get('.usa-date-picker__calendar__date').first().click();
// Calendar should close and focus should return to input
cy.get('.usa-date-picker__calendar').should('not.be.visible');
cy.get('.usa-input').should('have.value');
});
it('should verify click outside closes calendar', () => {
cy.mount(`
`);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Click outside
cy.get('#outside-element').click();
// Calendar should close
cy.get('.usa-date-picker__calendar').should('not.be.visible');
});
});
describe('Date Selection and Value Updates', () => {
it('should verify date selection updates input value and closes calendar', () => {
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Get initial input value
cy.get('.usa-input').invoke('val').then((initialValue) => {
// Click on a date
cy.get('.usa-date-picker__calendar__date').first().click();
// Calendar should close
cy.get('.usa-date-picker__calendar').should('not.be.visible');
// Input should have new value
cy.get('.usa-input').invoke('val').should('not.equal', initialValue);
cy.get('.usa-input').should('not.have.value', '');
});
});
it('should verify selected date appears highlighted in calendar', () => {
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// There should be a selected date with appropriate styling
cy.get('.usa-date-picker__calendar__date--selected').should('exist');
cy.get('.usa-date-picker__calendar__date--selected').should('be.visible');
// Selected date should have different visual styling
cy.get('.usa-date-picker__calendar__date--selected').then(($selected) => {
const computedStyle = window.getComputedStyle($selected[0]);
// Should have different background or text color
expect(computedStyle.backgroundColor).to.not.equal('rgba(0, 0, 0, 0)');
});
});
it('should verify today\'s date is highlighted appropriately', () => {
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Today's date should be marked if visible in current month
cy.get('.usa-date-picker__calendar__date--today').then(($today) => {
if ($today.length > 0) {
cy.wrap($today).should('be.visible');
// Today should have distinctive styling
cy.wrap($today).then(($el) => {
const computedStyle = window.getComputedStyle($el[0]);
expect(computedStyle.backgroundColor).to.not.equal('rgba(0, 0, 0, 0)');
});
}
});
});
});
describe('Month Navigation Functionality', () => {
it('should verify month navigation actually changes calendar content', () => {
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Get current month text
cy.get('.usa-date-picker__calendar__month-label').invoke('text').then((currentMonth) => {
// Click next month
cy.get('.usa-date-picker__calendar__next-month').click();
// Month should change
cy.get('.usa-date-picker__calendar__month-label').should('not.contain.text', currentMonth);
// Calendar should still be visible and functional
cy.get('.usa-date-picker__calendar').should('be.visible');
cy.get('.usa-date-picker__calendar__date').should('be.visible');
cy.get('.usa-date-picker__calendar__date').should('have.length.greaterThan', 0);
});
});
it('should verify previous month navigation works correctly', () => {
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Get current month text
cy.get('.usa-date-picker__calendar__month-label').invoke('text').then((currentMonth) => {
// Click previous month
cy.get('.usa-date-picker__calendar__previous-month').click();
// Month should change
cy.get('.usa-date-picker__calendar__month-label').should('not.contain.text', currentMonth);
// Calendar dates should be updated
cy.get('.usa-date-picker__calendar__date').should('be.visible');
});
});
it('should verify year changes when navigating past month boundaries', () => {
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Navigate through 12 months to test year rollover
for (let i = 0; i < 13; i++) {
cy.get('.usa-date-picker__calendar__next-month').click();
cy.wait(50); // Small delay for rendering
}
// Year should have changed
cy.get('.usa-date-picker__calendar__month-label').should('contain.text', '2025');
// Calendar should still be functional
cy.get('.usa-date-picker__calendar__date').should('be.visible');
});
});
describe('Error State and Edge Case Handling', () => {
it('should verify calendar remains functional when component has error state', () => {
cy.mount(``);
// Input should show error styling
cy.get('.usa-input').should('have.class', 'usa-input--error');
cy.get('.usa-error-message').should('be.visible');
// Calendar should still open and function
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Should be able to select dates
cy.get('.usa-date-picker__calendar__date').first().click();
cy.get('.usa-date-picker__calendar').should('not.be.visible');
cy.get('.usa-input').should('have.value');
});
it('should verify disabled state prevents calendar interaction', () => {
cy.mount(``);
// Button should be disabled
cy.get('.usa-date-picker__button').should('be.disabled');
cy.get('.usa-input').should('be.disabled');
// Clicking disabled button should not open calendar
cy.get('.usa-date-picker__button').click({ force: true });
cy.get('.usa-date-picker__calendar').should('not.exist');
});
it('should verify calendar handles min/max date constraints visually', () => {
const minDate = '2024-01-01';
const maxDate = '2024-01-31';
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Calendar should be showing January 2024 (within constraints)
cy.get('.usa-date-picker__calendar__month-label').should('contain.text', 'January 2024');
// All visible dates should be selectable (within range)
cy.get('.usa-date-picker__calendar__date').each(($date) => {
cy.wrap($date).should('not.have.attr', 'disabled');
});
});
});
describe('Performance and Responsiveness', () => {
it('should verify calendar opens quickly without noticeable delay', () => {
cy.mount(``);
const startTime = Date.now();
// Click to open calendar
cy.get('.usa-date-picker__button').click();
// Calendar should appear quickly (within reasonable time)
cy.get('.usa-date-picker__calendar').should('be.visible').then(() => {
const endTime = Date.now();
const duration = endTime - startTime;
expect(duration).to.be.lessThan(500); // Should open within 500ms
});
});
it('should verify calendar remains responsive during rapid interactions', () => {
cy.mount(``);
// Open calendar
cy.get('.usa-date-picker__button').click();
cy.get('.usa-date-picker__calendar').should('be.visible');
// Rapidly navigate months
for (let i = 0; i < 5; i++) {
cy.get('.usa-date-picker__calendar__next-month').click();
cy.get('.usa-date-picker__calendar__previous-month').click();
}
// Calendar should still be visible and functional
cy.get('.usa-date-picker__calendar').should('be.visible');
cy.get('.usa-date-picker__calendar__date').should('be.visible');
cy.get('.usa-date-picker__calendar__date').first().click();
cy.get('.usa-date-picker__calendar').should('not.be.visible');
});
it('should verify multiple date pickers can coexist without interference', () => {
cy.mount(`
`);
// Open first calendar
cy.get('#picker1 .usa-date-picker__button').click();
cy.get('#picker1 .usa-date-picker__calendar').should('be.visible');
// Second calendar should not be affected
cy.get('#picker2 .usa-date-picker__calendar').should('not.exist');
// Open second calendar (should close first)
cy.get('#picker2 .usa-date-picker__button').click();
cy.get('#picker2 .usa-date-picker__calendar').should('be.visible');
// Both calendars should be independently functional
cy.get('#picker2 .usa-date-picker__calendar__date').first().click();
cy.get('#picker2 .usa-date-picker__calendar').should('not.be.visible');
cy.get('#picker2 .usa-input').should('have.value');
});
});
});