feat(form-builder): FormFieldValidationRuleService + legacy backfill + snapshot + library row-copy

This commit is contained in:
2026-04-24 22:12:08 +02:00
parent fedaed1b32
commit 800b1b6c01
16 changed files with 1430 additions and 18 deletions

View File

@@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
namespace Tests\Feature\FormBuilder\ValidationRules;
use App\Enums\FormBuilder\FormFieldType;
use App\Enums\FormBuilder\FormFieldValidationRuleType;
use App\Enums\FormBuilder\FormSchemaSnapshotMode;
use App\Enums\FormBuilder\FormSubmissionMode;
use App\Models\FormBuilder\FormField;
use App\Models\FormBuilder\FormFieldValidationRule;
use App\Models\FormBuilder\FormSchema;
use App\Models\Organisation;
use App\Services\FormBuilder\FormSubmissionService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
/**
* `form_submissions.schema_snapshot.fields[*].validation_rules` is now
* sourced from the relational table via
* `FormFieldValidationRuleService::toJsonShape()`. Given a field with
* known rules, the snapshot JSON embeds the canonical shape parity
* check against a freshly-rendered resource output.
*/
final class SchemaSnapshotValidationRulesParityTest extends TestCase
{
use RefreshDatabase;
public function test_snapshot_embeds_canonical_validation_rules_shape(): void
{
$org = Organisation::factory()->create();
$schema = FormSchema::factory()->create([
'organisation_id' => $org->id,
'submission_mode' => FormSubmissionMode::SINGLE,
'snapshot_mode' => FormSchemaSnapshotMode::ON_SUBMIT,
]);
$field = FormField::factory()->create([
'form_schema_id' => $schema->id,
'field_type' => FormFieldType::TEXT->value,
'slug' => 'voornaam',
]);
FormFieldValidationRule::factory()->forField($field)
->ofType(FormFieldValidationRuleType::MinLength, ['value' => 2])->create();
FormFieldValidationRule::factory()->forField($field)
->ofType(FormFieldValidationRuleType::MaxLength, ['value' => 40])->create();
$service = app(FormSubmissionService::class);
$snapshot = $this->invokeBuildSnapshot($service, $schema);
$fieldEntry = collect($snapshot['fields'])->firstWhere('slug', 'voornaam');
$this->assertNotNull($fieldEntry);
$this->assertSame([
'min_length' => 2,
'max_length' => 40,
], $fieldEntry['validation_rules']);
}
public function test_snapshot_validation_rules_null_when_no_rules(): void
{
$org = Organisation::factory()->create();
$schema = FormSchema::factory()->create(['organisation_id' => $org->id]);
FormField::factory()->create([
'form_schema_id' => $schema->id,
'slug' => 'noot',
]);
$service = app(FormSubmissionService::class);
$snapshot = $this->invokeBuildSnapshot($service, $schema);
$entry = collect($snapshot['fields'])->firstWhere('slug', 'noot');
$this->assertNull($entry['validation_rules']);
}
/** @return array<string, mixed> */
private function invokeBuildSnapshot(FormSubmissionService $service, FormSchema $schema): array
{
$ref = new \ReflectionMethod($service, 'buildSnapshot');
$ref->setAccessible(true);
return $ref->invoke($service, $schema);
}
}