Files
xamxam/tests/phpunit/AutofocusFieldForErrorTest.php
Pontoporeia 99125cc8e3 Add autosave draft system for partage form with HTMX-based session persistence
- New fragment endpoint POST/GET /partage/fragments/draft.php:
  saves all form fields to PHP session, excludes file/csrf/slug fields
  GET returns JSON for JS hydration on page load
  rotates both global CSRF and share CSRF tokens in sync

- form.php accepts optional $formExtraAttrs and $showAutosaveStatus:
  allows injecting HTMX attributes and 'Brouillon enregistré' indicator

- renderShareLinkForm adds hx-post with change/input debounce trigger,
  loads autosave-handler.js, hydrate fields from draft on page load

- Draft cleared on successful form submission in handleShareLinkSubmission

- autosave-handler.js now also updates share_link_token hidden input
  when rotating CSRF token (partage form uses both csrf_token and share_link_token)

- Added .autosave-status CSS to form.css (was admin.css-only)

- Updated fragment routing to accept GET requests (needed for draft hydration)
2026-06-11 11:04:49 +02:00

139 lines
5.6 KiB
PHP

<?php
use PHPUnit\Framework\TestCase;
/**
* AutofocusFieldForErrorTest — Tests for the autofocusFieldForError helpers
* on both ThesisCreateController and ThesisEditController.
*/
class AutofocusFieldForErrorTest extends TestCase
{
// ── ThesisCreateController::autofocusFieldForError ────────────────────────
public function testCreateAutofocusTitle(): void
{
$this->assertSame('titre', ThesisCreateController::autofocusFieldForError("Le champ 'Titre du TFE' est requis."));
}
public function testCreateAutofocusAuthors(): void
{
$this->assertSame('auteurice', ThesisCreateController::autofocusFieldForError("Le champ 'Auteur·ice(s)' est requis."));
}
public function testCreateAutofocusSynopsis(): void
{
$this->assertSame('synopsis', ThesisCreateController::autofocusFieldForError("Le champ 'Synopsis' est requis."));
}
public function testCreateAutofocusYear(): void
{
$this->assertSame('année', ThesisCreateController::autofocusFieldForError('Année invalide. Veuillez entrer une année valide.'));
}
public function testCreateAutofocusOrientation(): void
{
$this->assertSame('orientation', ThesisCreateController::autofocusFieldForError('Veuillez sélectionner une orientation.'));
}
public function testCreateAutofocusAP(): void
{
$this->assertSame('ap', ThesisCreateController::autofocusFieldForError("Veuillez sélectionner un 'Atelier Pratique'."));
}
public function testCreateAutofocusFinality(): void
{
$this->assertSame('finality', ThesisCreateController::autofocusFieldForError('La finalité est manquante.'));
}
public function testCreateAutofocusLanguages(): void
{
$this->assertSame('languages', ThesisCreateController::autofocusFieldForError('Veuillez sélectionner au moins une langue.'));
}
public function testCreateAutofocusPromoteur(): void
{
$this->assertSame('jury_promoteur', ThesisCreateController::autofocusFieldForError('Veuillez indiquer au moins un·e promoteur·ice.'));
}
public function testCreateAutofocusLecteurInterne(): void
{
$this->assertSame('jury_lecteur_interne[]', ThesisCreateController::autofocusFieldForError('Veuillez indiquer un·e lecteur·ice interne.'));
}
public function testCreateAutofocusLecteurExterne(): void
{
$this->assertSame('jury_lecteur_externe[]', ThesisCreateController::autofocusFieldForError('Veuillez indiquer un·e lecteur·ice externe.'));
}
public function testCreateAutofocusFormats(): void
{
$this->assertSame('formats', ThesisCreateController::autofocusFieldForError('Veuillez sélectionner au moins un format.'));
}
public function testCreateAutofocusLicense(): void
{
$this->assertSame('license_id', ThesisCreateController::autofocusFieldForError('Veuillez sélectionner une licence.'));
}
public function testCreateAutofocusUrl(): void
{
$this->assertSame('lien', ThesisCreateController::autofocusFieldForError('Lien URL invalide.'));
}
public function testCreateAutofocusTags(): void
{
$this->assertSame('tag', ThesisCreateController::autofocusFieldForError('Veuillez indiquer au moins 3 mots-clés.'));
}
public function testCreateAutofocusUnknownErrorReturnsNull(): void
{
$this->assertNull(ThesisCreateController::autofocusFieldForError('Some completely unrelated error'));
}
// ── ThesisEditController::autofocusFieldForError ──────────────────────────
public function testEditAutofocusTitle(): void
{
$this->assertSame('titre', ThesisEditController::autofocusFieldForError("Le champ 'Titre du TFE' est requis."));
}
public function testEditAutofocusYear(): void
{
$this->assertSame('année', ThesisEditController::autofocusFieldForError("L'année est invalide."));
}
public function testEditAutofocusSynopsis(): void
{
$this->assertSame('synopsis', ThesisEditController::autofocusFieldForError("Le champ 'Synopsis' est requis."));
}
public function testEditAutofocusAuthors(): void
{
$this->assertSame('auteurice', ThesisEditController::autofocusFieldForError("Le champ 'Auteur·ice(s)' est requis."));
}
public function testEditAutofocusUnknownErrorReturnsNull(): void
{
$this->assertNull(ThesisEditController::autofocusFieldForError('Some completely unrelated error'));
}
// ── No field name leak between Create and Edit controllers ────────────────
public function testCreateDoesNotLeakEditFieldNames(): void
{
// 'titre' is the Edit controller field name, but Create returns 'titre' too
// Actually check that Create-specific field names like 'auteurice' exist
// and that Edit doesn't return a Create-only name for an unrelated error
// Create returns 'auteurice' for author errors
$this->assertSame('auteurice', ThesisCreateController::autofocusFieldForError("Le champ 'Auteur·ice(s)' est requis."));
// Edit returns 'auteurice' for author errors too (same naming)
$this->assertSame('auteurice', ThesisEditController::autofocusFieldForError("Le champ 'Auteur·ice(s)' est requis."));
// Both return null for unknown errors (no spurious field)
$this->assertNull(ThesisCreateController::autofocusFieldForError('bogus error'));
$this->assertNull(ThesisEditController::autofocusFieldForError('bogus error'));
}
}