CluPilotCloud/tests/Feature/EditInModalTest.php

79 lines
2.9 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'");
});