<x-field> renders data-md-field with its props and parts as data-md-* attributes (box, control, label, outline, support, counter, trailing buttons), and field.css moves into material.components on tokens: px geometry, spacing and state tokens, the 600px breakpoint (plan step 36). Its icons take a size prop, 24/20/16 by the field's size. Every control the field wraps now marks itself data-md-field-control, so the inputs, the pickers, choices, field.js, menu.css's select and listbox rules and timepicker.css follow the renamed hooks. Browser tests cover the error icon, the disabled field's hover, the counter and the width bound from 600px. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
95 lines
3.6 KiB
PHP
95 lines
3.6 KiB
PHP
<?php
|
|
|
|
use Livewire\Component;
|
|
use Livewire\Livewire;
|
|
|
|
it('lays every option out as a filter chip', function () {
|
|
$html = (string) $this->blade('<x-choices label="Days" hint="Pick any" :value="[2]" :options="[[\'id\' => 1, \'name\' => \'Mon\'], [\'id\' => 2, \'name\' => \'Tue\'], [\'id\' => 3, \'name\' => \'Wed\', \'disabled\' => true]]" />');
|
|
|
|
expect($html)
|
|
->toContain('role="group"')
|
|
->toContain('Days')
|
|
->toContain('Pick any')
|
|
->toContain('x-modelable="selection"')
|
|
->toContain('x-on:click="toggle(0)"')
|
|
->toContain('x-bind:aria-pressed="selected(2).toString()"')
|
|
->and(substr_count($html, 'aria-pressed="true"'))->toBe(1)
|
|
->and(substr_count($html, 'aria-pressed="false"'))->toBe(2)
|
|
->and($html)->toContain('disabled');
|
|
});
|
|
|
|
it('entangles the selection with its Livewire property and renders it as the property says', function () {
|
|
Livewire::component('choices-probe', new class extends Component
|
|
{
|
|
/** @var list<int> */
|
|
public array $days = [1, 3];
|
|
|
|
public function render(): string
|
|
{
|
|
return '<div><x-choices wire:model.live="days" :options="[[\'id\' => 1, \'name\' => \'Mon\'], [\'id\' => 2, \'name\' => \'Tue\'], [\'id\' => 3, \'name\' => \'Wed\']]" /></div>';
|
|
}
|
|
});
|
|
|
|
$html = Livewire::test('choices-probe')->html();
|
|
|
|
expect($html)
|
|
->toContain(".entangle('days').live")
|
|
->not->toContain('x-modelable')
|
|
->and(substr_count($html, 'aria-pressed="true"'))->toBe(2);
|
|
});
|
|
|
|
it('draws a searchable combobox with a popover list', function () {
|
|
$html = (string) $this->blade('<x-choices id="zone" label="Time zone" searchable icon="public" value="Europe/Zurich" :options="[[\'id\' => \'Europe/Zurich\', \'name\' => \'Zurich\']]" />');
|
|
|
|
expect($html)
|
|
->toContain('role="combobox"')
|
|
->toContain('aria-controls="zone-list"')
|
|
->toContain('aria-expanded="false"')
|
|
->toContain('<ul')
|
|
->toContain('id="zone-list"')
|
|
->toContain('role="listbox"')
|
|
->toContain('popover="manual"')
|
|
->toMatch('/anchor-name: (--material-choices-[a-z0-9]{10})/')
|
|
->toContain('x-modelable="value"')
|
|
->toContain('data-md-field-arrow')
|
|
// WAI-ARIA's combobox keyboard, Home and End included.
|
|
->toContain('x-on:keydown.home="jump($event, false)"')
|
|
->toContain('x-on:keydown.end="jump($event, true)"')
|
|
->toContain('Nothing matches');
|
|
|
|
preg_match('/anchor-name: (--material-choices-[a-z0-9]{10})/', $html, $anchor);
|
|
|
|
expect($html)->toContain("position-anchor: {$anchor[1]}");
|
|
});
|
|
|
|
it('shows the errors for the property and its items', function () {
|
|
Livewire::component('choices-errors', new class extends Component
|
|
{
|
|
/** @var list<int> */
|
|
public array $days = [];
|
|
|
|
public ?string $zone = null;
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->addError('days.0', 'Mon is not a working day.');
|
|
$this->addError('zone', 'Choose a time zone.');
|
|
}
|
|
|
|
public function render(): string
|
|
{
|
|
return <<<'BLADE'
|
|
<div>
|
|
<x-choices wire:model="days" :options="[['id' => 1, 'name' => 'Mon']]" />
|
|
<x-choices wire:model="zone" searchable :options="[['id' => 'UTC', 'name' => 'UTC']]" />
|
|
</div>
|
|
BLADE;
|
|
}
|
|
});
|
|
|
|
expect(Livewire::test('choices-errors')->html())
|
|
->toContain('Mon is not a working day.')
|
|
->toContain('Choose a time zone.')
|
|
->toContain('aria-invalid="true"');
|
|
});
|