Cover the datepicker's shared classes, hover layer and 20px root font
Browser-test coverage the reviewer asked for on the step 36 batch: the year, menu-button and list-option state layer/focus ring (with the option's ring drawn inset in its row), a selected day's hover layer over its primary fill versus none on a disabled or blank day, and the 40px day indicator holding its size at a 20px root font size while only its (rem-sized) text grows. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c72908458b
commit
0b7dd7d46a
@@ -581,3 +581,99 @@ it('reaches the month and year dropdowns with Shift+M and Shift+Y', function ()
|
|||||||
$page->keys(':focus', 'Shift+Y')
|
$page->keys(':focus', 'Shift+Y')
|
||||||
->assertScript("document.activeElement.dataset.mdDatepickerMenuButton === 'years'");
|
->assertScript("document.activeElement.dataset.mdDatepickerMenuButton === 'years'");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('draws the shared state layer and focus ring on the menu buttons, the year and the list options, the option\'s ring drawn inset', function () {
|
||||||
|
$monthButton = '#expires-field-picker [data-md-datepicker-menu-button="months"]';
|
||||||
|
$yearButton = '#expires-field-picker [data-md-datepicker-menu-button="years"]';
|
||||||
|
$modalYearButton = '#birthday-field-picker [data-md-datepicker-nav]:not([data-md-docked]) [data-md-datepicker-menu-button]';
|
||||||
|
$selectedOption = "document.querySelector('#expires-field-picker [data-md-datepicker-option][aria-selected=\"true\"]')";
|
||||||
|
$selectedYear = "document.querySelector('#birthday-field-picker [data-md-datepicker-year][aria-selected=\"true\"]')";
|
||||||
|
|
||||||
|
$hasBoth = fn (string $expr): string => "({$expr}).classList.contains('md-state-layer') && ({$expr}).classList.contains('md-focus-ring')";
|
||||||
|
|
||||||
|
$page = dateProbe()
|
||||||
|
->click('[aria-controls="expires-field-picker"][data-md-datepicker-toggle]')
|
||||||
|
->assertScript($hasBoth("document.querySelector('{$monthButton}')"))
|
||||||
|
->assertScript($hasBoth("document.querySelector('{$yearButton}')"))
|
||||||
|
->click($monthButton)
|
||||||
|
// toggleView() scrolls the selected option into view and focuses it once settled.
|
||||||
|
->assertScript("document.activeElement === {$selectedOption}")
|
||||||
|
->assertScript($hasBoth($selectedOption))
|
||||||
|
// A real keydown (rather than the script focus above) puts the browser in keyboard
|
||||||
|
// modality, so :focus-visible — and the ring the foundation draws inside the row rather
|
||||||
|
// than round the control — actually applies.
|
||||||
|
->keys(':focus', 'ArrowDown')
|
||||||
|
->assertScript("document.activeElement.matches('[data-md-datepicker-option]')")
|
||||||
|
->assertScript("getComputedStyle(document.activeElement).outlineOffset === '-3px'");
|
||||||
|
|
||||||
|
// Close the docked popover, or it sits over the next field and swallows the click below.
|
||||||
|
$page->keys(':focus', 'Escape')
|
||||||
|
->assertScript("! document.querySelector('#expires-field-picker').matches(':popover-open')");
|
||||||
|
|
||||||
|
$page->click('#birthday-field')
|
||||||
|
->assertScript("document.querySelector('#birthday-field-picker').matches(':modal')")
|
||||||
|
->click($modalYearButton)
|
||||||
|
->assertScript($hasBoth("document.querySelector('{$modalYearButton}')"))
|
||||||
|
->assertScript("document.activeElement === {$selectedYear}")
|
||||||
|
->assertScript($hasBoth($selectedYear));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows a state layer over a selected day\'s primary fill on hover, and none on a disabled or blank day', function () {
|
||||||
|
$selectedDay = day('expires-field', '2026-09-13');
|
||||||
|
$selectedSpan = "document.querySelector('{$selectedDay} > span')";
|
||||||
|
$disabledDay = day('expires-field', '2026-09-09');
|
||||||
|
$disabledSpan = "document.querySelector('{$disabledDay} > span')";
|
||||||
|
|
||||||
|
$page = dateProbe()
|
||||||
|
->click('[aria-controls="expires-field-picker"][data-md-datepicker-toggle]')
|
||||||
|
->assertScript("document.querySelector('{$selectedDay}').hasAttribute('data-md-selected')")
|
||||||
|
->assertAttribute($disabledDay, 'aria-disabled', 'true')
|
||||||
|
// The day's own fill transitions in when the popover opens: let it settle before reading
|
||||||
|
// a resting value, or the "unchanged by hover" comparison below race against that instead.
|
||||||
|
->wait(0.3);
|
||||||
|
|
||||||
|
$fill = $page->script("getComputedStyle({$selectedSpan}).backgroundColor");
|
||||||
|
|
||||||
|
$page->hover($selectedDay)
|
||||||
|
// The layer draws over the same primary fill: hovering never changes the day's own background.
|
||||||
|
->assertScript("getComputedStyle({$selectedSpan}).backgroundColor === '{$fill}'")
|
||||||
|
->assertScript("getComputedStyle({$selectedSpan}, '::before').opacity !== '0'");
|
||||||
|
|
||||||
|
$page->hover($disabledDay)
|
||||||
|
->assertScript("getComputedStyle({$disabledSpan}, '::before').display === 'none'");
|
||||||
|
|
||||||
|
$page->script("document.querySelector('{$disabledDay}').focus()");
|
||||||
|
|
||||||
|
$page->assertScript("document.activeElement === document.querySelector('{$disabledDay}')")
|
||||||
|
->assertScript("getComputedStyle({$disabledSpan}, '::before').display === 'none'");
|
||||||
|
|
||||||
|
// Close the docked popover, or it sits over the next field and swallows the click below.
|
||||||
|
$page->keys(':focus', 'Escape')
|
||||||
|
->assertScript("! document.querySelector('#expires-field-picker').matches(':popover-open')");
|
||||||
|
|
||||||
|
// A blank cell (no date, outside the shown month in modal presentation) can't be focused at
|
||||||
|
// all — the same rule hides its layer regardless.
|
||||||
|
$page->click('#birthday-field')
|
||||||
|
->assertScript("document.querySelector('#birthday-field-picker').matches(':modal')")
|
||||||
|
->hover('#birthday-field-picker [data-md-blank] > span >> nth=0')
|
||||||
|
->assertScript("getComputedStyle([...document.querySelectorAll('#birthday-field-picker [data-md-blank] > span')][0], '::before').display === 'none'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps the day indicator its fixed 40px size at a 20px root font size, growing only its text', function () {
|
||||||
|
$daySpan = "document.querySelector('".day('expires-field', '2026-09-13')." > span')";
|
||||||
|
$width = "Math.round({$daySpan}.getBoundingClientRect().width)";
|
||||||
|
$font = "getComputedStyle({$daySpan}).fontSize";
|
||||||
|
$picker = "document.querySelector('#expires-field-picker')";
|
||||||
|
|
||||||
|
$page = dateProbe()->click('[aria-controls="expires-field-picker"][data-md-datepicker-toggle]');
|
||||||
|
|
||||||
|
$restingWidth = (int) $page->script($width);
|
||||||
|
$restingFont = $page->script($font);
|
||||||
|
|
||||||
|
$page->script("document.documentElement.style.fontSize = '20px'");
|
||||||
|
|
||||||
|
$page->assertScript("({$width}) === {$restingWidth}")
|
||||||
|
->assertScript("({$font}) !== '{$restingFont}'")
|
||||||
|
// The px-sized grid sets the popover's size, not the (rem-sized) text now growing inside it.
|
||||||
|
->assertScript("{$picker}.scrollWidth <= {$picker}.clientWidth + 1 && {$picker}.scrollHeight <= {$picker}.clientHeight + 1");
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user