111 lines
4.5 KiB
PHP
111 lines
4.5 KiB
PHP
<?php
|
|
|
|
use Illuminate\Support\Facades\File;
|
|
|
|
/**
|
|
* R20 — editing with fields happens in a modal, never in the row.
|
|
*
|
|
* Inline editing was tried once, on the seats table. It worked and it looked
|
|
* broken: the row grew as the inputs appeared, the columns beside it jumped,
|
|
* and a table half in edit mode reads as a rendering fault rather than as a
|
|
* form. The project already had a modal for exactly this (EditDatacenter);
|
|
* the seats table simply did not use it.
|
|
*
|
|
* So the rule is mechanical: a page view that would grow input fields into a
|
|
* table row fails this test. Forms that ARE the page — a create form, a
|
|
* settings panel, the invite row above a table — are not editing an existing
|
|
* record in place and are untouched by this.
|
|
*/
|
|
|
|
/** Views that legitimately hold their own fields: they are forms, not rows. */
|
|
function isModalOrForm(string $path): bool
|
|
{
|
|
return str_contains($path, '/components/')
|
|
|| preg_match('#/livewire/(admin/)?(edit|confirm|create|new)-#', $path) === 1
|
|
|| preg_match('#/(auth|errors|mail)/#', $path) === 1;
|
|
}
|
|
|
|
it('never grows input fields inside a table row', function () {
|
|
$offenders = [];
|
|
|
|
foreach (File::allFiles(resource_path('views')) as $file) {
|
|
$path = str_replace(base_path().'/', '', $file->getPathname());
|
|
|
|
if (isModalOrForm($path)) {
|
|
continue;
|
|
}
|
|
|
|
$source = $file->getContents();
|
|
|
|
// Look only INSIDE <td>…</td>: a field in a table cell is an inline
|
|
// editor by definition. Fields elsewhere on the page are a form.
|
|
foreach (preg_split('#</td>#', $source) as $segment) {
|
|
$open = strrpos($segment, '<td');
|
|
|
|
// No cell opened in this segment — everything before the first
|
|
// <td> is page, not row. Without this the whole file counted as
|
|
// one cell and every ordinary form failed.
|
|
if ($open === false) {
|
|
continue;
|
|
}
|
|
|
|
$cell = substr($segment, $open);
|
|
|
|
if (preg_match('#<(input|textarea)\b(?![^>]*type="(checkbox|radio|hidden)")#', $cell, $m)) {
|
|
$offenders[$path][] = trim(strtok(ltrim($cell), "\n") ?: $m[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
expect($offenders)->toBe([]);
|
|
});
|
|
|
|
it('reaches every edit modal through openModal', function () {
|
|
// An edit button that calls a method on the page component instead of
|
|
// dispatching openModal is the inline editor coming back under a new name.
|
|
$modals = collect(File::allFiles(app_path('Livewire')))
|
|
->filter(fn ($f) => str_contains($f->getContents(), 'extends ModalComponent'))
|
|
->map(fn ($f) => $f->getFilenameWithoutExtension())
|
|
->values();
|
|
|
|
expect($modals)->toContain('EditSeat')
|
|
->and($modals)->toContain('EditDatacenter');
|
|
|
|
// And the seats table actually opens it.
|
|
$users = File::get(resource_path('views/livewire/users.blade.php'));
|
|
|
|
expect($users)->toContain("component: 'edit-seat'");
|
|
});
|
|
|
|
it('closes every modal through the event the modal actually listens for', function () {
|
|
// Alpine's $dispatch fires a browser DOM event; wire-elements/modal listens
|
|
// for a LIVEWIRE event of that name. A cancel button written the Alpine way
|
|
// therefore does nothing at all — reported on the mail-template modal, where
|
|
// saving worked and cancelling did not. Every other modal in the repo was
|
|
// already correct, which is exactly why nobody noticed the odd one out.
|
|
$offenders = collect(File::allFiles(resource_path('views')))
|
|
->filter(fn ($file) => str_ends_with($file->getFilename(), '.blade.php'))
|
|
->filter(function ($file) {
|
|
// Blade comments stripped first: this file's own explanation of the
|
|
// wrong form must not read as an offence.
|
|
$body = preg_replace('/\{\{--.*?--\}\}/s', '', $file->getContents());
|
|
|
|
// ALPINE's $dispatch only. wire:click="$dispatch('closeModal')" is
|
|
// Livewire's own dispatcher and works — the broken form is the one
|
|
// bound through an Alpine handler, where $dispatch means the DOM.
|
|
return preg_match(
|
|
'/(?:x-on:click|@click)\s*=\s*"[^"]*\$dispatch\(\s*[\'"]closeModal/',
|
|
(string) $body,
|
|
) === 1;
|
|
})
|
|
->map(fn ($file) => $file->getRelativePathname())
|
|
->values()
|
|
->all();
|
|
|
|
expect($offenders)->toBe([]);
|
|
|
|
// And the working form is the one in use.
|
|
expect(File::get(resource_path('views/livewire/admin/edit-mail-template.blade.php')))
|
|
->toContain("Livewire.dispatch('closeModal')");
|
|
});
|