// Component tests for usa-memorable-date
import './index.ts';
describe('USA Memorable Date Component Tests', () => {
it('should render memorable date with default properties', () => {
cy.mount(``);
cy.get('usa-memorable-date').should('exist');
cy.get('.usa-memorable-date').should('exist');
cy.get('fieldset').should('exist');
cy.get('.usa-legend').should('contain.text', 'Date');
});
it('should render all three date fields', () => {
cy.mount(``);
// Month dropdown
cy.get('select[name="memorable-date-month"]').should('exist');
cy.get('label[for="memorable-date-month"]').should('contain.text', 'Month');
// Day input
cy.get('input[name="memorable-date-day"]').should('exist');
cy.get('label[for="memorable-date-day"]').should('contain.text', 'Day');
// Year input
cy.get('input[name="memorable-date-year"]').should('exist');
cy.get('label[for="memorable-date-year"]').should('contain.text', 'Year');
});
it('should populate month dropdown with all months', () => {
cy.mount(``);
cy.get('select[name="memorable-date-month"] option').should('have.length', 13);
cy.get('select[name="memorable-date-month"] option').first().should('contain.text', '- Select -');
cy.get('select[name="memorable-date-month"] option[value="01"]').should('contain.text', 'January');
cy.get('select[name="memorable-date-month"] option[value="12"]').should('contain.text', 'December');
});
it('should handle month selection', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Select March
cy.get('select[name="memorable-date-month"]').select('03');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match.hasNested('detail.month', '03')
);
});
});
});
it('should handle day input with validation', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Type valid day
cy.get('input[name="memorable-date-day"]').type('15');
cy.get('input[name="memorable-date-day"]').should('have.value', '15');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match.hasNested('detail.day', '15')
);
});
});
});
it('should validate day input range', () => {
cy.mount(``);
// Try to enter day > 31
cy.get('input[name="memorable-date-day"]').type('35');
cy.get('input[name="memorable-date-day"]').should('have.value', '31');
// Try to enter more than 2 digits
cy.get('input[name="memorable-date-day"]').clear().type('123');
cy.get('input[name="memorable-date-day"]').should('have.value', '12');
});
it('should handle year input with validation', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Type valid year
cy.get('input[name="memorable-date-year"]').type('1985');
cy.get('input[name="memorable-date-year"]').should('have.value', '1985');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match.hasNested('detail.year', '1985')
);
});
});
});
it('should limit year input to 4 digits', () => {
cy.mount(``);
// Try to enter more than 4 digits
cy.get('input[name="memorable-date-year"]').type('12345');
cy.get('input[name="memorable-date-year"]').should('have.value', '1234');
});
it('should prevent non-numeric input in day and year fields', () => {
cy.mount(``);
// Try to type letters in day field
cy.get('input[name="memorable-date-day"]').type('abc123def');
cy.get('input[name="memorable-date-day"]').should('have.value', '12');
// Try to type letters in year field
cy.get('input[name="memorable-date-year"]').type('abc2023def');
cy.get('input[name="memorable-date-year"]').should('have.value', '2023');
});
it('should handle complete date entry', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Enter complete date
cy.get('select[name="memorable-date-month"]').select('07');
cy.get('input[name="memorable-date-day"]').type('04');
cy.get('input[name="memorable-date-year"]').type('1976');
cy.then(() => {
// Should fire event with ISO date and validation
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match({
detail: Cypress.sinon.match({
month: '07',
day: '04',
year: '1976',
isoDate: '1976-07-04',
isValid: true,
isComplete: true
})
})
);
});
});
});
it('should validate date accuracy', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Enter invalid date (February 30th)
cy.get('select[name="memorable-date-month"]').select('02');
cy.get('input[name="memorable-date-day"]').type('30');
cy.get('input[name="memorable-date-year"]').type('2023');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match.hasNested('detail.isValid', false)
);
});
});
});
it('should handle custom label', () => {
cy.mount(`
`);
cy.get('.usa-legend').should('contain.text', 'Date of Birth');
});
it('should handle hint text', () => {
cy.mount(`
`);
cy.get('.usa-hint').should('contain.text', 'Please enter your birth date');
cy.get('.usa-hint').should('have.id', 'memorable-date-hint');
});
it('should handle required state', () => {
cy.mount(``);
cy.get('fieldset').should('have.class', 'usa-form-group--required');
cy.get('.usa-hint--required').should('exist').should('contain.text', '*');
// All inputs should have required attribute
cy.get('select[name="memorable-date-month"]').should('have.attr', 'required');
cy.get('input[name="memorable-date-day"]').should('have.attr', 'required');
cy.get('input[name="memorable-date-year"]').should('have.attr', 'required');
});
it('should handle disabled state', () => {
cy.mount(``);
// All inputs should be disabled
cy.get('select[name="memorable-date-month"]').should('be.disabled');
cy.get('input[name="memorable-date-day"]').should('be.disabled');
cy.get('input[name="memorable-date-year"]').should('be.disabled');
});
it('should handle custom name attribute', () => {
cy.mount(``);
cy.get('select[name="birthdate-month"]').should('exist');
cy.get('input[name="birthdate-day"]').should('exist');
cy.get('input[name="birthdate-year"]').should('exist');
cy.get('label[for="birthdate-month"]').should('exist');
cy.get('label[for="birthdate-day"]').should('exist');
cy.get('label[for="birthdate-year"]').should('exist');
});
it('should handle keyboard navigation', () => {
cy.mount(``);
// Tab through fields
cy.get('select[name="memorable-date-month"]').focus();
cy.focused().should('have.attr', 'name', 'memorable-date-month');
cy.focused().tab();
cy.focused().should('have.attr', 'name', 'memorable-date-day');
cy.focused().tab();
cy.focused().should('have.attr', 'name', 'memorable-date-year');
});
it('should handle special keys in numeric inputs', () => {
cy.mount(``);
// Test that special keys are allowed
cy.get('input[name="memorable-date-day"]')
.focus()
.type('{backspace}{delete}{home}{end}{leftarrow}{rightarrow}')
.type('15')
.should('have.value', '15');
// Test Ctrl+A, Ctrl+C, Ctrl+V
cy.get('input[name="memorable-date-year"]')
.focus()
.type('2023')
.type('{ctrl+a}')
.type('1985')
.should('have.value', '1985');
});
it('should programmatically set values', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
// Set values programmatically
dateComponent.setValue('08', '15', '1990');
cy.get('select[name="memorable-date-month"]').should('have.value', '08');
cy.get('input[name="memorable-date-day"]').should('have.value', '15');
cy.get('input[name="memorable-date-year"]').should('have.value', '1990');
});
});
it('should set from ISO date string', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
// Set from ISO date
dateComponent.setFromISODate('1965-12-25');
cy.get('select[name="memorable-date-month"]').should('have.value', '12');
cy.get('input[name="memorable-date-day"]').should('have.value', '25');
cy.get('input[name="memorable-date-year"]').should('have.value', '1965');
});
});
it('should clear all fields', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
// Set values first
dateComponent.setValue('03', '10', '2000');
// Then clear
dateComponent.clear();
cy.get('select[name="memorable-date-month"]').should('have.value', '');
cy.get('input[name="memorable-date-day"]').should('have.value', '');
cy.get('input[name="memorable-date-year"]').should('have.value', '');
});
});
it('should return date value object', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
dateComponent.setValue('06', '18', '1983');
const dateValue = dateComponent.getDateValue();
expect(dateValue).to.deep.equal({
month: '06',
day: '18',
year: '1983'
});
});
});
it('should handle leap year validation', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Test leap year (Feb 29, 2020)
cy.get('select[name="memorable-date-month"]').select('02');
cy.get('input[name="memorable-date-day"]').type('29');
cy.get('input[name="memorable-date-year"]').type('2020');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match.hasNested('detail.isValid', true)
);
});
// Test non-leap year (Feb 29, 2021)
cy.get('input[name="memorable-date-year"]').clear().type('2021');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match.hasNested('detail.isValid', false)
);
});
});
});
it('should handle form integration', () => {
cy.mount(`
`);
// Set date values
cy.get('select[name="event-date-month"]').select('09');
cy.get('input[name="event-date-day"]').type('11');
cy.get('input[name="event-date-year"]').type('2001');
// Check that form can access values
cy.window().then((win) => {
const form = win.document.getElementById('test-form') as HTMLFormElement;
const formData = new FormData(form);
expect(formData.get('event-date-month')).to.equal('09');
expect(formData.get('event-date-day')).to.equal('11');
expect(formData.get('event-date-year')).to.equal('2001');
});
});
it('should handle aria attributes correctly', () => {
cy.mount(`
`);
// Check fieldset structure
cy.get('fieldset').should('exist');
cy.get('.usa-legend').should('exist');
// Check aria-describedby references
cy.get('select[name="memorable-date-month"]')
.should('have.attr', 'aria-describedby', 'memorable-date-hint');
cy.get('input[name="memorable-date-day"]')
.should('have.attr', 'aria-describedby', 'memorable-date-hint');
cy.get('input[name="memorable-date-year"]')
.should('have.attr', 'aria-describedby', 'memorable-date-hint');
// Check input attributes
cy.get('input[name="memorable-date-day"]')
.should('have.attr', 'inputmode', 'numeric')
.should('have.attr', 'pattern', '[0-9]*');
cy.get('input[name="memorable-date-year"]')
.should('have.attr', 'inputmode', 'numeric')
.should('have.attr', 'pattern', '[0-9]*');
});
it('should handle month padding correctly', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
// Set single digit month
dateComponent.month = '5';
// Should pad to 2 digits in display
cy.get('select[name="memorable-date-month"]').should('have.value', '05');
});
});
it('should handle incomplete dates', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Set partial date (missing year)
cy.get('select[name="memorable-date-month"]').select('04');
cy.get('input[name="memorable-date-day"]').type('15');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match({
detail: Cypress.sinon.match({
isComplete: false,
isValid: false,
isoDate: ''
})
})
);
});
});
});
it('should handle edge case dates', () => {
cy.mount(``);
cy.window().then((win) => {
const dateComponent = win.document.getElementById('test-date') as any;
const changeSpy = cy.stub();
dateComponent.addEventListener('date-change', changeSpy);
// Test April 31st (invalid)
cy.get('select[name="memorable-date-month"]').select('04');
cy.get('input[name="memorable-date-day"]').type('31');
cy.get('input[name="memorable-date-year"]').type('2023');
cy.then(() => {
expect(changeSpy).to.have.been.calledWith(
Cypress.sinon.match.hasNested('detail.isValid', false)
);
});
});
});
it('should be accessible', () => {
cy.mount(`
Event Registration
`);
cy.injectAxe();
cy.checkAccessibility();
});
it('should handle custom CSS classes', () => {
cy.mount(`
`);
cy.get('usa-memorable-date').should('have.class', 'custom-date-class');
cy.get('.usa-memorable-date').should('exist');
});
it('should handle focus and blur events', () => {
cy.mount(``);
// Focus and blur each field
cy.get('select[name="memorable-date-month"]').focus().blur();
cy.get('input[name="memorable-date-day"]').focus().blur();
cy.get('input[name="memorable-date-year"]').focus().blur();
// Should not cause any errors
cy.get('usa-memorable-date').should('exist');
});
it('should handle mobile input behavior', () => {
cy.mount(``);
// Set mobile viewport
cy.viewport(375, 667);
// Numeric inputs should show numeric keyboard
cy.get('input[name="memorable-date-day"]')
.should('have.attr', 'inputmode', 'numeric')
.should('have.attr', 'pattern', '[0-9]*');
cy.get('input[name="memorable-date-year"]')
.should('have.attr', 'inputmode', 'numeric')
.should('have.attr', 'pattern', '[0-9]*');
});
});