From 12f1a5bb810b2d20b13e4a222f44c17201aee0e0 Mon Sep 17 00:00:00 2001 From: Bernhard Suttner Date: Tue, 21 Apr 2026 21:48:20 +0200 Subject: [PATCH] test(service/assignments): cover bulk failure handling Before this commit, bulk assignment failure cases were not covered by service tests. This commit adds coverage for missing sources, missing targets, single-clear behavior, and transaction rollback on later failures. Co-authored-by: codex --- test/services/unit/assignment_service_test.rb | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/test/services/unit/assignment_service_test.rb b/test/services/unit/assignment_service_test.rb index dd88d681..f7599d74 100644 --- a/test/services/unit/assignment_service_test.rb +++ b/test/services/unit/assignment_service_test.rb @@ -114,6 +114,86 @@ class AssignmentServiceTest < ForemanAnsibleDirectorTestCase ) assert_equal 2, target_assignments.count end + + test 'does nothing for empty assignments' do + FactoryBot.create( + :ansible_content_assignment, + consumable: @collection_role, + assignable: @host + ) + + ::ForemanAnsibleDirector::AssignmentService.create_bulk_assignments(assignments: []) + + assert_equal 1, ::ForemanAnsibleDirector::AnsibleContentAssignment.where(assignable: @host).count + end + + test 'raises and keeps existing assignments when source is missing' do + existing_assignment = FactoryBot.create( + :ansible_content_assignment, + consumable: @collection_role, + assignable: @host + ) + + assert_raises(ActiveRecord::StatementInvalid) do + ::ForemanAnsibleDirector::AssignmentService.create_bulk_assignments( + assignments: [ + { source: { type: 'ACR', id: -1 }, target: { type: 'HOST', id: @host.id } } + ] + ) + end + + assert_equal [existing_assignment], ::ForemanAnsibleDirector::AnsibleContentAssignment.where( + assignable: @host + ).to_a + end + + test 'raises and keeps existing assignments when target is missing' do + existing_assignment = FactoryBot.create( + :ansible_content_assignment, + consumable: @collection_role, + assignable: @host + ) + + assert_raises(NoMethodError) do + ::ForemanAnsibleDirector::AssignmentService.create_bulk_assignments( + assignments: [ + { source: { type: 'ACR', id: @collection_role.id }, target: { type: 'HOST', id: -1 } } + ] + ) + end + + assert_equal [existing_assignment], ::ForemanAnsibleDirector::AnsibleContentAssignment.where( + assignable: @host + ).to_a + end + + test 'rolls back all target changes when a later assignment fails' do + existing_assignment = FactoryBot.create( + :ansible_content_assignment, + consumable: @collection_role, + assignable: @host + ) + + collection2 = FactoryBot.create(:ansible_collection, organization: @organization) + collection_version2 = FactoryBot.create(:content_unit_version, :for_collection, versionable: collection2) + collection_role2 = FactoryBot.create( + :ansible_collection_role, + ansible_collection_version: collection_version2 + ) + + assert_raises(ActiveRecord::StatementInvalid) do + ::ForemanAnsibleDirector::AssignmentService.create_bulk_assignments( + assignments: [ + { source: { type: 'ACR', id: collection_role2.id }, target: { type: 'HOST', id: @host.id } }, + { source: { type: 'ACR', id: -1 }, target: { type: 'HOST', id: @host.id } } + ] + ) + end + + assert_equal [existing_assignment], ::ForemanAnsibleDirector::AnsibleContentAssignment.where( + assignable: @host + ).to_a + end end describe '#finder' do