create(); $schema = FormSchema::factory()->create(['organisation_id' => $org->id]); $field = FormField::factory()->create(['form_schema_id' => $schema->id]); FormFieldValidationRule::factory()->forField($field)->create(); FormFieldValidationRule::factory() ->forField($field) ->ofType(\App\Enums\FormBuilder\FormFieldValidationRuleType::MaxLength, ['value' => 10]) ->create(); $this->assertSame(2, FormFieldValidationRule::query() ->withoutGlobalScopes() ->where('owner_type', 'form_field') ->where('owner_id', $field->id) ->count(), ); $field->delete(); // soft delete on FormField $this->assertSame(0, FormFieldValidationRule::query() ->withoutGlobalScopes() ->where('owner_type', 'form_field') ->where('owner_id', $field->id) ->count(), ); } public function test_delete_of_library_entry_cascades_validation_rules(): void { $org = Organisation::factory()->create(); $library = FormFieldLibrary::factory()->create(['organisation_id' => $org->id]); FormFieldValidationRule::factory()->forLibrary($library)->create(); $this->assertSame(1, FormFieldValidationRule::query() ->withoutGlobalScopes() ->where('owner_type', 'form_field_library') ->where('owner_id', $library->id) ->count(), ); $library->delete(); $this->assertSame(0, FormFieldValidationRule::query() ->withoutGlobalScopes() ->where('owner_type', 'form_field_library') ->where('owner_id', $library->id) ->count(), ); } public function test_deleting_one_field_does_not_cascade_others(): void { $org = Organisation::factory()->create(); $schema = FormSchema::factory()->create(['organisation_id' => $org->id]); $a = FormField::factory()->create(['form_schema_id' => $schema->id]); $b = FormField::factory()->create(['form_schema_id' => $schema->id]); FormFieldValidationRule::factory()->forField($a)->create(); FormFieldValidationRule::factory()->forField($b)->create(); $a->delete(); $this->assertSame(1, FormFieldValidationRule::query() ->withoutGlobalScopes() ->where('owner_type', 'form_field') ->where('owner_id', $b->id) ->count(), ); } public function test_cascade_observer_also_cleans_up_bindings_on_same_owner(): void { // Regression guard after renaming the observer: the combined // observer must still clean up binding rows (WS-5a responsibility) // not only validation rules (WS-5b addition). $org = Organisation::factory()->create(); $schema = FormSchema::factory()->create(['organisation_id' => $org->id]); $field = FormField::factory()->create(['form_schema_id' => $schema->id]); FormFieldBinding::factory()->forField($field)->entityOwned('person', 'email')->create(); FormFieldValidationRule::factory()->forField($field)->create(); $field->delete(); $this->assertSame(0, FormFieldBinding::query() ->withoutGlobalScopes() ->where('owner_type', 'form_field') ->where('owner_id', $field->id) ->count(), ); $this->assertSame(0, FormFieldValidationRule::query() ->withoutGlobalScopes() ->where('owner_type', 'form_field') ->where('owner_id', $field->id) ->count(), ); } }