blade(''); expect($html) ->toContain('data-variant="outlined"') ->toContain('Share name') ->toMatch('/Share name<\/label>/') ->toContain('placeholder=" "') ->toContain('class="field-control"'); }); it('draws a filled field on request, or by the application\'s default', function () { expect((string) $this->blade(''))->toContain('data-variant="filled"'); config(['livewire-material.fields.variant' => 'filled']); expect((string) $this->blade(''))->toContain('data-variant="filled"') ->and((string) $this->blade(''))->toContain('data-variant="outlined"') ->and((string) $this->blade(''))->toContain('data-variant="filled"'); }); it('ties the label, the hint and the control together', function () { $html = (string) $this->blade(''); expect($html) ->toContain('') ->toContain('id="share-name"') ->toContain('aria-describedby="share-name-support"') ->toContain('Recipients see this name') ->toContain('wire:model="name"') ->not->toContain('aria-invalid'); }); it('replaces the hint with the errors for its model', function () { $html = (string) $this->withViewErrors(['email' => ['Enter a valid email address.']]) ->blade(''); expect($html) ->toContain('data-invalid') ->toContain('aria-invalid="true"') ->toContain('aria-describedby="email-support"') ->toContain('Enter a valid email address.') ->not->toContain('We never share it'); }); it('pairs the error colours with a trailing error icon', function () { $errors = ['email' => ['Enter a valid email address.']]; expect((string) $this->withViewErrors($errors)->blade('')) ->toContain('field-trailing field-error') ->toContain('aria-label="Error"') ->and((string) $this->withViewErrors($errors)->blade('')) ->not->toContain('field-error') ->and((string) $this->withViewErrors($errors)->blade('')) ->not->toContain('field-error') ->and((string) $this->blade('')) ->not->toContain('field-error'); }); it('puts icons, affixes and the size on the field, and every other attribute on the input', function () { $html = (string) $this->blade(''); expect($html) ->toContain('class="field w-40"') ->toContain('data-size="sm"') ->toContain('data-mono') ->toContain('data-readonly') ->toContain('CHF') ->toContain('per month') ->toContain('type="number"') ->toContain('min="0"') ->and(substr_count($html, 'toBe(2); }); it('offers to clear and to copy the value', function () { $html = (string) $this->blade(''); expect($html) ->toContain('data-field-clear') ->toContain('aria-label="Clear"') ->toContain('data-field-copy') ->toContain('navigator.clipboard.writeText') ->toContain('aria-label="Copy"'); }); it('lets a password be shown and hidden again', function () { $html = (string) $this->blade(''); expect($html) ->toContain('type="password"') ->not->toContain('type="text"') ->toContain('x-bind:type="shown ? \'text\' : \'password\'"') ->toContain('data-field-reveal') ->toContain('aria-label="Show password"') // The flipping label already says the state; aria-pressed would say it again, inverted. ->not->toContain('aria-pressed') ->toContain('autocomplete="current-password"'); }); it('grows a textarea from its rows up to its maximum, or leaves it to be resized', function () { expect((string) $this->blade('')) ->toContain('rows="2"') ->toContain('data-autogrow') ->toContain('--field-rows: 2;') ->toContain('--field-max-rows: 6;') ->and((string) $this->blade('')) ->toContain('rows="3"') ->not->toContain('data-autogrow'); }); it('draws a native select whose label always floats', function () { $html = (string) $this->blade(<<<'BLADE' BLADE); expect($html) ->toContain('data-floated') ->toContain('toContain('wire:model="hours"') ->toContain('Choose…') ->toContain('1 hour') ->toContain('30 days') ->toContain('field-arrow'); }); it('takes a select\'s options from its slot as well', function () { expect((string) $this->blade('Small')) ->toContain('Small'); }); it('collects a file field\'s own errors and each file\'s', function () { $html = (string) $this->withViewErrors([ 'photos' => ['Choose at most 10 photos.'], 'photos.0' => ['photo.jpg is larger than 2 GB.'], ])->blade(''); expect($html) ->toContain('type="file"') ->toContain('multiple') ->toContain('data-floated') ->toContain('Choose at most 10 photos.') ->toContain('photo.jpg is larger than 2 GB.'); }); it('lays out a form with its actions under an optional divider', function () { $html = (string) $this->blade(<<<'BLADE' Save BLADE); expect($html) ->toContain('') ->toContain('role="separator"') ->toContain('justify-between') ->toContain('Save') ->and((string) $this->blade('Save')) ->not->toContain('role="separator"'); });
Recipients see this name