Skip to content

Commit 4a613cd

Browse files
JasonBenettclaude
andcommitted
feat: add Codeception WireMock integration module
Implement a complete Codeception module for WireMock integration with the following features: - HTTP stub creation for any HTTP method with advanced request matching - Request verification with near-miss analysis for debugging - Request data retrieval (count, all requests, unmatched requests) - Automatic cleanup between tests with configurable behavior - Full WireMock Admin API integration - Comprehensive PHPStan compliance (max level, zero errors) - PER Coding Style 3.0 compliant - 100% test coverage with 26 passing tests (15 unit + 11 functional) Module provides intuitive Codeception-style methods: - haveHttpStubFor() - Create HTTP stubs - seeHttpRequest() / dontSeeHttpRequest() - Verify requests - grabRequestCount() / grabAllRequests() - Retrieve request data - sendReset() / sendClearRequests() - Manage WireMock state Includes Docker Compose setup for local development, comprehensive documentation, and detailed PHPDoc annotations with specific array types for excellent IDE support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
0 parents  commit 4a613cd

File tree

17 files changed

+1864
-0
lines changed

17 files changed

+1864
-0
lines changed

.gitattributes

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Exclude files that don't need to be present in packages (so they're not downloaded by Composer)
2+
/.gitattributes export-ignore
3+
/.gitignore export-ignore
4+
/*.md export-ignore
5+
/*.yml export-ignore

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Dependencies
2+
/vendor/
3+
4+
# Composer
5+
/composer.lock
6+
7+
# PHPUnit
8+
.phpunit.cache/
9+
.phpunit.result.cache
10+
11+
# Codeception
12+
tests/_output/
13+
tests/_support/_generated/
14+

.php-cs-fixer.dist.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
$finder = PhpCsFixer\Finder::create()
4+
->in(__DIR__ . '/src')
5+
->name('*.php');
6+
7+
$config = new PhpCsFixer\Config();
8+
return $config
9+
->setRules([
10+
'@PER-CS' => true,
11+
'@PER-CS:risky' => true,
12+
'declare_strict_types' => true,
13+
'no_unused_imports' => true,
14+
'ordered_imports' => ['sort_algorithm' => 'alpha'],
15+
'array_syntax' => ['syntax' => 'short'],
16+
'concat_space' => ['spacing' => 'one'],
17+
'no_extra_blank_lines' => true,
18+
'no_trailing_whitespace' => true,
19+
'single_quote' => true,
20+
'binary_operator_spaces' => ['default' => 'single_space'],
21+
])
22+
->setFinder($finder)
23+
->setRiskyAllowed(true);

CLAUDE.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a Codeception module for integrating with WireMock, a tool for mocking HTTP services in tests. The module extends Codeception's base `Module` class to provide WireMock functionality to Codeception test suites.
8+
9+
**Key Details:**
10+
- PHP 8.2+ required
11+
- Codeception 5.3+ required
12+
- Guzzle HTTP client 7.8+ required
13+
- MIT licensed
14+
- PSR-4 autoloading structure
15+
16+
## Project Structure
17+
18+
```
19+
src/JasonBenett/CodeceptionModuleWiremock/
20+
├── Module/
21+
│ └── Wiremock.php # Main module class with all public methods
22+
└── Exception/
23+
├── WiremockException.php # Base exception
24+
└── RequestVerificationException.php # Verification failure exception
25+
26+
tests/
27+
├── unit/
28+
│ └── Codeception/Module/
29+
│ └── WiremockTest.php # Unit tests with mocked HTTP client
30+
├── functional/
31+
│ └── WiremockIntegrationCest.php # Integration tests against real WireMock
32+
└── _support/
33+
└── FunctionalTester.php # Functional tester actor
34+
```
35+
36+
## Development Commands
37+
38+
### Dependency Management
39+
```bash
40+
composer install # Install dependencies
41+
composer update # Update dependencies
42+
composer dump-autoload # Regenerate autoload files
43+
```
44+
45+
### Testing
46+
```bash
47+
composer test # Run unit tests
48+
composer test:functional # Run functional tests (requires WireMock running)
49+
composer phpstan # Run static analysis
50+
composer cs-check # Check code style
51+
composer cs-fix # Fix code style issues
52+
```
53+
54+
### WireMock Server
55+
```bash
56+
docker-compose up -d # Start WireMock server on port 8080
57+
docker-compose down # Stop WireMock server
58+
docker-compose logs wiremock # View WireMock logs
59+
```
60+
61+
## Module Architecture
62+
63+
### Configuration Options
64+
65+
The module accepts the following configuration in `codeception.yml`:
66+
67+
```yaml
68+
modules:
69+
enabled:
70+
- \JasonBenett\CodeceptionModuleWiremock\Module\Wiremock:
71+
host: localhost # WireMock host (default: 127.0.0.1)
72+
port: 8080 # WireMock port (default: 8080)
73+
protocol: http # Protocol (default: http)
74+
timeout: 10.0 # Request timeout in seconds (default: 10.0)
75+
cleanupBefore: test # When to cleanup: 'never', 'test', or 'suite' (default: test)
76+
preserveFileMappings: true # Keep file-based stubs on reset (default: true)
77+
verifySSL: true # Verify SSL certificates (default: true)
78+
adminPath: /__admin # Admin API path (default: /__admin)
79+
```
80+
81+
### Public Methods (MVP)
82+
83+
#### Setup Methods (have*)
84+
- `haveHttpStubFor(string $method, string $url, int $status = 200, $body = '', array $headers = [], array $requestMatchers = []): string` - Create stub for any HTTP method
85+
86+
#### Assertion Methods (see*)
87+
- `seeHttpRequest(string $method, string $url, array $additionalMatchers = []): void` - Verify request was made
88+
- `dontSeeHttpRequest(string $method, string $url, array $additionalMatchers = []): void` - Verify request was NOT made
89+
- `seeRequestCount(int $count, array $requestPattern): void` - Assert exact request count
90+
91+
#### Data Retrieval Methods (grab*)
92+
- `grabRequestCount(array $requestPattern): int` - Get request count
93+
- `grabAllRequests(): array` - Get all recorded requests
94+
- `grabUnmatchedRequests(): array` - Get requests that didn't match any stub
95+
96+
#### Action Methods (send*)
97+
- `sendReset(): void` - Reset stubs to default (preserves file-based mappings)
98+
- `sendClearRequests(): void` - Clear request journal without affecting stubs
99+
100+
### Lifecycle Hooks
101+
102+
- `_initialize()` - Creates Guzzle HTTP client and verifies WireMock connectivity
103+
- `_beforeSuite()` - Cleanup if `cleanupBefore: suite`
104+
- `_before()` - Cleanup if `cleanupBefore: test` (default behavior)
105+
106+
### WireMock Admin API Endpoints Used
107+
108+
- `POST /__admin/mappings` - Create stub mapping
109+
- `POST /__admin/mappings/reset` - Reset to defaults
110+
- `POST /__admin/reset` - Full reset (mappings + requests)
111+
- `DELETE /__admin/requests` - Clear request journal
112+
- `POST /__admin/requests/count` - Count matching requests
113+
- `GET /__admin/requests` - Get all requests
114+
- `GET /__admin/requests/unmatched` - Get unmatched requests
115+
- `POST /__admin/near-misses/request` - Get near-miss analysis
116+
- `GET /__admin/health` - Health check
117+
118+
## Local Development
119+
120+
### Running Tests
121+
122+
1. Start WireMock server:
123+
```bash
124+
docker-compose up -d
125+
```
126+
127+
2. Wait for WireMock to be healthy:
128+
```bash
129+
docker-compose ps
130+
# Should show "healthy" status
131+
```
132+
133+
3. Run unit tests (don't require WireMock):
134+
```bash
135+
composer test
136+
```
137+
138+
4. Build Codeception support classes:
139+
```bash
140+
vendor/bin/codecept build
141+
```
142+
143+
5. Run functional tests (require WireMock):
144+
```bash
145+
composer test:functional
146+
```
147+
148+
### Debugging Tests
149+
150+
- Use `grabAllRequests()` to see all requests made
151+
- Use `grabUnmatchedRequests()` to see requests that didn't match any stub
152+
- Check WireMock logs: `docker-compose logs wiremock`
153+
- Near-miss analysis is automatically included in verification error messages
154+
155+
## Common Patterns
156+
157+
### Basic Stub Creation
158+
```php
159+
$I->haveHttpStubFor('GET', '/api/test', 200, 'Hello World');
160+
$I->seeHttpRequest('GET', '/api/test');
161+
```
162+
163+
### JSON Stub
164+
```php
165+
$I->haveHttpStubFor('GET', '/api/users/1', 200, [
166+
'id' => 1,
167+
'name' => 'John Doe'
168+
]);
169+
```
170+
171+
### POST Stub with Body Matching
172+
```php
173+
$I->haveHttpStubFor('POST', '/api/users', 201, ['success' => true], [], [
174+
'bodyPatterns' => [
175+
['equalToJson' => ['name' => 'Jane Doe']]
176+
]
177+
]);
178+
```
179+
180+
### Verify Request Count
181+
```php
182+
$I->seeRequestCount(3, ['method' => 'GET', 'url' => '/api/data']);
183+
```
184+
185+
### Debug Unmatched Requests
186+
```php
187+
$unmatched = $I->grabUnmatchedRequests();
188+
codecept_debug($unmatched);
189+
```
190+
191+
## Future Enhancements (Post-MVP)
192+
193+
- `haveDelayedStub()` - Simulate slow responses
194+
- `haveMultipleStubs()` - Bulk import stubs
195+
- `seeNoUnmatchedRequests()` - Assert all requests matched
196+
- `grabNearMisses()` - Explicit near-miss analysis
197+
- `grabStubMapping()` - Retrieve specific stub
198+
- `sendFullReset()` - Public method for complete reset
199+
- Scenario/state management support
200+
- Request templating support
201+
- File-based stub import helper

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2011-2024 Michael Bodnarchuk and contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

0 commit comments

Comments
 (0)