Skip to content

Commit 3de2eae

Browse files
authored
feat: enhance ecotone-contributor skill with test-first rules and broader trigger (#653)
1 parent aa00d0f commit 3de2eae

1 file changed

Lines changed: 51 additions & 1 deletion

File tree

  • .claude/skills/ecotone-contributor

.claude/skills/ecotone-contributor/SKILL.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ name: ecotone-contributor
33
description: >-
44
Guides Ecotone framework contributions: dev environment setup, monorepo
55
navigation, running tests, PR workflow, and package split mechanics.
6-
Use when setting up development environment, preparing PRs, validating
6+
TRIGGER whenever any code change is made to the Ecotone codebase —
7+
new features, bug fixes, refactors, or any modification to source files.
8+
Also use when setting up development environment, preparing PRs, validating
79
changes, running tests across packages, or understanding the monorepo
810
structure.
911
argument-hint: "[package-name]"
@@ -13,6 +15,54 @@ argument-hint: "[package-name]"
1315

1416
Tests use inline anonymous classes with PHP 8.1+ attributes, snake_case method names, and high-level behavioral assertions. Use this skill when writing or debugging any Ecotone test.
1517

18+
## 0. Test-First Rule (MANDATORY)
19+
20+
Every new feature or bug fix **MUST** start with a test written using **Ecotone Lite** (`EcotoneLite::bootstrapFlowTesting()` or `EcotoneLite::bootstrapForTesting()`). This is a blocking requirement — do not write production code before the test exists.
21+
22+
**Tests must follow the userland perspective.** Each test should read like an example of how an Ecotone end-user would use the feature in their application. The test sets up real handler classes (inline anonymous classes with attributes), sends commands/events/queries through the bus, and asserts on the outcome — exactly as a user would interact with the framework. Never test framework internals directly; instead, demonstrate the feature through its public API as seen by the user.
23+
24+
**Workflow:**
25+
1. **Write the test first** using Ecotone Lite — model it as a real-world usage example from the user's perspective
26+
2. Run the test — confirm it fails (red)
27+
3. Write the minimal production code to make it pass (green)
28+
4. Refactor if needed
29+
30+
**Example test-first skeleton (userland perspective with inline classes):**
31+
32+
```php
33+
public function test_placing_order_publishes_event(): void
34+
{
35+
$ecotoneLite = EcotoneLite::bootstrapFlowTesting(
36+
[new class {
37+
private array $products = [];
38+
39+
#[CommandHandler]
40+
public function placeOrder(#[Header('orderId')] string $orderId, #[Header('product')] string $product): void
41+
{
42+
$this->products[$orderId] = $product;
43+
}
44+
45+
#[QueryHandler('order.getProduct')]
46+
public function getProduct(string $orderId): string
47+
{
48+
return $this->products[$orderId];
49+
}
50+
}],
51+
);
52+
53+
$ecotoneLite->sendCommandWithRoutingKey('placeOrder', metadata: ['orderId' => '123', 'product' => 'Book']);
54+
55+
$this->assertSame(
56+
'Book',
57+
$ecotoneLite->sendQueryWithRouting('order.getProduct', '123'),
58+
);
59+
}
60+
```
61+
62+
Tests use **inline anonymous classes** defined directly inside the test method — never create separate fixture files. This keeps each test self-contained and readable as a complete usage example. **Never use static properties or static methods** in test classes — use instance properties and instance methods only. The test demonstrates **how a user would use the feature** — registering handlers, sending commands, and querying results. It does not test internal message routing, channel resolution, or framework wiring directly.
63+
64+
This applies to **all** code changes that add or modify behavior — features, bug fixes, refactors that change behavior. Pure refactors with no behavior change may skip this if existing tests already cover the behavior.
65+
1666
## 1. Dev Environment Setup
1767

1868
Start the Docker Compose stack:

0 commit comments

Comments
 (0)