Link Commands
Commands for managing binding-test relationships.
eventflow links:report
Show the relationship between bindings and their tests.
bash
# All bindings
eventflow links:report
# For specific flow
eventflow links:report order.flow
# Output formats
eventflow links:report --format=table # Default
eventflow links:report --format=json
eventflow links:report --format=markdownOutput: Table Format (Default)
$ eventflow links:report
EventFlow v1.0.0
════════════════════════════════════════
BINDING-TEST LINKS REPORT
════════════════════════════════════════
GUARDS
────────────────────────────────────────
┌─────────────────────────────┬───────────────────────────────────────┬──────────┐
│ Pattern │ Binding → Test │ Status │
├─────────────────────────────┼───────────────────────────────────────┼──────────┤
│ 'cart is not empty' │ CartNotEmptyGuard │ ✓ Linked │
│ │ ↔ CartNotEmptyGuardTest │ 3 tests │
├─────────────────────────────┼───────────────────────────────────────┼──────────┤
│ '@customer is logged in' │ CustomerLoggedInGuard │ ✓ Linked │
│ │ ↔ CustomerLoggedInGuardTest │ 3 tests │
├─────────────────────────────┼───────────────────────────────────────┼──────────┤
│ '$retry_count is less than │ RetryLimitGuard │ ⚠ Partial│
│ 3' │ → RetryLimitGuardTest (no #[Tests]) │ 5 tests │
├─────────────────────────────┼───────────────────────────────────────┼──────────┤
│ 'payment is authorized' │ PaymentAuthorizedGuard │ ✗ None │
│ │ (no test linked) │ 0 tests │
└─────────────────────────────┴───────────────────────────────────────┴──────────┘
ACTIONS
────────────────────────────────────────
┌─────────────────────────────┬───────────────────────────────────────┬──────────┐
│ Pattern │ Binding → Test │ Status │
├─────────────────────────────┼───────────────────────────────────────┼──────────┤
│ '$retry_count increases by │ IncrementRetryCountAction │ ✓ Linked │
│ 1' │ ↔ IncrementRetryCountActionTest │ 2 tests │
├─────────────────────────────┼───────────────────────────────────────┼──────────┤
│ 'send confirmation email' │ SendConfirmationEmailAction │ ✓ Linked │
│ │ ↔ SendConfirmationEmailActionTest │ 2 tests │
└─────────────────────────────┴───────────────────────────────────────┴──────────┘
════════════════════════════════════════
SUMMARY
════════════════════════════════════════
Link Status:
✓ Fully linked (bidirectional): 4 bindings
⚠ Partially linked: 1 binding
✗ Not linked: 1 binding
Coverage:
Bindings with tests: 5/6 (83%)
Total test methods: 15
Orphaned tests: 0
Placeholders:
Unresolved: 0Output: JSON Format
json
{
"version": "1.0.0",
"generated_at": "2024-01-15T14:32:15Z",
"summary": {
"total_bindings": 6,
"linked": 4,
"partial": 1,
"unlinked": 1,
"total_tests": 15,
"orphaned_tests": 0
},
"bindings": [
{
"pattern": "cart is not empty",
"type": "guard",
"class": "App\\Order\\Guards\\CartNotEmptyGuard",
"file": "src/Order/Guards/CartNotEmptyGuard.php",
"line": 12,
"tested_by": [
{
"class": "Tests\\Order\\Guards\\CartNotEmptyGuardTest",
"bidirectional": true,
"methods": [
"test_returns_false_when_cart_is_null",
"test_returns_false_when_cart_is_empty",
"test_returns_true_when_cart_has_items"
]
}
],
"status": "linked"
}
]
}eventflow links:validate
Validate that all bindings have proper test links.
bash
# Basic validation
eventflow links:validate
# For specific flow
eventflow links:validate order.flow
# Strict mode (fail on warnings)
eventflow links:validate --strict
# Quiet mode (exit code only)
eventflow links:validate --quietOptions:
| Option | Description |
|---|---|
--strict | Treat warnings as errors (for CI/CD) |
--quiet | Only output on failure |
--ignore=PATTERN | Ignore patterns matching regex |
Exit Codes:
| Code | Meaning |
|---|---|
0 | All validations passed |
1 | Errors found (or warnings in strict mode) |
Output: All Valid
$ eventflow links:validate
EventFlow v1.0.0
Validating binding-test links...
Checking bindings...
✓ CartNotEmptyGuard ('cart is not empty')
✓ CustomerLoggedInGuard ('@customer is logged in')
✓ RetryLimitGuard ('$retry_count is less than 3')
✓ CustomerIsAdminGuard ('@customer is admin')
✓ IncrementRetryCountAction ('$retry_count increases by 1')
✓ SendConfirmationEmailAction ('send confirmation email')
Checking tests...
✓ CartNotEmptyGuardTest → 'cart is not empty'
✓ CustomerLoggedInGuardTest → '@customer is logged in'
✓ RetryLimitGuardTest → '$retry_count is less than 3'
✓ CustomerIsAdminGuardTest → '@customer is admin'
✓ IncrementRetryCountActionTest → '$retry_count increases by 1'
✓ SendConfirmationEmailActionTest → 'send confirmation email'
Checking placeholders...
✓ No unresolved placeholders
────────────────────────────────────────
✓ Validation passed
6 bindings validated
6 test classes validated
0 issues foundOutput: With Warnings
$ eventflow links:validate
EventFlow v1.0.0
Validating binding-test links...
Checking bindings...
✓ CartNotEmptyGuard ('cart is not empty')
✓ CustomerLoggedInGuard ('@customer is logged in')
⚠ RetryLimitGuard ('$retry_count is less than 3')
Missing #[TestedBy] attribute
✓ CustomerIsAdminGuard ('@customer is admin')
⚠ PaymentAuthorizedGuard ('payment is authorized')
No test coverage
Checking tests...
✓ CartNotEmptyGuardTest → 'cart is not empty'
✓ CustomerLoggedInGuardTest → '@customer is logged in'
⚠ RetryLimitGuardTest
Missing #[Tests] attribute
✓ CustomerIsAdminGuardTest → '@customer is admin'
Checking placeholders...
✓ No unresolved placeholders
────────────────────────────────────────
⚠ Validation passed with warnings
6 bindings validated
4 test classes validated
3 warnings found
Warnings:
1. RetryLimitGuard: Missing #[TestedBy] attribute
Add: #[TestedBy(RetryLimitGuardTest::class)]
2. PaymentAuthorizedGuard: No test coverage
Run: eventflow make:binding-test "payment is authorized"
3. RetryLimitGuardTest: Missing #[Tests] attribute
Add: #[Tests('$retry_count is less than 3')]Output: Strict Mode with Errors
$ eventflow links:validate --strict
EventFlow v1.0.0
Validating binding-test links (strict mode)...
Checking bindings...
✓ CartNotEmptyGuard ('cart is not empty')
✓ CustomerLoggedInGuard ('@customer is logged in')
✗ RetryLimitGuard ('$retry_count is less than 3')
Missing #[TestedBy] attribute
✓ CustomerIsAdminGuard ('@customer is admin')
✗ PaymentAuthorizedGuard ('payment is authorized')
No test coverage
Checking tests...
✓ CartNotEmptyGuardTest → 'cart is not empty'
✗ OldCartTest
Orphaned test: links to 'cart is empty' but binding not found
Checking placeholders...
✗ @payment-guard
Unresolved placeholder in PaymentGuard.php:8
────────────────────────────────────────
✗ Validation FAILED (strict mode)
Issues Found:
ERROR #1: Missing #[TestedBy]
────────────────────────────────────────
Binding: App\Order\Guards\RetryLimitGuard
File: src/Order/Guards/RetryLimitGuard.php:10
The binding has a test but no #[TestedBy] attribute.
Fix: Add attribute to binding class:
#[Guard('$retry_count is less than 3')]
#[TestedBy(RetryLimitGuardTest::class)] // Add this
class RetryLimitGuard
Or run: eventflow links:sync
ERROR #2: No Test Coverage
────────────────────────────────────────
Binding: App\Order\Guards\PaymentAuthorizedGuard
File: src/Order/Guards/PaymentAuthorizedGuard.php:8
The binding has no linked test class.
Fix: Create a test class:
eventflow make:binding-test "payment is authorized"
────────────────────────────────────────
4 errors, 0 warnings
Exit code: 1eventflow links:sync
Automatically add missing #[TestedBy] attributes to bindings.
bash
# Sync all bindings
eventflow links:sync
# For specific flow
eventflow links:sync order.flow
# Dry run (show what would change)
eventflow links:sync --dry-run
# Force overwrite existing
eventflow links:sync --forceOptions:
| Option | Description |
|---|---|
--dry-run | Show changes without applying |
--force | Overwrite existing links |
Output: Dry Run
$ eventflow links:sync --dry-run
EventFlow v1.0.0
Analyzing binding-test links (dry run)...
Scanning bindings...
→ 6 bindings found
Scanning tests...
→ 6 test classes found
Matching patterns...
────────────────────────────────────────
CHANGES TO BE MADE
────────────────────────────────────────
1. RetryLimitGuard
File: src/Order/Guards/RetryLimitGuard.php
Current:
#[Guard('$retry_count is less than 3')]
class RetryLimitGuard
After sync:
#[Guard('$retry_count is less than 3')]
#[TestedBy(RetryLimitGuardTest::class)] // Added
class RetryLimitGuard
2. CustomerIsAdminGuard
File: src/Order/Guards/CustomerIsAdminGuard.php
Current:
#[Guard('@customer is admin')]
class CustomerIsAdminGuard
After sync:
#[Guard('@customer is admin')]
#[TestedBy(CustomerIsAdminGuardTest::class)] // Added
class CustomerIsAdminGuard
────────────────────────────────────────
DRY RUN COMPLETE
Would update: 2 files
Would skip: 4 files (already synced)
No test: 0 files
Run without --dry-run to apply changes.Output: Actual Sync
$ eventflow links:sync
EventFlow v1.0.0
Syncing binding-test links...
Scanning bindings...
→ 6 bindings found
Scanning tests...
→ 6 test classes found
Syncing...
✓ RetryLimitGuard
Added: #[TestedBy(RetryLimitGuardTest::class)]
File: src/Order/Guards/RetryLimitGuard.php
✓ CustomerIsAdminGuard
Added: #[TestedBy(CustomerIsAdminGuardTest::class)]
File: src/Order/Guards/CustomerIsAdminGuard.php
○ CartNotEmptyGuard
Already synced
○ CustomerLoggedInGuard
Already synced
○ IncrementRetryCountAction
Already synced
○ SendConfirmationEmailAction
Already synced
────────────────────────────────────────
✓ Sync complete
Updated: 2 files
Skipped: 4 files (already synced)
Run eventflow links:validate to verify.eventflow links:pair
Resolve placeholder references to actual class names.
bash
# Resolve all placeholders
eventflow links:pair
# For specific flow
eventflow links:pair order.flow
# Dry run
eventflow links:pair --dry-runOutput: Resolving Placeholders
$ eventflow links:pair
EventFlow v1.0.0
Resolving placeholders...
Scanning for placeholders...
→ Found 3 placeholders
Matching placeholders to classes...
────────────────────────────────────────
PLACEHOLDER RESOLUTION
────────────────────────────────────────
1. @cart-guard
────────────────────────────────────
Found in:
→ src/Order/Guards/CartNotEmptyGuard.php:9
#[TestedBy('@cart-guard')]
→ tests/Order/Guards/CartNotEmptyGuardTest.php:8
#[Tests('@cart-guard')]
Resolution:
Pattern: 'cart is not empty'
Binding: App\Order\Guards\CartNotEmptyGuard
Test: Tests\Order\Guards\CartNotEmptyGuardTest
Changes:
CartNotEmptyGuard.php:
- #[TestedBy('@cart-guard')]
+ #[TestedBy(CartNotEmptyGuardTest::class)]
CartNotEmptyGuardTest.php:
- #[Tests('@cart-guard')]
+ #[Tests('cart is not empty')]
✓ Resolved
2. @login-guard
────────────────────────────────────
Found in:
→ src/Order/Guards/CustomerLoggedInGuard.php:9
#[TestedBy('@login-guard')]
→ tests/Order/Guards/CustomerLoggedInGuardTest.php:8
#[Tests('@login-guard')]
Resolution:
Pattern: '@customer is logged in'
Binding: App\Order\Guards\CustomerLoggedInGuard
Test: Tests\Order\Guards\CustomerLoggedInGuardTest
✓ Resolved
3. @payment-handler
────────────────────────────────────
Found in:
→ src/Payment/Actions/ProcessPayment.php:10
#[TestedBy('@payment-handler')]
⚠ No matching test found
Suggestions:
→ Create test: eventflow make:binding-test "process payment"
→ Or manually link to existing test
○ Skipped
────────────────────────────────────────
✓ Pairing complete
Resolved: 2 placeholders
Skipped: 1 placeholder (no match)
Files: 4 updated