create(); $this->assertSame(26, mb_strlen($schema->id)); } public function test_form_schema_is_org_scoped(): void { $orgA = Organisation::factory()->create(); $orgB = Organisation::factory()->create(); FormSchema::factory()->count(2)->create(['organisation_id' => $orgA->id]); FormSchema::factory()->count(3)->create(['organisation_id' => $orgB->id]); // Without context: scope is a no-op (CLI tests have no route context) $this->assertSame(5, FormSchema::query()->count()); // Manually-applied scope filters by org $orgAOnly = FormSchema::query() ->where('organisation_id', $orgA->id) ->count(); $this->assertSame(2, $orgAOnly); } public function test_form_schema_morphs_to_owner(): void { $event = Event::factory()->create(); $schema = FormSchema::factory()->create([ 'organisation_id' => $event->organisation_id, 'owner_type' => 'event', 'owner_id' => $event->id, ]); $this->assertInstanceOf(Event::class, $schema->owner); $this->assertSame($event->id, $schema->owner->id); } public function test_form_schema_casts_purpose_to_enum(): void { $schema = FormSchema::factory()->forPurpose(FormPurpose::INCIDENT_REPORT)->create(); $this->assertSame(FormPurpose::INCIDENT_REPORT, $schema->fresh()->purpose); } public function test_form_schema_has_many_fields_and_submissions(): void { $schema = FormSchema::factory()->create(); FormField::factory()->count(3)->for($schema, 'schema')->create(); FormSubmission::factory()->count(2)->create(['form_schema_id' => $schema->id]); $this->assertCount(3, $schema->fresh()->fields); $this->assertCount(2, $schema->fresh()->submissions); } public function test_log_schema_change_creates_activity_entry(): void { Activity::query()->delete(); $schema = FormSchema::factory()->create(); $schema->logSchemaChange('schema.published', ['by' => 'admin']); $entry = Activity::query() ->where('subject_type', $schema->getMorphClass()) ->where('subject_id', $schema->id) ->first(); $this->assertNotNull($entry); $this->assertSame('schema.published', $entry->description); $this->assertSame('admin', $entry->properties->get('by')); } }