You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .claude/skills/add-test-fixture/SKILL.md
+25-48Lines changed: 25 additions & 48 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,77 +6,54 @@ description: Creates a new test event fixture directory under tests/events/{even
6
6
7
7
## Critical
8
8
9
-
- Every fixture directory requires **three files** — `GithubMessageBuilderTest.php`reads all three; missing any will cause a fatal test error:
9
+
- Every fixture directory requires **exactly three files** — `GithubMessageBuilderTest.php`skips any directory missing `expected_text.txt`. The required files are:
10
10
```
11
11
tests/events/deployment/type.txt
12
12
tests/events/deployment/payload.json
13
13
tests/events/deployment/expected_text.txt
14
14
```
15
-
-`expected_text.txt` contains plain-text chat message output — **generate it by running the test harness**, not by hand.
16
-
- The value in `tests/events/deployment/type.txt` must match the `X-GitHub-Event` header value exactly (e.g. `push`, `pull_request`, `ping`) — no trailing newline issues; the test trims it.
15
+
-`expected_text.txt` contains **plain text** (no IRC color codes). Write the expected `$Msg['text']` output from `GithubMessageBuilder::build()` directly.
16
+
- Do NOT create `expected.bin` or `discord.json` — those are for the removed `IrcConverter`/`DiscordConverter` and will be silently ignored.
17
+
- The value in `type.txt` must match the `X-GitHub-Event` header value exactly (e.g. `push`, `pull_request`) — `GithubMessageBuilderTest.php` trims it.
17
18
18
19
## Instructions
19
20
20
21
1.**Create the fixture directory.**
21
-
Use the GitHub event name as the directory name (e.g. `deployment`, `workflow_dispatch`). For action variants, append `_{action}` (e.g. `pull_request_merged`, `issue_closed`). Verify no existing directory with that name exists under `tests/events/`.
22
+
```bash
23
+
mkdir tests/events/deployment
24
+
```
25
+
Use the GitHub event name as the directory name. For action variants, append `_{action}` (e.g. `pull_request_merged`, `issues_closed`).
22
26
23
27
2.**Write the event type file.**
24
-
Content is the bare event type only — no action suffix, no newline required (the test trims it). Matches the value GitHub sends in the `X-GitHub-Event` HTTP header.
25
-
Write `deployment` to `tests/events/deployment/type.txt`.
Bare event type only — no action suffix, no trailing newline required.
26
32
27
33
3.**Write the payload file.**
28
-
Save a real GitHub webhook payload to `tests/events/deployment/payload.json`. Mirror the formatting of existing fixtures — tabs for indentation, `JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES` style:
Verify `tests/events/deployment/payload.json` is valid JSON:
34
+
Copy a real payload from `log/` (structure is `{"repo":"...","event":"...","data":{...}}`; use the `data` value) or from GitHub docs. Save as `tests/events/deployment/payload.json`. Validate:
4.**Generate `expected_text.txt` using the test suite.**
53
-
Run the tests — the new fixture will fail and print the actual output. Use that output as the content of `expected_text.txt`, then re-run to confirm it passes:
3. Write `tests/events/deployment/payload.json` with a real GitHub deployment payload
72
-
4. Run `vendor/bin/phpunit tests/GithubMessageBuilderTest.php`, capture actual output, write to `tests/events/deployment/expected_text.txt`
73
-
5. Re-run tests to verify they pass
74
-
75
-
**Result:**`tests/events/deployment/` contains all three files; `vendor/bin/phpunit tests/GithubMessageBuilderTest.php` exits green.
52
+
All tests must pass. The fixture is picked up automatically via `DirectoryIterator` on `tests/events/`.
76
53
77
54
## Common Issues
78
55
79
-
-**`file_get_contents(...): Failed to open stream`** — one of the three required files is missing. Check `tests/events/deployment/` contains `type.txt`, `payload.json`, `expected_text.txt`.
80
-
-**`assertEquals failed`** — `expected_text.txt`content doesn't match actual output. Re-run the test, capture actual output, update the file.
81
-
-**New fixture not picked up by test runner** — confirm the directory is directly under `tests/events/` (not nested). The test uses a single-level `DirectoryIterator`.
82
-
-**`GetEventType()` assertion fails** — `tests/events/deployment/type.txt` contains extra whitespace or wrong casing. The value must exactly match the GitHub `X-GitHub-Event` header (all lowercase, underscores, e.g. `pull_request` not `Pull-Request`).
56
+
-**Fixture not tested** — `expected_text.txt`is missing. The test provider skips directories without this file.
57
+
-**`assertSame` fails with whitespace difference** — `expected_text.txt`has a trailing newline. The test `trim()`s the file content, so trailing newlines are fine, but mid-string differences (e.g. extra space) will fail.
58
+
-**`json_decode` returns null** — `payload.json` has invalid JSON. Validate with `php -r "var_dump(json_decode(file_get_contents('...')));"` — must not print `NULL`.
59
+
-**New fixture not picked up** — confirm the directory is directly under `tests/events/` (not nested two levels deep).
Copy file name to clipboardExpand all lines: CALIBER_LEARNINGS.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,3 +8,9 @@ Auto-managed by [caliber](https://github.com/caliber-ai-org/ai-setup) — do not
8
8
-**[gotcha:project]**`composer.json` has no `autoload`, `autoload-dev`, or `scripts` sections — there is no PSR-4 autoloader and no `composer test` shortcut. Classes (`GithubWebhook`, `IgnoredEventException`, etc.) are loaded via manual `require` statements. Tests must bootstrap these manually or via a PHPUnit bootstrap file.
9
9
-**[pattern:project]** Real GitHub webhook payloads live in `log/` as JSON files with structure `{"repo": "...", "event": "...", "data": {...payload...}}`. The `data` key holds the raw webhook payload — use these as authoritative source material when creating new fixtures under `tests/events/`.
10
10
-**[gotcha:project]** In the `push` event handler, `$Msg['alias']` is set from `$Message['head_commit']['author']['name']` (commit author name), **not**`$Message['pusher']['name']`. These differ when CI or bots push commits authored by a human. Code that compares commit authors against the pusher must use `$Msg['alias']`, not `$Message['pusher']['name']`.
11
+
-**[fix:project]**`phpunit.xml` must have `bootstrap="tests/bootstrap.php"` set — without it PHPUnit cannot load source classes since there is no PSR-4 autoloader. The bootstrap file manually `require`s all `src/` classes.
12
+
-**[gotcha:project]**`composer.json` now has a `scripts` section — `composer test`, `composer analyse`, `composer cs-fix`, and `composer cs-check` all work. The old stale learning about no scripts is now superseded.
13
+
-**[convention:project]** Test fixture directories under `tests/events/{event_name}/` now use **3 files**: `payload.json`, `type.txt`, and `expected_text.txt` (plain text, no IRC color codes). The old 4-file format with `expected.bin` and `discord.json` was for the removed `IrcConverter`/`DiscordConverter` — do NOT create those files.
14
+
-**[pattern:project]**`GithubMessageBuilder` (in `src/GithubMessageBuilder.php`) handles all message formatting. The `switch ($EventType)` block in `web/github.php` is now routing-only: call `$Builder->build()` before the switch, then each case just decides whether to call `SendToChat` or skip it. Do NOT rebuild `$Msg` inside individual cases.
15
+
-**[gotcha:project]**`release` edited events have a `changes` key in the payload that is an **empty array**`[]` — GitHub does not populate what fields changed. There is no `from`/`to` data available for release edits; the message can only show the current release state, not what was modified.
16
+
-**[gotcha:project]**`status` events (CI status from AppVeyor, Scrutinizer, Travis, etc.) are NOT ignored in the current codebase — they fall through to `default:` which emits a generic "triggered a status event" message. The payload has rich fields: `state` (success/failure/error/pending), `description` (CI message), `context` (CI service name), `target_url` (link to build), and `commit.commit.message`. Add a dedicated `case 'status':` handler in `GithubMessageBuilder::buildText()` to surface these fields.
0 commit comments