async-test-and-doc-sync
Skill1.1k starsChanged 35 days agoMITView on GitHub
Maintain test and documentation alignment — PHPUnit tests, async testing patterns, PHPDoc contracts, guide pages, and documentation workflow. Use when adding tests, updating docs, or changing public behavior.
- Reads credentials
Trending
More talk lately.about the whole repository
Who's talking about discord-php/DiscordPHP
- @throwable.bsky.social“📦 team-reflex/discord-php v10.45.21 An unofficial API to interact with the voice and text service Discord. …”Bluesky · Feb 27, 2026 · 1 likes
- crimsonstrife/streamer.live“Bump team-reflex/discord-php from 10.18.24 to 10.18.45”GitHub · Aug 19, 2025 · 1 reactions
- crimsonstrife/streamer.live“Bump team-reflex/discord-php from 10.18.0 to 10.18.5”GitHub · Jul 8, 2025 · 1 reactions
- crimsonstrife/streamer.live“build(deps): bump team-reflex/discord-php from 10.17.0 to 10.17.3”GitHub · Jun 16, 2025 · 1 reactions
- crimsonstrife/streamer.live“build(deps): bump team-reflex/discord-php from 10.13.1 to 10.14.0”GitHub · Jun 9, 2025 · 1 reactions
The biggest 5 of 52 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 52
Talked about on GitHub and Bluesky (52 times).
On GitHub · 50
- Aug 19, 2025Bump team-reflex/discord-php from 10.18.24 to 10.18.45 — crimsonstrife/streamer.live1 reaction · 2 comments
- Jul 8, 2025Bump team-reflex/discord-php from 10.18.0 to 10.18.5 — crimsonstrife/streamer.live1 reaction · 3 comments
- Jun 16, 2025build(deps): bump team-reflex/discord-php from 10.17.0 to 10.17.3 — crimsonstrife/streamer.live1 reaction · 3 comments
- Jun 9, 2025build(deps): bump team-reflex/discord-php from 10.13.1 to 10.14.0 — crimsonstrife/streamer.live1 reaction · 3 comments
- Jun 2, 2025build(deps): bump team-reflex/discord-php from 10.10.12 to 10.11.6 — crimsonstrife/streamer.live1 reaction · 3 comments
45 more on GitHub
- May 26, 2025build(deps): bump team-reflex/discord-php from 10.10.0 to 10.10.6 — crimsonstrife/streamer.live1 reaction · 2 comments
- May 19, 2025build(deps): bump team-reflex/discord-php from 10.7.3 to 10.8.5 — crimsonstrife/streamer.live1 reaction · 2 comments
- May 5, 2025build(deps): bump team-reflex/discord-php from 10.7.1 to 10.7.2 — crimsonstrife/streamer.live1 reaction · 2 comments
- Apr 28, 2025build(deps): bump team-reflex/discord-php from 10.4.7 to 10.7.1 — crimsonstrife/streamer.live1 reaction · 3 comments
- Mar 25, 2025build(deps): bump team-reflex/discord-php from 10.4.3 to 10.4.4 — crimsonstrife/streamer.live1 reaction · 3 comments
- Jul 18, 2024✨ Add support for polls — laracord/framework1 reaction
- May 11, 2024update d.py/d.php polls — advaith1/libs1 reaction · 1 comment
- Nov 2, 2026build(deps): update team-reflex/discord-php requirement from 10.66.* to 10.71.* — smrealms/smr0 reactions
- Oct 26, 2026build(deps): update team-reflex/discord-php requirement from 10.66.* to 10.69.* — smrealms/smr0 reactions · 1 comment
- Oct 20, 2026build(deps): update team-reflex/discord-php requirement from 10.66.* to 10.68.* — smrealms/smr0 reactions · 1 comment
- Oct 19, 2026Bump team-reflex/discord-php from 10.59.0 to 10.67.0 — omnicolor/commlink0 reactions · 1 comment
- Oct 14, 2026build(deps): update team-reflex/discord-php requirement from 10.66.* to 10.67.* — smrealms/smr0 reactions · 1 comment
- Oct 13, 2026Bump team-reflex/discord-php from 10.59.0 to 10.66.3 — omnicolor/commlink0 reactions · 1 comment
- Oct 6, 2026Bump team-reflex/discord-php from 10.59.0 to 10.66.1 — omnicolor/commlink0 reactions · 1 comment
- Oct 5, 2026Bump team-reflex/discord-php from 10.59.0 to 10.65.0 — omnicolor/commlink0 reactions · 1 comment
- Oct 1, 2026build(deps): update team-reflex/discord-php requirement from 10.49.* to 10.66.* — smrealms/smr0 reactions
- Oct 1, 2026Bump team-reflex/discord-php from 10.57.0 to 10.59.0 — omnicolor/commlink0 reactions
- Sep 30, 2026build(deps): update team-reflex/discord-php requirement from 10.49.* to 10.62.* — smrealms/smr0 reactions · 1 comment
- Sep 29, 2026Bump team-reflex/discord-php from 10.57.0 to 10.58.0 — omnicolor/commlink0 reactions · 1 comment
- Sep 28, 2026build(deps): update team-reflex/discord-php requirement from 10.49.* to 10.59.* — smrealms/smr0 reactions · 1 comment
- Sep 25, 2026build(deps): update team-reflex/discord-php requirement from 10.49.* to 10.58.* — smrealms/smr0 reactions · 1 comment
- Sep 25, 2026Bump team-reflex/discord-php from 10.56.18 to 10.57.0 — omnicolor/commlink0 reactions
- Sep 23, 2026Bump team-reflex/discord-php from 10.56.17 to 10.56.18 — omnicolor/commlink0 reactions
- Sep 21, 2026build(deps): update team-reflex/discord-php requirement from 10.49.* to 10.57.* — smrealms/smr0 reactions · 1 comment
- Sep 14, 2026Bump team-reflex/discord-php from 10.56.15 to 10.56.17 — omnicolor/commlink0 reactions
- Sep 7, 2026Bump team-reflex/discord-php from 10.56.10 to 10.56.15 — omnicolor/commlink0 reactions
- Sep 7, 2026build: Bump team-reflex/discord-php from 10.48.14 to 10.56.15 — VATSIM-UK/core0 reactions
- Sep 4, 2026Bump team-reflex/discord-php from 10.56.10 to 10.56.13 — omnicolor/commlink0 reactions · 1 comment
- Sep 2, 2026Bump team-reflex/discord-php from 10.56.8 to 10.56.10 — omnicolor/commlink0 reactions
- Sep 1, 2026Bump team-reflex/discord-php from 10.56.8 to 10.56.9 — omnicolor/commlink0 reactions · 1 comment
- Aug 26, 2026Bump team-reflex/discord-php from 10.55.1 to 10.56.5 — omnicolor/commlink0 reactions
- Aug 25, 2026Bump team-reflex/discord-php from 10.55.1 to 10.56.3 — omnicolor/commlink0 reactions · 1 comment
- Aug 18, 2026build(deps): update team-reflex/discord-php requirement from 10.49.* to 10.56.* — smrealms/smr0 reactions · 1 comment
- Apr 20, 2026Bump team-reflex/discord-php from 10.47.12 to 10.48.1 — crimsonstrife/streamer.live0 reactions · 1 comment
- Feb 10, 2026Bump team-reflex/discord-php from 10.45.15 to 10.45.16 — crimsonstrife/streamer.live0 reactions · 3 comments
- Nov 4, 2025Add Discord Announcement Bot System — k33bz/lastwar-server15860 reactions · 4 comments
- Oct 20, 2025Tag "@property" has error when both ? and null types are included — phpDocumentor/phpDocumentor0 reactions · 1 comment
- Nov 15, 2024Update dependency team-reflex/discord-php to v10 — System3-2/discord-bot0 reactions
- Feb 11, 2024Thread gets terminated when using a slash command with options. — DiscordBot-PMMP/DiscordBot0 reactions · 3 comments
- Jan 14, 2024Update dependency team-reflex/discord-php to v7.3.5 — Karhal/discord-gpt0 reactions
- Jan 14, 2024Update dependency team-reflex/discord-php to v7.3.5 — System3-2/discord-bot0 reactions
- Jan 31, 2023Invalid Activity URL — DiscordBot-PMMP/DiscordBot0 reactions · 3 comments
- Dec 20, 2022Another message type not supported when delete the message — DiscordBot-PMMP/DiscordBot0 reactions · 6 comments
- Aug 19, 2022[Egg Request]: DiscordPHP — pelican-eggs/eggs0 reactions · 1 comment
- Apr 17, 2022Intents help — DiscordBot-PMMP/DiscordBot0 reactions · 4 comments
On Bluesky · 2
- Feb 27, 2026📦 team-reflex/discord-php v10.45.21 An unofficial API to interact with the voice and text service Discord. 🔗… — @throwable.bsky.social1 likes and repost
- Aug 10, 2026📦 team-reflex/discord-php v10.55.0 An unofficial API to interact with the voice and text service Discord. 🔗… — @throwable.bsky.social0 likes and reposts · 1 reply
In this repository14 other files it gives its agents.
- AGENTS.mdAGENTS.md
- builder-payload-smithSkill
- gateway-cache-sync-keeperSkill
- helpers-and-infra-keeperSkill
- interaction-flow-keeperSkill
- legacy-command-client-keeperSkill
- part-model-maintainerSkill
- repository-cache-keeperSkill
- runtime-bootstrap-keeperSkill
- type-map-keeperSkill
- voice-subsystem-keeperSkill
- discord-php-bot-securitySkill
- discord-php-extensionSkill
- discord-php-interactionsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
16 rules. About 0 are common, 6 are distinctive, and 10 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 11
Use this skill when adding or changing public behavior, updating builder validation or part semantics, writing or reviewing tests, updating …
- Distinctive: line 17
Keep tests, PHPDoc, and long-form documentation synchronized with the public behavior of parts, repositories, builders, and helpers:
- Distinctive: line 53
If a change touches public behavior but skips one of these surfaces, the contract is incomplete.
- Very specific: line 59
All unit-test classes must extend DiscordTestCase, including tests for logic isolated from Discord I/O:
- Very specific: line 67
Use $this->getMockBuilder() for isolated class dependencies and getMockDiscord() when a lightweight real client is needed.
- Very specific: line 73
Use wait() and return the wait() call when the test must interact with real Discord infrastructure — sending/editing/deleting messages, …
- Very specific: line 83
Use $this->getMockBuilder() for mocked class dependencies.
- Very specific: line 89
Test files mirror the source structure.
- Very specific: line 96
All unit tests extend DiscordTestCase
- Very specific: line 136
always pass $resolve as both fulfillment and rejection handler at the end of the chain
- Very specific: line 139
default timeout is 10 seconds (TIMEOUT constant)
- Very specific: line 145
Every part class should have class-level docblock annotations for @property (read/write magic properties from $fillable), @property-read …
- Distinctive: line 194
default behavior changes in a way that affects existing bots
- Very specific: line 220
Use --filter to target specific tests: ./vendor/bin/phpunit --filter ModalBuilderTest
- Distinctive: line 256
Stop if you see:
- Distinctive: line 264
test asserting exact internal array structure instead of semantic behavior
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Skill: async-test-and-doc-sync
Use this skill when adding or changing public behavior, updating builder validation or part semantics, writing or reviewing tests, updating PHPDoc blocks or guide pages, or touching anything user-facing enough that tests or docs should move with it.
This is alignment skill. Load it when the question is not "does the code work?" but "do tests prove it and do docs describe it?"
Goal
Keep tests, PHPDoc, and long-form documentation synchronized with the public behavior of parts, repositories, builders, and helpers:
- unit tests assert semantic behavior, not incidental implementation
- integration tests prove real async flows against Discord
- PHPDoc blocks serve as contract surface for IDEs and generated reference
- guide and docs pages reflect current recommended usage
- changes to public behavior always travel with their companion test and doc updates
Read in this order
tests/functions.php—wait()helper andgetMockDiscord()factorytests/DiscordTestCase.php— integration base class with real channel setuptests/bootstrap.php— autoload,.envloading, singleton wiringphpunit.xml— test suite configuration, coverage settings- Representative unit tests:
tests/Builders/ModalBuilderTest.phptests/FunctionsTest.phptests/CollectionsTest.php
- Representative integration tests:
tests/Parts/Channel/ChannelTest.phptests/Parts/Channel/Message/Embed/EmbedTest.phptests/Parts/Channel/Message/MessageTest.php
guide/— long-form RST documentation for parts, events, buildersdocs/— Gatsby site source for published documentationREADME.md— getting started, installation, basic usageCONTRIBUTING.md— contributor workflow and code style expectations
Core contract
Tests and docs in this repo are not afterthoughts. They form a contract surface:
- PHPDoc
@propertyand@property-readannotations on parts are how IDEs and users discover magic properties. If code adds a fillable field or getter mutator without updating the docblock, the property is effectively invisible to consumers. - Unit tests extend
DiscordTestCase; use$this->getMockBuilder()for isolated class dependencies andgetMockDiscord()when a lightweight real client is needed. - Integration tests extending
DiscordTestCaseprove that async flows work against real Discord infrastructure. These require environment variables and a live bot token. - Guide pages in
guide/and Gatsby pages indocs/describe recommended patterns. They should only change when public behavior or preferred usage actually changes — not for internal refactors.
If a change touches public behavior but skips one of these surfaces, the contract is incomplete.
Unit tests vs integration tests
Unit tests
All unit-test classes must extend DiscordTestCase, including tests for logic isolated from Discord I/O:
- builder validation limits (content length, component counts, enum values)
- helper function behavior (
contains(),studly(),escapeMarkdown(),poly_strlen()) - collection operations (
push(),map(),filter(),from()) - part attribute hydration from raw arrays using
getMockDiscord() - serialization shape from
jsonSerialize()on builders
Use $this->getMockBuilder() for isolated class dependencies and getMockDiscord() when a lightweight real client is needed. DiscordTestCase supplies the shared test lifecycle and skips cleanly when Discord integration is unavailable.
Example: tests/Builders/ModalBuilderTest.php uses $this->expectException(\LogicException::class) and str_repeat('a', 101) to verify title length validation.
Integration tests
Use wait() and return the wait() call when the test must interact with real Discord infrastructure — sending/editing/deleting messages, pinning, creating invites, fetching message history, verifying embed hydration, or testing repository fetch()/freshen() against live API.
These tests require DISCORD_TOKEN, TEST_CHANNEL, and TEST_CHANNEL_NAME in .env or environment. DiscordSingleton shares a single connected client across the suite. Reach the live channel only through $this->channel(): it skips the test when there is no token, so the rest of the class still runs offline. A test that needs Discord some other way should check self::isLive() and skip itself.
A test that sends a request should not need Discord at all: set getMockHttpDriver() on a getMockDiscord() client and assert on the requests it records, as tests/Parts/Guild/GuildRequestsTest.php does. Those run in CI on every push and pull request (.github/workflows/tests.yml).
The getMockDiscord() factory
Defined in tests/functions.php. Creates a minimal Discord instance with empty token and NullLogger — suitable for constructing parts and testing attribute access without connecting to gateway.
Use $this->getMockBuilder() for mocked class dependencies. Use getMockDiscord() for local client-backed tests; otherwise use and return wait() for asynchronous work.
Test suite organization
Directory layout
Test files mirror the source structure. Builder tests live in tests/Builders/, part tests in tests/Parts/{Family}/, and utility tests in tests/ root. Infrastructure files (bootstrap.php, functions.php, DiscordSingleton.php, DiscordTestCase.php) live at the tests/ root.
Where to place new tests
- Builder tests →
tests/Builders/{BuilderName}Test.php - Part tests →
tests/Parts/{Family}/{PartName}Test.php - Helper/utility tests →
tests/root - All unit tests extend
DiscordTestCase
phpunit.xml
Discovers all *Test.php under tests/ recursively. Coverage tracks src/. Bootstrap is tests/bootstrap.php.
Async testing patterns
The wait() bridge
wait() in tests/functions.php bridges Promise-based async code into synchronous PHPUnit assertions:
function wait(callable $callback, float $timeout = TIMEOUT, ?callable $timeoutFn = null)It works by scheduling $callback on the ReactPHP loop via futureTick(), passing a $resolve callable that stops the loop and captures the result, adding a timeout timer (default 10s), running the loop synchronously, and re-throwing any captured exception after loop stops.
Common assertion patterns in integration tests
Promise chain with assertion then resolve:
return wait(function (Discord $discord, $resolve) {
$this->channel()->sendMessage('test content')
->then(fn (Message $m) => $this->assertEquals('test content', $m->content))
->then($resolve, $resolve);
});Custom timeout with fallback:
return wait(function (Discord $discord, $resolve) {
// ... async work ...
}, 10, fn () => $this->markTestIncomplete('Hit rate limit.'));Key rules:
- always pass
$resolveas both fulfillment and rejection handler at the end of the chain - the
$callbackreceives(Discord $discord, callable $resolve)— use$discordfor client access - return the
wait()call from the test method so PHPUnit tracks it - default timeout is 10 seconds (
TIMEOUTconstant)
PHPDoc as contract surface
What to document
Every part class should have class-level docblock annotations for @property (read/write magic properties from $fillable), @property-read (computed properties from mutators or repos), @method (delegated magic methods), @since (version introduced), and @link (Discord API docs URL).
Why this matters
PHPDoc in this repo serves three purposes: IDE autocompletion (consumers rely on @property since all access goes through __get()), generated reference (docs tooling reads annotations), and static analysis (Mago uses docblocks for type checking).
When to update docblocks
- new field added to
$fillable→ add@propertywith type - new getter mutator added → add
@property-readwith return type - new repository exposed in
$repositories→ add@property-readfor the repository type - field removed or deprecated → update or remove annotation
- type changed (e.g.,
stringto?string) → update annotation
Example pattern
/**
* @property string $id
* @property string $name
* @property-read Carbon $created_at
* @property-read MemberRepository $members
* @link https://discord.com/developers/docs/resources/guild
*/
class Guild extends PartGuide and documentation structure
guide/ — long-form RST content
User-facing guides organized by topic: basics.rst (getting started, intents), parts/ (per-resource docs), events/ (gateway handling), repositories.rst, message_builder.rst, components.rst, interactions.rst, permissions.rst, collection.rst, faq.rst.
docs/ — Gatsby site
Published documentation website source. Build with cd docs && yarn install && yarn build.
README.md
Installation, requirements, basic bot example. Update when minimum PHP version, major dependencies, or getting-started flow changes.
When docs must change
Docs should change when:
- a new public method, property, or repository is added that users will call
- preferred usage pattern changes (e.g., builder replaces raw array)
- a method signature or return type changes
- a feature is deprecated and users need migration guidance
- default behavior changes in a way that affects existing bots
Docs should not change when:
- internal refactoring preserves all public behavior
- test infrastructure changes
- cache implementation details shift without affecting public API
- gateway event internals change without altering emitted shapes
Running tests and checks
| Purpose | Command |
| Run PHPUnit suite | composer unit |
| Static analysis | composer run-script mago-lint |
| Code style fixer | composer run-script cs |
| Non-mutating style check | ./vendor/bin/pint --test --config ./pint.json ./src |
| Compare with Discord's live OpenAPI description | composer openapi |
| Docs site build | cd docs && yarn install && yarn build |
Integration test environment
Integration tests require .env or shell variables: DISCORD_TOKEN (bot token), TEST_CHANNEL (channel ID), TEST_CHANNEL_NAME (channel name). When absent, DiscordSingleton falls back to getMockDiscord(), the tests that use $this->channel() skip, and every other test runs.
Running subsets
Use --filter to target specific tests: ./vendor/bin/phpunit --filter ModalBuilderTest
What to test
Builder tests should assert
- validation boundary cases (max length, max count, invalid enum)
- correct exception types and messages for invalid input
jsonSerialize()output shape matches Discord API expectationsnew()factory wires arguments correctlyfromPart()round-trip preserves meaningful fields- optional fields omitted when unset
Part tests should assert
- getter mutators return correct types (Carbon, Collection, nested Part)
- attribute hydration from raw Discord payload arrays
getCreatableAttributes()/getUpdatableAttributes()include correct fields- permission and semantic guard behavior in
save()overrides - computed properties resolve correctly from related data
Integration tests should assert
- end-to-end flows complete through real Discord API
- returned objects are correctly typed instances
- repository operations (fetch, freshen, save) produce expected state
- message operations (send, edit, delete, pin) work as documented
What not to test
- trivial getters/setters with no logic
- internal cache mechanics (test through public behavior instead)
- Discord API behavior itself (test your code's handling of responses)
Smells
Stop if you see:
- new public magic property with no
@propertydocblock entry - builder with validation logic but no test for boundary cases
- integration test that could be a unit test (no real Discord interaction needed)
wait()used in a test that never performs async I/O- guide page updated for internal refactor that did not change public behavior
- public method added with no test and no docblock
- test asserting exact internal array structure instead of semantic behavior
getMockDiscord()used where asynchronous real client interaction is actually needed
Checklist before commit
- New public properties have
@propertyor@property-readin class docblock - Builder validation has boundary test cases (valid edge, invalid edge, exception type)
- Integration tests use
wait()pattern with proper$resolvechaining - Every test class extends
DiscordTestCase - Tests use
getMockBuilder()orgetMockDiscord()where appropriate - Async tests use and return
wait()with proper$resolvechaining - Test file placed in correct directory mirroring source structure
- Guide pages updated if preferred usage or public contract changed
- README updated if installation, requirements, or getting-started flow changed
composer unitpassescomposer run-script mago-lintreports no new issues- No tests left that assert implementation details instead of behavior
Bottom line
Tests prove behavior, docblocks declare surface, guides teach usage — if any of these drift from the code, users and tooling lose trust in the library.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

