diff options
| author | Salvo Polizzi <salvopolizzi03@gmail.com> | 2024-11-28 13:52:58 +0100 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2024-11-28 17:40:52 +0100 |
| commit | b82f80906a563741e34aecac537b53c19945a44f (patch) | |
| tree | 7c043cbeeb3daf548fcc056a8114b89717e1675c /tests | |
| parent | b92511b47475ce7fa1626d7d8c6180ae84bf0a19 (diff) | |
Fixed #35038 -- Created AlterConstraint operation.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/migrations/test_autodetector.py | 65 | ||||
| -rw-r--r-- | tests/migrations/test_operations.py | 75 | ||||
| -rw-r--r-- | tests/migrations/test_optimizer.py | 74 |
3 files changed, 214 insertions, 0 deletions
diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index d93114564a..de62170eb3 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -2969,6 +2969,71 @@ class AutodetectorTests(BaseAutodetectorTests): ["CreateModel", "AddField", "AddIndex"], ) + def test_alter_constraint(self): + book_constraint = models.CheckConstraint( + condition=models.Q(title__contains="title"), + name="title_contains_title", + ) + book_altered_constraint = models.CheckConstraint( + condition=models.Q(title__contains="title"), + name="title_contains_title", + violation_error_code="error_code", + ) + author_altered_constraint = models.CheckConstraint( + condition=models.Q(name__contains="Bob"), + name="name_contains_bob", + violation_error_message="Name doesn't contain Bob", + ) + + book_check_constraint = copy.deepcopy(self.book) + book_check_constraint_with_error_message = copy.deepcopy(self.book) + author_name_check_constraint_with_error_message = copy.deepcopy( + self.author_name_check_constraint + ) + + book_check_constraint.options = {"constraints": [book_constraint]} + book_check_constraint_with_error_message.options = { + "constraints": [book_altered_constraint] + } + author_name_check_constraint_with_error_message.options = { + "constraints": [author_altered_constraint] + } + + changes = self.get_changes( + [self.author_name_check_constraint, book_check_constraint], + [ + author_name_check_constraint_with_error_message, + book_check_constraint_with_error_message, + ], + ) + + self.assertNumberMigrations(changes, "testapp", 1) + self.assertOperationTypes(changes, "testapp", 0, ["AlterConstraint"]) + self.assertOperationAttributes( + changes, + "testapp", + 0, + 0, + model_name="author", + name="name_contains_bob", + constraint=author_altered_constraint, + ) + + self.assertNumberMigrations(changes, "otherapp", 1) + self.assertOperationTypes(changes, "otherapp", 0, ["AlterConstraint"]) + self.assertOperationAttributes( + changes, + "otherapp", + 0, + 0, + model_name="book", + name="title_contains_title", + constraint=book_altered_constraint, + ) + self.assertMigrationDependencies( + changes, "otherapp", 0, [("testapp", "auto_1")] + ) + def test_remove_constraints(self): """Test change detection of removed constraints.""" changes = self.get_changes( diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 3ac813b899..da0ec93dcd 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -4366,6 +4366,81 @@ class OperationTests(OperationTestBase): {"model_name": "Pony", "name": "test_remove_constraint_pony_pink_gt_2"}, ) + def test_alter_constraint(self): + constraint = models.UniqueConstraint( + fields=["pink"], name="test_alter_constraint_pony_fields_uq" + ) + project_state = self.set_up_test_model( + "test_alterconstraint", constraints=[constraint] + ) + + new_state = project_state.clone() + violation_error_message = "Pink isn't unique" + uq_constraint = models.UniqueConstraint( + fields=["pink"], + name="test_alter_constraint_pony_fields_uq", + violation_error_message=violation_error_message, + ) + uq_operation = migrations.AlterConstraint( + "Pony", "test_alter_constraint_pony_fields_uq", uq_constraint + ) + self.assertEqual( + uq_operation.describe(), + "Alter constraint test_alter_constraint_pony_fields_uq on Pony", + ) + self.assertEqual( + uq_operation.formatted_description(), + "~ Alter constraint test_alter_constraint_pony_fields_uq on Pony", + ) + self.assertEqual( + uq_operation.migration_name_fragment, + "alter_pony_test_alter_constraint_pony_fields_uq", + ) + + uq_operation.state_forwards("test_alterconstraint", new_state) + self.assertEqual( + project_state.models["test_alterconstraint", "pony"] + .options["constraints"][0] + .violation_error_message, + "Constraint ā%(name)sā is violated.", + ) + self.assertEqual( + new_state.models["test_alterconstraint", "pony"] + .options["constraints"][0] + .violation_error_message, + violation_error_message, + ) + + with connection.schema_editor() as editor, self.assertNumQueries(0): + uq_operation.database_forwards( + "test_alterconstraint", editor, project_state, new_state + ) + self.assertConstraintExists( + "test_alterconstraint_pony", + "test_alter_constraint_pony_fields_uq", + value=False, + ) + with connection.schema_editor() as editor, self.assertNumQueries(0): + uq_operation.database_backwards( + "test_alterconstraint", editor, project_state, new_state + ) + self.assertConstraintExists( + "test_alterconstraint_pony", + "test_alter_constraint_pony_fields_uq", + value=False, + ) + definition = uq_operation.deconstruct() + self.assertEqual(definition[0], "AlterConstraint") + self.assertEqual(definition[1], []) + self.assertEqual( + definition[2], + { + "model_name": "Pony", + "name": "test_alter_constraint_pony_fields_uq", + "constraint": uq_constraint, + }, + ) + def test_add_partial_unique_constraint(self): project_state = self.set_up_test_model("test_addpartialuniqueconstraint") partial_unique_constraint = models.UniqueConstraint( diff --git a/tests/migrations/test_optimizer.py b/tests/migrations/test_optimizer.py index 0a40b50edc..a871e67a45 100644 --- a/tests/migrations/test_optimizer.py +++ b/tests/migrations/test_optimizer.py @@ -1232,6 +1232,80 @@ class OptimizerTests(OptimizerTestBase): ], ) + def test_multiple_alter_constraints(self): + gt_constraint_violation_msg_added = models.CheckConstraint( + condition=models.Q(pink__gt=2), + name="pink_gt_2", + violation_error_message="ERROR", + ) + gt_constraint_violation_msg_altered = models.CheckConstraint( + condition=models.Q(pink__gt=2), + name="pink_gt_2", + violation_error_message="error", + ) + self.assertOptimizesTo( + [ + migrations.AlterConstraint( + "Pony", "pink_gt_2", gt_constraint_violation_msg_added + ), + migrations.AlterConstraint( + "Pony", "pink_gt_2", gt_constraint_violation_msg_altered + ), + ], + [ + migrations.AlterConstraint( + "Pony", "pink_gt_2", gt_constraint_violation_msg_altered + ) + ], + ) + other_constraint_violation_msg = models.CheckConstraint( + condition=models.Q(weight__gt=3), + name="pink_gt_3", + violation_error_message="error", + ) + self.assertDoesNotOptimize( + [ + migrations.AlterConstraint( + "Pony", "pink_gt_2", gt_constraint_violation_msg_added + ), + migrations.AlterConstraint( + "Pony", "pink_gt_3", other_constraint_violation_msg + ), + ] + ) + + def test_alter_remove_constraint(self): + self.assertOptimizesTo( + [ + migrations.AlterConstraint( + "Pony", + "pink_gt_2", + models.CheckConstraint( + condition=models.Q(pink__gt=2), name="pink_gt_2" + ), + ), + migrations.RemoveConstraint("Pony", "pink_gt_2"), + ], + [migrations.RemoveConstraint("Pony", "pink_gt_2")], + ) + + def test_add_alter_constraint(self): + constraint = models.CheckConstraint( + condition=models.Q(pink__gt=2), name="pink_gt_2" + ) + constraint_with_error = models.CheckConstraint( + condition=models.Q(pink__gt=2), + name="pink_gt_2", + violation_error_message="error", + ) + self.assertOptimizesTo( + [ + migrations.AddConstraint("Pony", constraint), + migrations.AlterConstraint("Pony", "pink_gt_2", constraint_with_error), + ], + [migrations.AddConstraint("Pony", constraint_with_error)], + ) + def test_create_model_add_index(self): self.assertOptimizesTo( [ |
