ag-cortex 0.1.0
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.
- package/.agent/commands/test-browser.md +339 -0
- package/.agent/rules/00-constitution.md +46 -0
- package/.agent/rules/project-rules.md +49 -0
- package/.agent/skills/agent-browser/SKILL.md +223 -0
- package/.agent/skills/agent-native-architecture/SKILL.md +435 -0
- package/.agent/skills/agent-native-architecture/references/action-parity-discipline.md +409 -0
- package/.agent/skills/agent-native-architecture/references/agent-execution-patterns.md +467 -0
- package/.agent/skills/agent-native-architecture/references/agent-native-testing.md +582 -0
- package/.agent/skills/agent-native-architecture/references/architecture-patterns.md +478 -0
- package/.agent/skills/agent-native-architecture/references/dynamic-context-injection.md +338 -0
- package/.agent/skills/agent-native-architecture/references/files-universal-interface.md +301 -0
- package/.agent/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +359 -0
- package/.agent/skills/agent-native-architecture/references/mcp-tool-design.md +506 -0
- package/.agent/skills/agent-native-architecture/references/mobile-patterns.md +871 -0
- package/.agent/skills/agent-native-architecture/references/product-implications.md +443 -0
- package/.agent/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +317 -0
- package/.agent/skills/agent-native-architecture/references/self-modification.md +269 -0
- package/.agent/skills/agent-native-architecture/references/shared-workspace-architecture.md +680 -0
- package/.agent/skills/agent-native-architecture/references/system-prompt-design.md +250 -0
- package/.agent/skills/agent-native-reviewer/SKILL.md +246 -0
- package/.agent/skills/andrew-kane-gem-writer/SKILL.md +184 -0
- package/.agent/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/.agent/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/.agent/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/.agent/skills/andrew-kane-gem-writer/references/resources.md +119 -0
- package/.agent/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/.agent/skills/ankane-readme-writer/SKILL.md +50 -0
- package/.agent/skills/architecture-strategist/SKILL.md +52 -0
- package/.agent/skills/best-practices-researcher/SKILL.md +100 -0
- package/.agent/skills/bug-reproduction-validator/SKILL.md +67 -0
- package/.agent/skills/code-simplicity-reviewer/SKILL.md +85 -0
- package/.agent/skills/coding-tutor/.claude-plugin/plugin.json +9 -0
- package/.agent/skills/coding-tutor/README.md +37 -0
- package/.agent/skills/coding-tutor/commands/quiz-me.md +1 -0
- package/.agent/skills/coding-tutor/commands/sync-tutorials.md +25 -0
- package/.agent/skills/coding-tutor/commands/teach-me.md +1 -0
- package/.agent/skills/coding-tutor/skills/coding-tutor/SKILL.md +214 -0
- package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/create_tutorial.py +202 -0
- package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/index_tutorials.py +203 -0
- package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/quiz_priority.py +190 -0
- package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/setup_tutorials.py +132 -0
- package/.agent/skills/compound-docs/SKILL.md +510 -0
- package/.agent/skills/compound-docs/assets/critical-pattern-template.md +34 -0
- package/.agent/skills/compound-docs/assets/resolution-template.md +93 -0
- package/.agent/skills/compound-docs/references/yaml-schema.md +65 -0
- package/.agent/skills/compound-docs/schema.yaml +176 -0
- package/.agent/skills/create-agent-skills/SKILL.md +299 -0
- package/.agent/skills/create-agent-skills/references/api-security.md +226 -0
- package/.agent/skills/create-agent-skills/references/be-clear-and-direct.md +531 -0
- package/.agent/skills/create-agent-skills/references/best-practices.md +404 -0
- package/.agent/skills/create-agent-skills/references/common-patterns.md +595 -0
- package/.agent/skills/create-agent-skills/references/core-principles.md +437 -0
- package/.agent/skills/create-agent-skills/references/executable-code.md +175 -0
- package/.agent/skills/create-agent-skills/references/iteration-and-testing.md +474 -0
- package/.agent/skills/create-agent-skills/references/official-spec.md +185 -0
- package/.agent/skills/create-agent-skills/references/recommended-structure.md +168 -0
- package/.agent/skills/create-agent-skills/references/skill-structure.md +372 -0
- package/.agent/skills/create-agent-skills/references/using-scripts.md +113 -0
- package/.agent/skills/create-agent-skills/references/using-templates.md +112 -0
- package/.agent/skills/create-agent-skills/references/workflows-and-validation.md +510 -0
- package/.agent/skills/create-agent-skills/templates/router-skill.md +73 -0
- package/.agent/skills/create-agent-skills/templates/simple-skill.md +33 -0
- package/.agent/skills/create-agent-skills/workflows/add-reference.md +96 -0
- package/.agent/skills/create-agent-skills/workflows/add-script.md +93 -0
- package/.agent/skills/create-agent-skills/workflows/add-template.md +74 -0
- package/.agent/skills/create-agent-skills/workflows/add-workflow.md +120 -0
- package/.agent/skills/create-agent-skills/workflows/audit-skill.md +138 -0
- package/.agent/skills/create-agent-skills/workflows/create-domain-expertise-skill.md +605 -0
- package/.agent/skills/create-agent-skills/workflows/create-new-skill.md +191 -0
- package/.agent/skills/create-agent-skills/workflows/get-guidance.md +121 -0
- package/.agent/skills/create-agent-skills/workflows/upgrade-to-router.md +161 -0
- package/.agent/skills/create-agent-skills/workflows/verify-skill.md +204 -0
- package/.agent/skills/data-integrity-guardian/SKILL.md +70 -0
- package/.agent/skills/data-migration-expert/SKILL.md +97 -0
- package/.agent/skills/deployment-verification-agent/SKILL.md +159 -0
- package/.agent/skills/design-implementation-reviewer/SKILL.md +85 -0
- package/.agent/skills/design-iterator/SKILL.md +197 -0
- package/.agent/skills/dhh-rails-reviewer/SKILL.md +45 -0
- package/.agent/skills/dhh-rails-style/SKILL.md +184 -0
- package/.agent/skills/dhh-rails-style/references/architecture.md +653 -0
- package/.agent/skills/dhh-rails-style/references/controllers.md +303 -0
- package/.agent/skills/dhh-rails-style/references/frontend.md +510 -0
- package/.agent/skills/dhh-rails-style/references/gems.md +266 -0
- package/.agent/skills/dhh-rails-style/references/models.md +359 -0
- package/.agent/skills/dhh-rails-style/references/testing.md +338 -0
- package/.agent/skills/dspy-ruby/SKILL.md +594 -0
- package/.agent/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/.agent/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/.agent/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/.agent/skills/dspy-ruby/references/core-concepts.md +265 -0
- package/.agent/skills/dspy-ruby/references/optimization.md +623 -0
- package/.agent/skills/dspy-ruby/references/providers.md +305 -0
- package/.agent/skills/every-style-editor/SKILL.md +134 -0
- package/.agent/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/.agent/skills/figma-design-sync/SKILL.md +166 -0
- package/.agent/skills/file-todos/SKILL.md +251 -0
- package/.agent/skills/file-todos/assets/todo-template.md +155 -0
- package/.agent/skills/framework-docs-researcher/SKILL.md +83 -0
- package/.agent/skills/frontend-design/SKILL.md +42 -0
- package/.agent/skills/gemini-imagegen/SKILL.md +237 -0
- package/.agent/skills/gemini-imagegen/requirements.txt +2 -0
- package/.agent/skills/gemini-imagegen/scripts/compose_images.py +168 -0
- package/.agent/skills/gemini-imagegen/scripts/edit_image.py +157 -0
- package/.agent/skills/gemini-imagegen/scripts/gemini_images.py +265 -0
- package/.agent/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/.agent/skills/gemini-imagegen/scripts/multi_turn_chat.py +215 -0
- package/.agent/skills/git-history-analyzer/SKILL.md +42 -0
- package/.agent/skills/git-worktree/SKILL.md +302 -0
- package/.agent/skills/git-worktree/scripts/worktree-manager.sh +345 -0
- package/.agent/skills/julik-frontend-races-reviewer/SKILL.md +222 -0
- package/.agent/skills/kieran-python-reviewer/SKILL.md +104 -0
- package/.agent/skills/kieran-rails-reviewer/SKILL.md +86 -0
- package/.agent/skills/kieran-typescript-reviewer/SKILL.md +95 -0
- package/.agent/skills/lint/SKILL.md +16 -0
- package/.agent/skills/pattern-recognition-specialist/SKILL.md +57 -0
- package/.agent/skills/performance-oracle/SKILL.md +110 -0
- package/.agent/skills/pr-comment-resolver/SKILL.md +69 -0
- package/.agent/skills/rclone/SKILL.md +150 -0
- package/.agent/skills/rclone/scripts/check_setup.sh +60 -0
- package/.agent/skills/repo-research-analyst/SKILL.md +113 -0
- package/.agent/skills/security-sentinel/SKILL.md +93 -0
- package/.agent/skills/skill-creator/SKILL.md +209 -0
- package/.agent/skills/skill-creator/scripts/init_skill.py +304 -0
- package/.agent/skills/skill-creator/scripts/package_skill.py +112 -0
- package/.agent/skills/skill-creator/scripts/quick_validate.py +72 -0
- package/.agent/skills/spec-flow-analyzer/SKILL.md +113 -0
- package/.agent/skills/test-agent/SKILL.md +4 -0
- package/.agent/workflows/agent-native-audit.md +277 -0
- package/.agent/workflows/ask-user-question.md +21 -0
- package/.agent/workflows/changelog.md +137 -0
- package/.agent/workflows/compound.md +202 -0
- package/.agent/workflows/create-agent-skill.md +8 -0
- package/.agent/workflows/deepen-plan-research.md +334 -0
- package/.agent/workflows/deepen-plan-synthesis.md +182 -0
- package/.agent/workflows/deepen-plan.md +79 -0
- package/.agent/workflows/feature-video.md +342 -0
- package/.agent/workflows/generate-command.md +162 -0
- package/.agent/workflows/heal-skill.md +142 -0
- package/.agent/workflows/lfg.md +20 -0
- package/.agent/workflows/plan-analysis.md +67 -0
- package/.agent/workflows/plan-next-steps.md +63 -0
- package/.agent/workflows/plan-review.md +33 -0
- package/.agent/workflows/plan-synthesis.md +106 -0
- package/.agent/workflows/plan.md +49 -0
- package/.agent/workflows/report-bug.md +150 -0
- package/.agent/workflows/reproduce-bug.md +99 -0
- package/.agent/workflows/resolve-parallel.md +34 -0
- package/.agent/workflows/resolve-pr-parallel.md +49 -0
- package/.agent/workflows/resolve-todo-parallel.md +35 -0
- package/.agent/workflows/review-analysis.md +145 -0
- package/.agent/workflows/review-synthesis.md +262 -0
- package/.agent/workflows/review.md +64 -0
- package/.agent/workflows/ship.md +90 -0
- package/.agent/workflows/test-command.md +3 -0
- package/.agent/workflows/triage.md +310 -0
- package/.agent/workflows/work.md +157 -0
- package/.agent/workflows/xcode-test.md +332 -0
- package/LICENSE +22 -0
- package/README.md +49 -0
- package/bin/ag-cortex.js +54 -0
- package/lib/core.js +165 -0
- package/package.json +31 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Testing - DHH Rails Style
|
|
2
|
+
|
|
3
|
+
## Core Philosophy
|
|
4
|
+
|
|
5
|
+
"Minitest with fixtures - simple, fast, deterministic." The approach prioritizes pragmatism over convention.
|
|
6
|
+
|
|
7
|
+
## Why Minitest Over RSpec
|
|
8
|
+
|
|
9
|
+
- **Simpler**: Less DSL magic, plain Ruby assertions
|
|
10
|
+
- **Ships with Rails**: No additional dependencies
|
|
11
|
+
- **Faster boot times**: Less overhead
|
|
12
|
+
- **Plain Ruby**: No specialized syntax to learn
|
|
13
|
+
|
|
14
|
+
## Fixtures as Test Data
|
|
15
|
+
|
|
16
|
+
Rather than factories, fixtures provide preloaded data:
|
|
17
|
+
- Loaded once, reused across tests
|
|
18
|
+
- No runtime object creation overhead
|
|
19
|
+
- Explicit relationship visibility
|
|
20
|
+
- Deterministic IDs for easier debugging
|
|
21
|
+
|
|
22
|
+
### Fixture Structure
|
|
23
|
+
```yaml
|
|
24
|
+
# test/fixtures/users.yml
|
|
25
|
+
david:
|
|
26
|
+
identity: david
|
|
27
|
+
account: basecamp
|
|
28
|
+
role: admin
|
|
29
|
+
|
|
30
|
+
jason:
|
|
31
|
+
identity: jason
|
|
32
|
+
account: basecamp
|
|
33
|
+
role: member
|
|
34
|
+
|
|
35
|
+
# test/fixtures/rooms.yml
|
|
36
|
+
watercooler:
|
|
37
|
+
name: Water Cooler
|
|
38
|
+
creator: david
|
|
39
|
+
direct: false
|
|
40
|
+
|
|
41
|
+
# test/fixtures/messages.yml
|
|
42
|
+
greeting:
|
|
43
|
+
body: Hello everyone!
|
|
44
|
+
room: watercooler
|
|
45
|
+
creator: david
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Using Fixtures in Tests
|
|
49
|
+
```ruby
|
|
50
|
+
test "sending a message" do
|
|
51
|
+
user = users(:david)
|
|
52
|
+
room = rooms(:watercooler)
|
|
53
|
+
|
|
54
|
+
# Test with fixture data
|
|
55
|
+
end
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Dynamic Fixture Values
|
|
59
|
+
ERB enables time-sensitive data:
|
|
60
|
+
```yaml
|
|
61
|
+
recent_card:
|
|
62
|
+
title: Recent Card
|
|
63
|
+
created_at: <%= 1.hour.ago %>
|
|
64
|
+
|
|
65
|
+
old_card:
|
|
66
|
+
title: Old Card
|
|
67
|
+
created_at: <%= 1.month.ago %>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Test Organization
|
|
71
|
+
|
|
72
|
+
### Unit Tests
|
|
73
|
+
Verify business logic using setup blocks and standard assertions:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
class CardTest < ActiveSupport::TestCase
|
|
77
|
+
setup do
|
|
78
|
+
@card = cards(:one)
|
|
79
|
+
@user = users(:david)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
test "closing a card creates a closure" do
|
|
83
|
+
assert_difference -> { Card::Closure.count } do
|
|
84
|
+
@card.close(creator: @user)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
assert @card.closed?
|
|
88
|
+
assert_equal @user, @card.closure.creator
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
test "reopening a card destroys the closure" do
|
|
92
|
+
@card.close(creator: @user)
|
|
93
|
+
|
|
94
|
+
assert_difference -> { Card::Closure.count }, -1 do
|
|
95
|
+
@card.reopen
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
refute @card.closed?
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Integration Tests
|
|
104
|
+
Test full request/response cycles:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
class CardsControllerTest < ActionDispatch::IntegrationTest
|
|
108
|
+
setup do
|
|
109
|
+
@user = users(:david)
|
|
110
|
+
sign_in @user
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
test "closing a card" do
|
|
114
|
+
card = cards(:one)
|
|
115
|
+
|
|
116
|
+
post card_closure_path(card)
|
|
117
|
+
|
|
118
|
+
assert_response :success
|
|
119
|
+
assert card.reload.closed?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
test "unauthorized user cannot close card" do
|
|
123
|
+
sign_in users(:guest)
|
|
124
|
+
card = cards(:one)
|
|
125
|
+
|
|
126
|
+
post card_closure_path(card)
|
|
127
|
+
|
|
128
|
+
assert_response :forbidden
|
|
129
|
+
refute card.reload.closed?
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### System Tests
|
|
135
|
+
Browser-based tests using Capybara:
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
class MessagesTest < ApplicationSystemTestCase
|
|
139
|
+
test "sending a message" do
|
|
140
|
+
sign_in users(:david)
|
|
141
|
+
visit room_path(rooms(:watercooler))
|
|
142
|
+
|
|
143
|
+
fill_in "Message", with: "Hello, world!"
|
|
144
|
+
click_button "Send"
|
|
145
|
+
|
|
146
|
+
assert_text "Hello, world!"
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
test "editing own message" do
|
|
150
|
+
sign_in users(:david)
|
|
151
|
+
visit room_path(rooms(:watercooler))
|
|
152
|
+
|
|
153
|
+
within "#message_#{messages(:greeting).id}" do
|
|
154
|
+
click_on "Edit"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
fill_in "Message", with: "Updated message"
|
|
158
|
+
click_button "Save"
|
|
159
|
+
|
|
160
|
+
assert_text "Updated message"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
test "drag and drop card to new column" do
|
|
164
|
+
sign_in users(:david)
|
|
165
|
+
visit board_path(boards(:main))
|
|
166
|
+
|
|
167
|
+
card = find("#card_#{cards(:one).id}")
|
|
168
|
+
target = find("#column_#{columns(:done).id}")
|
|
169
|
+
|
|
170
|
+
card.drag_to target
|
|
171
|
+
|
|
172
|
+
assert_selector "#column_#{columns(:done).id} #card_#{cards(:one).id}"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Advanced Patterns
|
|
178
|
+
|
|
179
|
+
### Time Testing
|
|
180
|
+
Use `travel_to` for deterministic time-dependent assertions:
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
test "card expires after 30 days" do
|
|
184
|
+
card = cards(:one)
|
|
185
|
+
|
|
186
|
+
travel_to 31.days.from_now do
|
|
187
|
+
assert card.expired?
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### External API Testing with VCR
|
|
193
|
+
Record and replay HTTP interactions:
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
test "fetches user data from API" do
|
|
197
|
+
VCR.use_cassette("user_api") do
|
|
198
|
+
user_data = ExternalApi.fetch_user(123)
|
|
199
|
+
|
|
200
|
+
assert_equal "John", user_data[:name]
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Background Job Testing
|
|
206
|
+
Assert job enqueueing and email delivery:
|
|
207
|
+
|
|
208
|
+
```ruby
|
|
209
|
+
test "closing card enqueues notification job" do
|
|
210
|
+
card = cards(:one)
|
|
211
|
+
|
|
212
|
+
assert_enqueued_with(job: NotifyWatchersJob, args: [card]) do
|
|
213
|
+
card.close
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
test "welcome email is sent on signup" do
|
|
218
|
+
assert_emails 1 do
|
|
219
|
+
Identity.create!(email: "new@example.com")
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Testing Turbo Streams
|
|
225
|
+
```ruby
|
|
226
|
+
test "message creation broadcasts to room" do
|
|
227
|
+
room = rooms(:watercooler)
|
|
228
|
+
|
|
229
|
+
assert_turbo_stream_broadcasts [room, :messages] do
|
|
230
|
+
room.messages.create!(body: "Test", creator: users(:david))
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Testing Principles
|
|
236
|
+
|
|
237
|
+
### 1. Test Observable Behavior
|
|
238
|
+
Focus on what the code does, not how it does it:
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
# ❌ Testing implementation
|
|
242
|
+
test "calls notify method on each watcher" do
|
|
243
|
+
card.expects(:notify).times(3)
|
|
244
|
+
card.close
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# ✅ Testing behavior
|
|
248
|
+
test "watchers receive notifications when card closes" do
|
|
249
|
+
assert_difference -> { Notification.count }, 3 do
|
|
250
|
+
card.close
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### 2. Don't Mock Everything
|
|
256
|
+
|
|
257
|
+
```ruby
|
|
258
|
+
# ❌ Over-mocked test
|
|
259
|
+
test "sending message" do
|
|
260
|
+
room = mock("room")
|
|
261
|
+
user = mock("user")
|
|
262
|
+
message = mock("message")
|
|
263
|
+
|
|
264
|
+
room.expects(:messages).returns(stub(create!: message))
|
|
265
|
+
message.expects(:broadcast_create)
|
|
266
|
+
|
|
267
|
+
MessagesController.new.create
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# ✅ Test the real thing
|
|
271
|
+
test "sending message" do
|
|
272
|
+
sign_in users(:david)
|
|
273
|
+
post room_messages_url(rooms(:watercooler)),
|
|
274
|
+
params: { message: { body: "Hello" } }
|
|
275
|
+
|
|
276
|
+
assert_response :success
|
|
277
|
+
assert Message.exists?(body: "Hello")
|
|
278
|
+
end
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### 3. Tests Ship with Features
|
|
282
|
+
Same commit, not TDD-first but together. Neither before (strict TDD) nor after (deferred testing).
|
|
283
|
+
|
|
284
|
+
### 4. Security Fixes Always Include Regression Tests
|
|
285
|
+
Every security fix must include a test that would have caught the vulnerability.
|
|
286
|
+
|
|
287
|
+
### 5. Integration Tests Validate Complete Workflows
|
|
288
|
+
Don't just test individual pieces - test that they work together.
|
|
289
|
+
|
|
290
|
+
## File Organization
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
test/
|
|
294
|
+
├── controllers/ # Integration tests for controllers
|
|
295
|
+
├── fixtures/ # YAML fixtures for all models
|
|
296
|
+
├── helpers/ # Helper method tests
|
|
297
|
+
├── integration/ # API integration tests
|
|
298
|
+
├── jobs/ # Background job tests
|
|
299
|
+
├── mailers/ # Mailer tests
|
|
300
|
+
├── models/ # Unit tests for models
|
|
301
|
+
├── system/ # Browser-based system tests
|
|
302
|
+
└── test_helper.rb # Test configuration
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Test Helper Setup
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
# test/test_helper.rb
|
|
309
|
+
ENV["RAILS_ENV"] ||= "test"
|
|
310
|
+
require_relative "../config/environment"
|
|
311
|
+
require "rails/test_help"
|
|
312
|
+
|
|
313
|
+
class ActiveSupport::TestCase
|
|
314
|
+
fixtures :all
|
|
315
|
+
|
|
316
|
+
parallelize(workers: :number_of_processors)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
class ActionDispatch::IntegrationTest
|
|
320
|
+
include SignInHelper
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
|
324
|
+
driven_by :selenium, using: :headless_chrome
|
|
325
|
+
end
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Sign In Helper
|
|
329
|
+
|
|
330
|
+
```ruby
|
|
331
|
+
# test/support/sign_in_helper.rb
|
|
332
|
+
module SignInHelper
|
|
333
|
+
def sign_in(user)
|
|
334
|
+
session = user.identity.sessions.create!
|
|
335
|
+
cookies.signed[:session_id] = session.id
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
```
|