get($path, fn () => Blade::render(<< @vite(config('livewire-material.showcase.vite')) @livewireStyles {$body} @livewireScripts BLADE)); return layoutReady(visit($path)->resize($width, $height)); } function layoutReady(mixed $page): mixed { return $page->waitForEvent('networkidle') ->assertScript("document.readyState === 'complete' && typeof window.Alpine !== 'undefined' && typeof window.Livewire !== 'undefined'"); } /** A computed style of the element matching the selector. */ function layoutStyle(string $selector, string $property): string { return "getComputedStyle(document.querySelector('{$selector}')).{$property}"; } /** A side of the element's box, rounded to the pixel. */ function layoutRect(string $selector, string $side): string { return "Math.round(document.querySelector('{$selector}').getBoundingClientRect().{$side})"; } /** How many column tracks a grid has. */ function layoutColumns(string $selector): string { return layoutStyle($selector, 'gridTemplateColumns').".split(' ').length"; } it('spaces a stack with its token, never with its parent\'s, and hides it from a breakpoint over its own display', function () { $body = '

One

Two

Three

' .'

Compact only

'; layoutPage($body, 599) ->assertScript(layoutStyle('#outer', 'flexDirection')." === 'column'") ->assertScript(layoutStyle('#outer', 'rowGap')." === '24px'") ->assertScript(layoutStyle('#inner', 'rowGap')." === '0px'") ->assertScript(layoutStyle('#hidden-from', 'display')." === 'flex'"); layoutPage($body, 600) ->assertScript(layoutStyle('#hidden-from', 'display')." === 'none'"); }); it('stacks a row below its breakpoint and lays it side by side from it', function () { $body = 'OneTwo' .'One' .'Medium and up'; layoutPage($body, 599) ->assertScript(layoutStyle('#row', 'flexDirection')." === 'column'") ->assertScript(layoutStyle('#row', 'alignItems')." === 'stretch'") ->assertScript(layoutStyle('#aligned', 'alignItems')." === 'flex-start'") ->assertScript(layoutStyle('#row', 'rowGap')." === '16px'") ->assertScript(layoutStyle('#hidden', 'display')." === 'none'"); layoutPage($body, 600) ->assertScript(layoutStyle('#row', 'flexDirection')." === 'row'") ->assertScript(layoutStyle('#row', 'alignItems')." === 'center'") ->assertScript(layoutStyle('#hidden', 'display')." === 'flex'"); }); it('mirrors a row in a right-to-left document', function () { layoutPage('FirstSecond', 800, 600, 'rtl') ->assertScript(layoutRect('#first', 'left').' > '.layoutRect('#second', 'left')); }); it('gives a grid its columns per breakpoint, and a nested grid its own', function () { $body = <<<'BLADE'
A
B
2
3
4
BLADE; layoutPage($body, 599) ->assertScript(layoutColumns('#outer').' === 1') ->assertScript(layoutColumns('#inner').' === 1'); layoutPage($body, 600) ->assertScript(layoutColumns('#outer').' === 3') ->assertScript(layoutStyle('#outer', 'columnGap')." === '16px'") // The parent's three never reach the grid inside it. ->assertScript(layoutColumns('#inner').' === 1'); layoutPage($body, 1199)->assertScript(layoutColumns('#outer').' === 3'); layoutPage($body, 1200)->assertScript(layoutColumns('#outer').' === 4'); }); it('fills a grid with columns of a minimum width, capped by the count', function () { $body = '
1
2
3
4
' .'
1
2
3
4
'; layoutPage($body, 800) ->assertScript(layoutColumns('#fill').' === 3') ->assertScript(layoutColumns('#capped').' === 2'); });