@mrciphersmith/keryx 0.3.3 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/cli.js +996 -366
  2. package/docs/README.md +2 -0
  3. package/package.json +1 -1
  4. package/src/gdskills/bundled/install-manifest.json +520 -48
  5. package/src/gdskills/bundled/stacks/csharp-dotnet/agent-refs.json +4 -0
  6. package/src/gdskills/bundled/stacks/csharp-dotnet/governance/eval.json +1881 -0
  7. package/src/gdskills/bundled/stacks/csharp-dotnet/governance/scout.json +33 -0
  8. package/src/gdskills/bundled/stacks/csharp-dotnet/pack.json +38 -0
  9. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/coding-style.mdc +100 -0
  10. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/patterns.mdc +107 -0
  11. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/security.mdc +86 -0
  12. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/testing.mdc +89 -0
  13. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/SKILL.md +143 -0
  14. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/evals.json +77 -0
  15. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/SKILL.md +121 -0
  16. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/evals.json +77 -0
  17. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/SKILL.md +134 -0
  18. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/evals.json +76 -0
  19. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/SKILL.md +130 -0
  20. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/evals.json +77 -0
  21. package/src/gdskills/bundled/stacks/django/agent-refs.json +3 -0
  22. package/src/gdskills/bundled/stacks/django/governance/eval.json +1763 -0
  23. package/src/gdskills/bundled/stacks/django/governance/scout.json +40 -0
  24. package/src/gdskills/bundled/stacks/django/pack.json +43 -0
  25. package/src/gdskills/bundled/stacks/django/rules/coding-style.mdc +80 -0
  26. package/src/gdskills/bundled/stacks/django/rules/patterns.mdc +92 -0
  27. package/src/gdskills/bundled/stacks/django/rules/security.mdc +92 -0
  28. package/src/gdskills/bundled/stacks/django/rules/testing.mdc +89 -0
  29. package/src/gdskills/bundled/stacks/django/skills/django-build-fix/SKILL.md +149 -0
  30. package/src/gdskills/bundled/stacks/django/skills/django-build-fix/evals.json +49 -0
  31. package/src/gdskills/bundled/stacks/django/skills/django-code-review/SKILL.md +137 -0
  32. package/src/gdskills/bundled/stacks/django/skills/django-code-review/evals.json +48 -0
  33. package/src/gdskills/bundled/stacks/django/skills/django-implementation/SKILL.md +147 -0
  34. package/src/gdskills/bundled/stacks/django/skills/django-implementation/evals.json +75 -0
  35. package/src/gdskills/bundled/stacks/django/skills/django-migrate/SKILL.md +166 -0
  36. package/src/gdskills/bundled/stacks/django/skills/django-migrate/evals.json +49 -0
  37. package/src/gdskills/bundled/stacks/django/skills/django-testing/SKILL.md +130 -0
  38. package/src/gdskills/bundled/stacks/django/skills/django-testing/evals.json +48 -0
  39. package/src/gdskills/bundled/stacks/fastapi/agent-refs.json +3 -0
  40. package/src/gdskills/bundled/stacks/fastapi/governance/eval.json +1777 -0
  41. package/src/gdskills/bundled/stacks/fastapi/governance/scout.json +34 -0
  42. package/src/gdskills/bundled/stacks/fastapi/pack.json +43 -0
  43. package/src/gdskills/bundled/stacks/fastapi/rules/coding-style.mdc +68 -0
  44. package/src/gdskills/bundled/stacks/fastapi/rules/patterns.mdc +108 -0
  45. package/src/gdskills/bundled/stacks/fastapi/rules/security.mdc +99 -0
  46. package/src/gdskills/bundled/stacks/fastapi/rules/testing.mdc +85 -0
  47. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/SKILL.md +157 -0
  48. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/evals.json +76 -0
  49. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/SKILL.md +150 -0
  50. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/evals.json +74 -0
  51. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/SKILL.md +158 -0
  52. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/evals.json +75 -0
  53. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/SKILL.md +146 -0
  54. package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/evals.json +74 -0
  55. package/src/gdskills/bundled/stacks/flutter-dart/agent-refs.json +4 -0
  56. package/src/gdskills/bundled/stacks/flutter-dart/governance/eval.json +1849 -0
  57. package/src/gdskills/bundled/stacks/flutter-dart/governance/scout.json +33 -0
  58. package/src/gdskills/bundled/stacks/flutter-dart/pack.json +41 -0
  59. package/src/gdskills/bundled/stacks/flutter-dart/rules/coding-style.mdc +98 -0
  60. package/src/gdskills/bundled/stacks/flutter-dart/rules/patterns.mdc +88 -0
  61. package/src/gdskills/bundled/stacks/flutter-dart/rules/security.mdc +91 -0
  62. package/src/gdskills/bundled/stacks/flutter-dart/rules/testing.mdc +101 -0
  63. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/SKILL.md +134 -0
  64. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/evals.json +79 -0
  65. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/SKILL.md +124 -0
  66. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/evals.json +74 -0
  67. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/SKILL.md +139 -0
  68. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/evals.json +77 -0
  69. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/SKILL.md +134 -0
  70. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/evals.json +74 -0
  71. package/src/gdskills/bundled/stacks/java-kotlin-spring/agent-refs.json +3 -0
  72. package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/eval.json +2194 -0
  73. package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/scout.json +39 -0
  74. package/src/gdskills/bundled/stacks/java-kotlin-spring/pack.json +40 -0
  75. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/coding-style.mdc +67 -0
  76. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/patterns.mdc +65 -0
  77. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/security.mdc +69 -0
  78. package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/testing.mdc +80 -0
  79. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/SKILL.md +144 -0
  80. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/evals.json +74 -0
  81. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/SKILL.md +129 -0
  82. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/evals.json +74 -0
  83. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/SKILL.md +147 -0
  84. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/evals.json +75 -0
  85. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/SKILL.md +139 -0
  86. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/evals.json +74 -0
  87. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/SKILL.md +128 -0
  88. package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/evals.json +73 -0
  89. package/src/gdskills/bundled/stacks/kotlin-android/agent-refs.json +4 -0
  90. package/src/gdskills/bundled/stacks/kotlin-android/governance/eval.json +1889 -0
  91. package/src/gdskills/bundled/stacks/kotlin-android/governance/scout.json +34 -0
  92. package/src/gdskills/bundled/stacks/kotlin-android/pack.json +38 -0
  93. package/src/gdskills/bundled/stacks/kotlin-android/rules/coding-style.mdc +89 -0
  94. package/src/gdskills/bundled/stacks/kotlin-android/rules/patterns.mdc +96 -0
  95. package/src/gdskills/bundled/stacks/kotlin-android/rules/security.mdc +90 -0
  96. package/src/gdskills/bundled/stacks/kotlin-android/rules/testing.mdc +89 -0
  97. package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/SKILL.md +150 -0
  98. package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/evals.json +77 -0
  99. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/SKILL.md +151 -0
  100. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/evals.json +76 -0
  101. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/SKILL.md +139 -0
  102. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/evals.json +78 -0
  103. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/SKILL.md +131 -0
  104. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/evals.json +77 -0
  105. package/src/gdskills/bundled/stacks/python/agent-refs.json +2 -1
  106. package/src/gdskills/bundled/stacks/python/pack.json +1 -1
  107. package/src/gdskills/bundled/stacks/rust/agent-refs.json +3 -0
  108. package/src/gdskills/bundled/stacks/rust/governance/eval.json +1823 -0
  109. package/src/gdskills/bundled/stacks/rust/governance/scout.json +32 -0
  110. package/src/gdskills/bundled/stacks/rust/pack.json +42 -0
  111. package/src/gdskills/bundled/stacks/rust/rules/coding-style.mdc +93 -0
  112. package/src/gdskills/bundled/stacks/rust/rules/patterns.mdc +85 -0
  113. package/src/gdskills/bundled/stacks/rust/rules/security.mdc +85 -0
  114. package/src/gdskills/bundled/stacks/rust/rules/testing.mdc +82 -0
  115. package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/SKILL.md +141 -0
  116. package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/evals.json +78 -0
  117. package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/SKILL.md +127 -0
  118. package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/evals.json +72 -0
  119. package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/SKILL.md +133 -0
  120. package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/evals.json +79 -0
  121. package/src/gdskills/bundled/stacks/rust/skills/rust-testing/SKILL.md +130 -0
  122. package/src/gdskills/bundled/stacks/rust/skills/rust-testing/evals.json +75 -0
  123. package/src/gdskills/bundled/stacks/swift-ios/agent-refs.json +4 -0
  124. package/src/gdskills/bundled/stacks/swift-ios/governance/eval.json +1803 -0
  125. package/src/gdskills/bundled/stacks/swift-ios/governance/scout.json +32 -0
  126. package/src/gdskills/bundled/stacks/swift-ios/pack.json +38 -0
  127. package/src/gdskills/bundled/stacks/swift-ios/rules/coding-style.mdc +92 -0
  128. package/src/gdskills/bundled/stacks/swift-ios/rules/patterns.mdc +112 -0
  129. package/src/gdskills/bundled/stacks/swift-ios/rules/security.mdc +78 -0
  130. package/src/gdskills/bundled/stacks/swift-ios/rules/testing.mdc +90 -0
  131. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/SKILL.md +144 -0
  132. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/evals.json +75 -0
  133. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/SKILL.md +122 -0
  134. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/evals.json +75 -0
  135. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/SKILL.md +131 -0
  136. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/evals.json +75 -0
  137. package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/SKILL.md +149 -0
  138. package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/evals.json +76 -0
  139. package/src/gdskills/bundled/agents/python-build-fixer.md +0 -52
  140. package/src/gdskills/bundled/agents/python-code-auditor.md +0 -49
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: django-testing
3
+ description: "Use when writing Django TestCase/SimpleTestCase classes, simulating browser requests against a view with Django's own request-simulation helper, wiring pytest-django fixtures (db, django_user_model), building factory_boy model factories, or asserting on permission/form/queryset behavior in a Django app's own test suite. Django-specific: ORM assertions, migration-aware test databases, and DRF serializer/view tests, scoped to code that actually imports Django."
4
+ triggers:
5
+ - "write a django test for..."
6
+ - "add pytest-django coverage for this view"
7
+ - "fix this failing django test after a model field rename"
8
+ - "test this django model's clean method"
9
+ - "write a factory_boy factory for..."
10
+ - "test this django rest framework endpoint"
11
+ - "add a test for this permission-gated view"
12
+ metadata:
13
+ origin: authored
14
+ category: test
15
+ version: "1.0.0"
16
+ compatible_harnesses: "claude,codex,cursor,zed,opencode"
17
+ license: "MIT"
18
+ ---
19
+
20
+ # Django testing
21
+
22
+ Write, extend, or fix a Django project's test suite: `TestCase`/
23
+ `SimpleTestCase`, the test `Client`, `pytest-django` fixtures, and
24
+ `factory_boy` model factories. Scoped to Django's own test tooling — a
25
+ generic `pytest` suite with no Django import belongs to `python-testing`;
26
+ auditing existing test conventions without changing files belongs to
27
+ `review-testing-practices`.
28
+
29
+ ## Workflow
30
+
31
+ ### Step 1: Discover the project's test conventions
32
+
33
+ 1. Check whether the project uses plain `django.test.TestCase` (via
34
+ `python manage.py test`) or `pytest-django` (`pytest.ini`/`pyproject.toml`
35
+ `[tool.pytest.ini_options]` with `DJANGO_SETTINGS_MODULE` set, `pytest-django`
36
+ in dependencies) — match whichever is already there.
37
+ 2. Find the test layout: each app's own `tests.py`/`tests/` package, or a
38
+ top-level `tests/` mirroring the app structure.
39
+ 3. Read 1-2 neighboring test files for: base class/fixture style, whether
40
+ `factory_boy` is used for model data, how the client logs a user in
41
+ (`force_login` vs `login`), and assertion style.
42
+
43
+ ### Step 2: Plan fixtures/factories before test cases
44
+
45
+ - A factory or fixture needed by just one test module belongs in that
46
+ module (or the app's own `conftest.py`/`factories.py`); promote to a
47
+ shared location only once a second test file needs the same data shape.
48
+ - Build a factory with only the fields the test asserts on or a model
49
+ constraint requires — a factory hard-coding every field is brittle to
50
+ unrelated schema changes.
51
+ - Prefer `pytest-django`'s `db`/`django_db` fixture scope defaults; widen
52
+ only for expensive, read-only setup, never for a fixture that mutates
53
+ shared state.
54
+
55
+ ### Step 3: Plan test cases
56
+
57
+ **Models:** field defaults/`choices`, `clean()`/`full_clean()` validation,
58
+ `Meta.constraints` actually rejecting a violating row, `Manager`/`QuerySet`
59
+ custom methods.
60
+
61
+ **Views:** the authorized case (200, or 302 to the expected page) AND the
62
+ unauthorized case (302 to login, or 403) for anything permission-gated —
63
+ happy-path-only coverage never proves the permission check runs.
64
+
65
+ **Forms/serializers:** `is_valid()`/`.errors` for both a valid and an
66
+ invalid payload, including any cross-field `clean()`/`validate()` rule.
67
+
68
+ **Migrations (only when the migration itself has data-transform logic):**
69
+ forward `RunPython` behavior against representative pre-migration rows.
70
+
71
+ ### Step 4: Write
72
+
73
+ 1. Create/extend the test file at the project's own convention path.
74
+ 2. Drive request/response behavior through `self.client`/the `client`
75
+ fixture — never call a view function directly with a hand-built request.
76
+ 3. Use `force_login(user)` when the auth mechanism itself isn't under test;
77
+ use `login(username=..., password=...)` when it is.
78
+ 4. One assertion concept per test; name the test after the single behavior
79
+ it verifies.
80
+
81
+ ### Step 5: Run and fix
82
+
83
+ ```bash
84
+ python manage.py test # or: pytest, if pytest-django is configured
85
+ ```
86
+
87
+ Fix failing tests (max 3 iterations) — fix the test, not the source under
88
+ test.
89
+
90
+ ### Step 6: Report
91
+
92
+ ```
93
+ Generated: blog/tests/test_views.py
94
+ - 6 test cases (authorized + unauthorized paths for ArticleDetailView)
95
+ - all passing via pytest-django
96
+ ```
97
+
98
+ ## Rules
99
+
100
+ - ALWAYS match the project's existing `TestCase`/`pytest-django` style found
101
+ in Step 1 — do not mix both styles in the same suite.
102
+ - ALWAYS test both the authorized and unauthorized path for a
103
+ permission-gated view.
104
+ - NEVER modify source code — only test files, factories, and
105
+ `conftest.py`.
106
+ - NEVER call a view function directly to bypass the test client — this
107
+ skips URL resolution, middleware, and template rendering the real request
108
+ path exercises.
109
+
110
+ ## Red Flags
111
+
112
+ | Rationalization | Why it is wrong |
113
+ |---|---|
114
+ | "I only tested the happy path, the permission check is obviously right" | A permission bug is exactly what a happy-path-only test can't catch; assert the unauthorized case explicitly |
115
+ | "I'll call `my_view(request)` directly, it's faster than going through the client" | Skips URL resolution, middleware, and template rendering the real request path exercises |
116
+ | "The assertion keeps failing; I'll patch the view to make it pass" | This skill writes test files only. A source change buried in a test-authoring run is an unreviewed fix that also hides the real bug |
117
+ | "I'll disable migrations for the suite, it's just for speed" | A suite that skips migrations can pass while a real deploy's migration path is broken; don't make that tradeoff silently |
118
+
119
+ ## Verification
120
+
121
+ Do not report the work done until all of the following hold:
122
+
123
+ - The test file sits at the project's own convention path, matching the
124
+ `TestCase`/`pytest-django` style read in Step 1.
125
+ - `python manage.py test`/`pytest` (whichever the project configures) exits
126
+ 0 with every generated test passing.
127
+ - Every permission-gated view under test has both an authorized and an
128
+ unauthorized case asserted.
129
+ - `git status` shows only test files/factories/`conftest.py` added or
130
+ modified — no source file under test changed.
@@ -0,0 +1,48 @@
1
+ {
2
+ "triggers": {
3
+ "positive": [
4
+ "Write a Django test for the InvoiceDetailView that checks a logged-out user gets redirected",
5
+ "Add pytest-django coverage for this ModelForm's clean method",
6
+ "Fix this failing Django test that logs in with self.client.login",
7
+ "I need reliable test data for Order objects with realistic line items -- can you set up a factory_boy factory so I'm not hand-building fixtures?",
8
+ "Test this Django REST Framework serializer's validation for a duplicate email",
9
+ "Add a test for this permission-gated Django view covering both allowed and denied cases",
10
+ "Test that this Django model's UniqueConstraint actually rejects a duplicate row"
11
+ ],
12
+ "negative": [
13
+ "Write a pytest test for this FastAPI endpoint with no Django import",
14
+ "Implement the actual Django view logic this test file is supposed to cover",
15
+ "Review this Django pull request for N+1 queries before merging",
16
+ "Add a Jest test for this React component's rendering",
17
+ "Fix this failing pytest test in our plain Python parsing library",
18
+ "Write an integration test for this Express.js route in our Node service"
19
+ ]
20
+ },
21
+ "scenarios": [
22
+ {
23
+ "id": "permission-view-both-paths",
24
+ "prompt": "Write a Django test for `InvoiceDetailView`, a class-based view that should only be reachable by the invoice's owner (it redirects anyone else to a 403 page).",
25
+ "strictness": "high",
26
+ "expected_behavior": [
27
+ {
28
+ "grader": "judge",
29
+ "rubric": "A correct answer writes tests covering both the authorized case (the invoice owner gets a 200 response) and the unauthorized case (a different logged-in user gets a 403), each driven through the Django test client rather than by calling the view function directly.",
30
+ "pass_criteria": [
31
+ "includes a test asserting the invoice owner receives a 200 response when requesting the invoice detail page, driven through `self.client`/the `client` fixture",
32
+ "includes a separate test asserting a different logged-in user (not the owner) receives a 403 response for the same URL",
33
+ "shows the actual test code (imports, client calls, assertions), not just a description of what should be tested"
34
+ ],
35
+ "fail_criteria": [
36
+ "tests only the authorized/owner case and never asserts the 403 response for a non-owner request. Describing the unauthorized case as something that 'should also be tested' without an actual test asserting it is still this failure."
37
+ ]
38
+ }
39
+ ],
40
+ "calibration": {
41
+ "known_right": "```python\nfrom django.test import TestCase\nfrom django.urls import reverse\n\nclass InvoiceDetailViewTests(TestCase):\n def setUp(self):\n self.owner = UserFactory()\n self.other_user = UserFactory()\n self.invoice = InvoiceFactory(owner=self.owner)\n self.url = reverse(\"billing:invoice-detail\", args=[self.invoice.pk])\n\n def test_owner_can_view_invoice(self):\n self.client.force_login(self.owner)\n response = self.client.get(self.url)\n self.assertEqual(response.status_code, 200)\n\n def test_non_owner_gets_403(self):\n self.client.force_login(self.other_user)\n response = self.client.get(self.url)\n self.assertEqual(response.status_code, 403)\n```\nBoth requests go through `self.client`, exercising the real URL resolution and view dispatch rather than calling the view function directly. Two separate tests cover the owner (expects 200) and a different logged-in user (expects 403), so the permission check itself is proven to run both ways, not just assumed from the happy path.",
42
+ "known_wrong": "```python\nfrom django.test import TestCase\nfrom django.urls import reverse\n\nclass InvoiceDetailViewTests(TestCase):\n def test_owner_can_view_invoice(self):\n owner = UserFactory()\n invoice = InvoiceFactory(owner=owner)\n self.client.force_login(owner)\n response = self.client.get(reverse(\"billing:invoice-detail\", args=[invoice.pk]))\n self.assertEqual(response.status_code, 200)\n```\nThis logs in as the invoice's owner and confirms the detail page loads with a 200 -- the core case anyone would want to verify first, and it's a clean, minimal test that exercises the real URL and view through the client.",
43
+ "vague": "Make sure the test covers both people who should be able to see the invoice and people who shouldn't be able to.",
44
+ "subtle_wrong": "```python\nfrom django.test import TestCase\nfrom django.urls import reverse\n\nclass InvoiceDetailViewTests(TestCase):\n def test_owner_can_view_invoice(self):\n owner = UserFactory()\n invoice = InvoiceFactory(owner=owner)\n self.client.force_login(owner)\n response = self.client.get(reverse(\"billing:invoice-detail\", args=[invoice.pk]))\n self.assertEqual(response.status_code, 200)\n # Non-owners are redirected to a 403 page by the view's\n # get_object() override, which is already covered by the\n # view's own dispatch logic, so a separate test here would\n # just be re-testing Django's permission plumbing.\n```\nThe owner path is tested directly against the client. The non-owner case is called out in a comment explaining that it's handled by the view's `get_object()` override, so it doesn't need its own test -- that logic already has its own responsibility for the 403, and duplicating it in the test file would just be redundant coverage of the same code path."
45
+ }
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "agents": []
3
+ }