Skip to content

Commit 6db4fa5

Browse files
committed
feat: initial implementation of PHP OpenAPI mock server with Mezzio, Codeception tests, and AI reporting
0 parents  commit 6db4fa5

26 files changed

Lines changed: 10793 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
on:
2+
push:
3+
branches:
4+
- "main"
5+
pull_request:
6+
7+
name: "CI"
8+
9+
permissions:
10+
contents: read
11+
12+
env:
13+
PHP_VERSION: "8.3"
14+
15+
jobs:
16+
configuration:
17+
name: "Configuration"
18+
runs-on: "ubuntu-latest"
19+
outputs:
20+
php-version: ${{ steps.determine-php-version.outputs.php-version }}
21+
steps:
22+
- name: "Determine PHP version"
23+
id: "determine-php-version"
24+
run: "echo \"php-version=${{ env.PHP_VERSION }}\" >> $GITHUB_OUTPUT"
25+
26+
qa:
27+
name: "QA (lint + static analysis)"
28+
if: "!startsWith(github.event.head_commit.message, 'chore(release)')"
29+
runs-on: "ubuntu-latest"
30+
steps:
31+
- name: "Checkout"
32+
uses: "actions/checkout@v4"
33+
34+
- name: "Install PHP"
35+
uses: "shivammathur/setup-php@v2"
36+
with:
37+
coverage: "none"
38+
php-version: "${{ env.PHP_VERSION }}"
39+
40+
- name: "Validate composer.json and composer.lock"
41+
run: "composer validate --ansi --strict"
42+
43+
- name: "Install dependencies with composer"
44+
run: "composer install --no-interaction --no-progress"
45+
46+
- name: "Build Codeception"
47+
run: "vendor/bin/codecept build"
48+
49+
- name: "Check coding style"
50+
run: "composer cs:check"
51+
52+
- name: "Run static analysis"
53+
run: "composer stan"
54+
55+
tests:
56+
name: "Run codeception tests"
57+
needs: [ configuration, qa ]
58+
runs-on: "ubuntu-latest"
59+
strategy:
60+
matrix:
61+
include:
62+
- { php-version: "8.3", dependencies: locked, with_coverage: false }
63+
- { php-version: "8.4", dependencies: highest, with_coverage: false }
64+
steps:
65+
- name: "Checkout"
66+
uses: "actions/checkout@v4"
67+
68+
- name: "Install PHP"
69+
uses: "shivammathur/setup-php@v2"
70+
with:
71+
coverage: "none"
72+
ini-values: display_errors=On, display_startup_errors=On, error_reporting=32767
73+
php-version: "${{ matrix.php-version }}"
74+
75+
- name: "Install dependencies with composer"
76+
run: "composer update --no-interaction --no-progress"
77+
78+
- name: "Run Tests"
79+
run: |
80+
vendor/bin/codecept build
81+
vendor/bin/codecept run --report

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/vendor/
2+
/tests/_output/*
3+
!.gitkeep
4+
5+
.env
6+
.env.local
7+
.env.testing
8+
9+
.idea/
10+
.vscode/
11+
12+
.php-cs-fixer.cache
13+
.phpunit.result.cache

.php-cs-fixer.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
5+
6+
$finder = PhpCsFixer\Finder::create()
7+
->in(
8+
[
9+
__DIR__ . '/public',
10+
__DIR__ . '/tests',
11+
]
12+
)
13+
->exclude('_generated')
14+
->append(
15+
[
16+
__FILE__,
17+
]
18+
)
19+
;
20+
$rules = [
21+
/** symfony set @see \PhpCsFixer\RuleSet\Sets\PSR12Set */
22+
'@PSR12' => true,
23+
/** symfony set @see \PhpCsFixer\RuleSet\Sets\SymfonySet */
24+
'@Symfony' => true,
25+
/** symfony set @see \PhpCsFixer\RuleSet\Sets\SymfonyRiskySet */
26+
'@Symfony:risky' => true,
27+
'@PhpCsFixer:risky' => true,
28+
'@PHP8x3Migration' => true,
29+
'@DoctrineAnnotation' => true,
30+
'binary_operator_spaces' => [
31+
'default' => 'align',
32+
'operators' => [
33+
'??' => 'single_space',
34+
],
35+
],
36+
'concat_space' => ['spacing' => 'one'],
37+
38+
'encoding' => true,
39+
'blank_lines_before_namespace' => true,
40+
'blank_line_after_opening_tag' => false, // psr 12 = true
41+
'strict_param' => true,
42+
'no_useless_else' => true,
43+
'no_useless_return' => true,
44+
'modernize_types_casting' => true,
45+
'declare_strict_types' => true,
46+
'dir_constant' => true,
47+
48+
'php_unit_dedicate_assert' => ['target' => 'newest'],
49+
'combine_nested_dirname' => true,
50+
51+
'ordered_imports' => [
52+
'sort_algorithm' => 'alpha',
53+
],
54+
55+
'global_namespace_import' => [
56+
'import_classes' => true,
57+
'import_functions' => true,
58+
'import_constants' => true,
59+
],
60+
61+
'phpdoc_to_comment' => false,
62+
'nullable_type_declaration_for_default_null_value' => true,
63+
// prevent mega diff
64+
'blank_line_between_import_groups' => false, // PSR 12 = true
65+
];
66+
67+
$config = new PhpCsFixer\Config('webproject-style');
68+
$config->setRules($rules);
69+
$config->setUsingCache(true);
70+
$config->setLineEnding("\n");
71+
$config->setRiskyAllowed(true);
72+
$config->setParallelConfig(ParallelConfigFactory::detect());
73+
$config->setFinder($finder);
74+
$config->setUnsupportedPhpVersionAllowed(true);
75+
76+
return $config;

README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# PHP OpenAPI Mock Server
2+
3+
[![CI](https://github.com/WebProject-xyz/php-openapi-mock-server/actions/workflows/ci.yml/badge.svg)](https://github.com/WebProject-xyz/php-openapi-mock-server/actions/workflows/ci.yml)
4+
[![PHP Version](https://img.shields.io/badge/php-%5E8.3-blue.svg)](https://www.php.net/)
5+
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6+
7+
> **A lightweight, zero-docker OpenAPI mock server built with Mezzio.**
8+
9+
This project provides a standalone PHP application that serves mock data based on an OpenAPI 3.x specification. It's designed for rapid prototyping, frontend development, and CI environments where you want to avoid the overhead of Docker.
10+
11+
---
12+
13+
## Features
14+
15+
- **PSR-15 Compliant:** Built on the robust [Mezzio](https://docs.mezzio.dev/) middleware stack.
16+
- **Zero-Docker:** Runs on the standard PHP built-in web server.
17+
- **Dynamic Spec Loading:** Point to any OpenAPI spec file (local or URL) via environment variables.
18+
- **Automatic Data Generation:** Uses [php-openapi-faker](https://github.com/canvural/php-openapi-faker) to generate realistic data when examples are missing.
19+
- **Problem Details:** Structured error responses using the [RFC 7807](https://tools.ietf.org/html/rfc7807) (Problem Details for HTTP APIs) standard.
20+
- **CI Ready:** Includes Codeception acceptance tests and GitHub Actions workflow.
21+
22+
---
23+
24+
## Installation
25+
26+
```bash
27+
git clone https://github.com/WebProject-xyz/php-openapi-mock-server.git
28+
cd php-openapi-mock-server
29+
composer install
30+
```
31+
32+
Requires PHP `^8.3`.
33+
34+
---
35+
36+
## Usage
37+
38+
### Start the Server
39+
40+
Run the PHP built-in server from the project root:
41+
42+
```bash
43+
php -S localhost:8080 -t public
44+
```
45+
46+
The server will now be available at `http://localhost:8080`.
47+
48+
### Use a Custom Spec
49+
50+
You can specify a different OpenAPI file (local path or URL) using the `OPENAPI_SPEC` environment variable. Both **YAML** and **JSON** formats are supported:
51+
52+
```bash
53+
# Using a JSON spec
54+
OPENAPI_SPEC=data/openapi.json php -S localhost:8080 -t public
55+
56+
# Using a remote YAML spec
57+
OPENAPI_SPEC=https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.yaml php -S localhost:8080 -t public
58+
```
59+
60+
### Enable/Disable Mocking
61+
62+
By default, the server is forced into "mock mode" for all requests. You can explicitly control this using the `X-OpenApi-Mock-Active` header:
63+
64+
- `X-OpenApi-Mock-Active: true` (default)
65+
- `X-OpenApi-Mock-Active: false` (falls through to Mezzio handlers)
66+
67+
---
68+
69+
## Testing
70+
71+
The project uses [Codeception](https://codeception.com) for acceptance testing. The server is automatically started and stopped during the test run.
72+
73+
```bash
74+
composer test:build # rebuild Codeception actor classes
75+
composer test # run tests
76+
composer stan # PHPStan static analysis
77+
composer cs:check # check code style
78+
composer cs:fix # auto-fix code style
79+
```
80+
81+
---
82+
83+
## Project Structure
84+
85+
- `public/index.php`: The entry point and middleware pipeline configuration.
86+
- `data/openapi.yaml`: The default OpenAPI specification file.
87+
- `tests/`: Codeception acceptance tests.
88+
- `.github/workflows/ci.yml`: GitHub Actions CI configuration.
89+
90+
---
91+
92+
## Contributing
93+
94+
Contributions are welcome! Please feel free to submit a Pull Request.
95+
96+
---
97+
98+
## License
99+
100+
MIT

codeception.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
namespace: WebProject\PhpOpenApiMockServer\Tests
2+
support_namespace: Support
3+
# suite config
4+
suites:
5+
Acceptance:
6+
actor: AcceptanceTester
7+
path: Acceptance
8+
extensions:
9+
enabled:
10+
- Codeception\Extension\RunProcess:
11+
- php -S localhost:8080 -t public
12+
modules:
13+
enabled:
14+
- PhpBrowser:
15+
url: http://localhost:8080
16+
- REST:
17+
depends: PhpBrowser
18+
- Asserts
19+
JsonAcceptance:
20+
actor: AcceptanceTester
21+
path: JsonAcceptance
22+
extensions:
23+
enabled:
24+
- Codeception\Extension\RunProcess:
25+
- OPENAPI_SPEC=data/openapi.json php -S localhost:8081 -t public
26+
modules:
27+
enabled:
28+
- PhpBrowser:
29+
url: http://localhost:8081
30+
- REST:
31+
depends: PhpBrowser
32+
- Asserts
33+
RemoteAcceptance:
34+
actor: AcceptanceTester
35+
path: RemoteAcceptance
36+
extensions:
37+
enabled:
38+
- Codeception\Extension\RunProcess:
39+
- OPENAPI_SPEC=https://raw.githubusercontent.com/Redocly/openapi-template/gh-pages/openapi.yaml php -S localhost:8082 -t public
40+
modules:
41+
enabled:
42+
- PhpBrowser:
43+
url: http://localhost:8082
44+
- REST:
45+
depends: PhpBrowser
46+
- Asserts
47+
FailureAcceptance:
48+
actor: AcceptanceTester
49+
path: FailureAcceptance
50+
extensions:
51+
enabled:
52+
- Codeception\Extension\RunProcess:
53+
- OPENAPI_SPEC=https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/non-existent.yaml php -S localhost:8083 -t public
54+
modules:
55+
enabled:
56+
- PhpBrowser:
57+
url: http://localhost:8083
58+
- REST:
59+
depends: PhpBrowser
60+
- Asserts
61+
62+
extensions:
63+
enabled:
64+
- Codeception\Extension\RunFailed
65+
- Codeception\Extension\RunProcess:
66+
- php -S localhost:8080 -t public
67+
- OPENAPI_SPEC=data/openapi.json php -S localhost:8081 -t public
68+
- OPENAPI_SPEC=https://raw.githubusercontent.com/Redocly/openapi-template/gh-pages/openapi.yaml php -S localhost:8082 -t public
69+
- OPENAPI_SPEC=https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/non-existent.yaml php -S localhost:8083 -t public
70+
- WebProject\Codeception\Module\AiReporter\Extension\AiReporter:
71+
format: both
72+
output: tests/_output
73+
max_frames: 8
74+
include_steps: true
75+
include_artifacts: true
76+
compact_paths: true
77+
78+
params:
79+
- env
80+
81+
gherkin: []
82+
83+
# additional paths
84+
paths:
85+
tests: tests
86+
output: tests/_output
87+
data: tests/Support/Data
88+
support: tests/Support
89+
envs: tests/_envs
90+
91+
settings:
92+
shuffle: false
93+
lint: true
94+
95+
coverage:
96+
enabled: true
97+
include:
98+
- public/*
99+
exclude:
100+
- tests/*

0 commit comments

Comments
 (0)