toContain('x-on:keydown="key($event)"')
->toContain('x-on:focusin="rove($event.target)"')
->toContain("id=\"{$labelledBy[1]}\" data-md-chip-set-label>File types")
->toContain("id=\"{$describedBy[1]}\" data-md-chip-set-hint>Show only these")
->not->toContain('data-md-scroll')
->not->toContain('flex-wrap');
});
it('draws the set from its stylesheet: 8px between chips, wrapping unless it scrolls', function () {
$css = (string) file_get_contents(__DIR__.'/../../../resources/css/components/chip-set.css');
expect($css)->toContain("@import './chip.css';")
->toMatch('/\[data-md-chip-set-row\] \{\s*display: flex;\s*flex-wrap: wrap;\s*gap: var\(--md-sys-measurement-space100\);/')
->toContain('[data-md-chip-set-scroller] > [data-md-chip-set-row] {')
->and((string) file_get_contents(__DIR__.'/../../../resources/css/components.css'))->toContain("@import './components/chip-set.css';");
});
it('scrolls a chip set on one line with fading edges', function () {
expect((string) $this->blade('
'))
->toContain('aria-label="Sort"')
->toMatch('/data-md-chip-set\s+data-md-scroll\s/')
->toContain('
')
->toContain('x-ref="row"')
->toContain('wire:ignore.self')
->and((string) file_get_contents(__DIR__.'/../../../resources/css/components/chip-set.css'))
->toContain('overflow-x: auto;')
->toContain('--chip-fade-start: var(--md-sys-measurement-space300);');
});
it('puts a scroll button over each fading edge, for a pointer that cannot swipe', function () {
$html = (string) $this->blade('
');
expect($html)
->toContain('data-md-chip-scroll="start"')
->toContain('data-md-chip-scroll="end"')
->toContain('x-on:click="nudge(\'start\')"')
->toContain('x-on:click="nudge(\'end\')"')
// A pointer affordance, not a tab stop: the arrows already walk every chip.
->toContain('tabindex="-1"')
->toContain('aria-hidden="true"')
->toContain('data-md-mirror-rtl');
expect((string) file_get_contents(__DIR__.'/../../../resources/css/components/chip-set.css'))
// Only while the row can still scroll that way, and only where the pointer is fine.
->toMatch("/@media \(pointer: fine\) \{\s*\[data-md-chip-set-row\]\[data-md-scroll-start\] ~ \[data-md-chip-scroll='start'\],\s*\[data-md-chip-set-row\]\[data-md-scroll-end\] ~ \[data-md-chip-scroll='end'\] \{\s*display: grid;/")
// A chip the keyboard reaches clears the buttons as well as the fade.
->toContain('scroll-padding-inline: var(--md-sys-measurement-space500);');
// A wrapping set has no edge to scroll towards.
expect((string) $this->blade('
'))
->not->toContain('data-md-chip-scroll');
});
it('binds filter chips to a Livewire array and shows the set\'s validation message in place of its hint', function () {
$component = new class extends Component
{
/** @var list
*/
public array $kinds = ['photos'];
public function save(): void
{
$this->validate(['kinds' => 'max:1'], ['kinds.max' => 'Pick one kind.']);
}
public function render(): string
{
return <<<'BLADE'
BLADE;
}
};
Livewire::test($component)
->assertSeeHtml('wire:model.live="kinds"')
->assertSeeHtml('value="photos" checked')
->assertDontSeeHtml('value="documents" checked')
->assertSee('Show only these')
->set('kinds', ['photos', 'documents'])
->assertSeeHtml('value="documents" checked')
->call('save')
->assertSee('Pick one kind.')
->assertDontSee('Show only these');
});