test(form-builder): cover purpose registry and morph-map alignment
- PurposeRegistryTest: all seven purposes load with expected shape; `get()` throws PurposeNotFoundException on unknown slug; `allSubjectTypes()` returns exactly [artist, company, person, user]; `publicAccessibleSlugs()` is only `[event_registration]`. - PurposeSchemaLifecycleTest: data-provider-driven create → publish for all seven purposes; negative tests for event_registration (three missing bindings) and supplier_intake (company.name missing); partial binding test reports only the missing subset. - CustomPurposeEscapeRemovedTest: column gone, config file gone, FormPurpose::CUSTOM gone, store endpoint rejects `'custom'`, resource payload omits the field. - SubjectTypeRegistryConsolidationTest: submission validation accepts registry subject types, rejects everything else including the legacy `event` alias that used to be allowed. - MorphMapAlignmentTest: compile-time guard that every PurposeRegistry::allSubjectTypes() alias appears in the morph-map and in AppServiceProvider::PURPOSE_SUBJECT_FQCN. - FormPurposeTest rewritten to cover the seven v1.0 cases and the registry-delegation helpers (now extends Tests\TestCase for the container). - Public/listener tests swap the removed PUBLIC_RSVP / PUBLIC_COMPLAINT / FEEDBACK references for valid v1.0 purposes, preserving their negative-path assertions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
60
api/tests/Feature/FormBuilder/MorphMapAlignmentTest.php
Normal file
60
api/tests/Feature/FormBuilder/MorphMapAlignmentTest.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature\FormBuilder;
|
||||
|
||||
use App\FormBuilder\Purposes\PurposeRegistry;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Compile-time guard: PurposeRegistry subject types MUST be registered in
|
||||
* the morph-map; otherwise polymorphic writes to form_submissions would
|
||||
* blow up at runtime. See ARCH-CONSOLIDATION-ADDENDUM-2026-04-24.md Q6.
|
||||
*
|
||||
* The reverse direction is NOT asserted end-to-end: the morph-map also
|
||||
* contains non-purpose domain types (owner_types, activity-log subjects)
|
||||
* and framework entries — those are intentionally broader.
|
||||
*/
|
||||
final class MorphMapAlignmentTest extends TestCase
|
||||
{
|
||||
public function test_every_purpose_subject_type_is_in_morph_map(): void
|
||||
{
|
||||
$registry = $this->app->make(PurposeRegistry::class);
|
||||
$morphMap = Relation::morphMap();
|
||||
|
||||
foreach ($registry->allSubjectTypes() as $alias) {
|
||||
$this->assertArrayHasKey(
|
||||
$alias,
|
||||
$morphMap,
|
||||
"Purpose subject_type '{$alias}' is declared in PurposeRegistry but "
|
||||
."missing from Relation::morphMap() in AppServiceProvider. "
|
||||
."Add it to the 'Domain subject types' block."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_domain_subject_types_block_matches_registry_exactly(): void
|
||||
{
|
||||
$registry = $this->app->make(PurposeRegistry::class);
|
||||
$registryAliases = $registry->allSubjectTypes();
|
||||
|
||||
// AppServiceProvider::PURPOSE_SUBJECT_FQCN is the single source of
|
||||
// truth for which aliases the domain-subject-types block can emit.
|
||||
// If the registry adds an alias not present in that lookup, boot()
|
||||
// would throw — but we also assert it here for fast feedback.
|
||||
$reflection = new \ReflectionClass(\App\Providers\AppServiceProvider::class);
|
||||
$lookup = $reflection->getConstant('PURPOSE_SUBJECT_FQCN');
|
||||
$this->assertIsArray($lookup);
|
||||
|
||||
foreach ($registryAliases as $alias) {
|
||||
$this->assertArrayHasKey(
|
||||
$alias,
|
||||
$lookup,
|
||||
"Purpose subject_type '{$alias}' has no FQCN in "
|
||||
."AppServiceProvider::PURPOSE_SUBJECT_FQCN. Register it there."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user