|
5 | 5 | from django.test import Client, TransactionTestCase, override_settings |
6 | 6 |
|
7 | 7 | from astron_console.accounts.models import User, UserProfile |
| 8 | +from astron_console.agents.models import Agent, AgentVersion |
8 | 9 | from astron_console.resources.common import UpstreamError |
9 | 10 | from astron_console.resources.models import ( |
10 | 11 | ConfigInfo, |
|
16 | 17 | WorkflowScope, |
17 | 18 | ) |
18 | 19 | from astron_console.spaces.models import Space, SpaceMember, SpacePermission |
| 20 | +from astron_console.workflows.models import Workflow, WorkflowVersion |
19 | 21 |
|
20 | 22 | SCHEMA = { |
21 | 23 | "openapi": "3.0.3", |
@@ -246,6 +248,45 @@ def test_model_delete_requires_write_verb(self): |
246 | 248 | self.model.refresh_from_db() |
247 | 249 | self.assertTrue(self.model.is_deleted) |
248 | 250 |
|
| 251 | + def test_model_delete_preserves_agent_draft_reference(self): |
| 252 | + Agent.objects.create(uid=self.user.pk, model_id=self.model.pk) |
| 253 | + result = self.client.delete(f"/api/model/delete?modelId={self.model.pk}") |
| 254 | + self.assertEqual(result.status_code, 400, result.content) |
| 255 | + self.model.refresh_from_db() |
| 256 | + self.assertFalse(self.model.is_deleted) |
| 257 | + |
| 258 | + def test_model_delete_preserves_agent_version_after_draft_changes(self): |
| 259 | + agent = Agent.objects.create(uid=self.user.pk, model_id=None) |
| 260 | + AgentVersion.objects.create( |
| 261 | + agent_id=agent.pk, |
| 262 | + definition={"modelId": self.model.pk}, |
| 263 | + created_by=self.user.pk, |
| 264 | + ) |
| 265 | + result = self.client.delete(f"/api/model/delete?modelId={self.model.pk}") |
| 266 | + self.assertEqual(result.status_code, 400, result.content) |
| 267 | + self.model.refresh_from_db() |
| 268 | + self.assertFalse(self.model.is_deleted) |
| 269 | + Agent.objects.filter(pk=agent.pk).update(is_delete=1) |
| 270 | + result = self.client.delete(f"/api/model/delete?modelId={self.model.pk}") |
| 271 | + self.assertEqual(result.status_code, 200, result.content) |
| 272 | + |
| 273 | + def test_model_delete_preserves_workflow_version_after_draft_changes(self): |
| 274 | + workflow = Workflow.objects.create( |
| 275 | + uid=self.user.pk, app_id="app", flow_id="version-only-model", name="Saved", data="{}" |
| 276 | + ) |
| 277 | + version = WorkflowVersion.objects.create( |
| 278 | + flow_id=workflow.flow_id, |
| 279 | + version_num="v1", |
| 280 | + data=json.dumps({"nodes": [{"data": {"nodeParam": {"modelId": self.model.pk}}}]}), |
| 281 | + ) |
| 282 | + result = self.client.delete(f"/api/model/delete?modelId={self.model.pk}") |
| 283 | + self.assertEqual(result.status_code, 400, result.content) |
| 284 | + self.model.refresh_from_db() |
| 285 | + self.assertFalse(self.model.is_deleted) |
| 286 | + WorkflowVersion.objects.filter(pk=version.pk).update(deleted=2) |
| 287 | + result = self.client.delete(f"/api/model/delete?modelId={self.model.pk}") |
| 288 | + self.assertEqual(result.status_code, 200, result.content) |
| 289 | + |
249 | 290 | def test_internal_brokers_require_credentials(self): |
250 | 291 | for url in [ |
251 | 292 | "/model/internal-runtime-config?flowId=flow&modelId=1", |
@@ -365,6 +406,45 @@ def test_tool_upstream_failure_does_not_create_local_success(self): |
365 | 406 | self.assertEqual(result.status_code, 502) |
366 | 407 | self.assertFalse(Tool.objects.exists()) |
367 | 408 |
|
| 409 | + def test_tool_delete_preserves_new_agent_references_before_remote_delete(self): |
| 410 | + for source in ("draft", "version", "workflow-version"): |
| 411 | + with self.subTest(source=source): |
| 412 | + tool = Tool.objects.create( |
| 413 | + user_id=self.user.pk, tool_id=f"remote-{source}", version="V1", deleted=0 |
| 414 | + ) |
| 415 | + # Deleting another card of the same tool also deletes this version upstream. |
| 416 | + selected = Tool.objects.create( |
| 417 | + user_id=self.user.pk, tool_id=tool.tool_id, version="V2", deleted=0 |
| 418 | + ) |
| 419 | + agent = Agent.objects.create( |
| 420 | + uid=self.user.pk, tools=json.dumps([tool.pk] if source == "draft" else []) |
| 421 | + ) |
| 422 | + if source == "version": |
| 423 | + AgentVersion.objects.create( |
| 424 | + agent_id=agent.pk, |
| 425 | + definition={"tools": [{"toolId": tool.tool_id, "version": "V1"}]}, |
| 426 | + created_by=self.user.pk, |
| 427 | + ) |
| 428 | + elif source == "workflow-version": |
| 429 | + workflow = Workflow.objects.create( |
| 430 | + uid=self.user.pk, app_id="app", flow_id="tool-flow", name="Saved", data="{}" |
| 431 | + ) |
| 432 | + WorkflowVersion.objects.create( |
| 433 | + flow_id=workflow.flow_id, |
| 434 | + version_num="v1", |
| 435 | + data=json.dumps( |
| 436 | + {"nodes": [{"data": {"nodeParam": {"pluginId": tool.tool_id}}}]} |
| 437 | + ), |
| 438 | + ) |
| 439 | + with patch("astron_console.resources.clients.call") as remote: |
| 440 | + result = self.client.delete(f"/resources/tools/{selected.pk}") |
| 441 | + self.assertEqual(result.status_code, 400, result.content) |
| 442 | + remote.assert_not_called() |
| 443 | + tool.refresh_from_db() |
| 444 | + selected.refresh_from_db() |
| 445 | + self.assertFalse(tool.deleted) |
| 446 | + self.assertFalse(selected.deleted) |
| 447 | + |
368 | 448 | def test_tool_registration_and_secret_mask(self): |
369 | 449 | with patch( |
370 | 450 | "astron_console.resources.clients.call", |
|
0 commit comments