Skip to content

Commit 74ac1f5

Browse files
committed
fixed cache support and refactored public API
1 parent d7d07fd commit 74ac1f5

File tree

3 files changed

+90
-30
lines changed

3 files changed

+90
-30
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ It converts HttpFoundation request and response objects to PSR-7 messages using
3030
## Installation
3131

3232
> [!NOTE]
33-
> This package is mostly intended to be used as part of an API test suite.
33+
> This package supports PHP 8.0 and above.
3434
3535
Via Composer:
3636

@@ -40,6 +40,9 @@ composer require --dev osteel/openapi-httpfoundation-testing
4040

4141
## Usage
4242

43+
> [!NOTE]
44+
> This package is mostly intended to be used as part of an API test suite.
45+
4346
Import the builder class:
4447

4548
```php
@@ -49,7 +52,7 @@ use Osteel\OpenApi\Testing\ValidatorBuilder;
4952
Use the builder to create a [`\Osteel\OpenApi\Testing\Validator`](/src/Validator.php) object, using one of the available factory methods for YAML or JSON:
5053

5154
```php
52-
// From a local file or URL:
55+
// From a local file:
5356

5457
$validator = ValidatorBuilder::fromYamlFile($yamlFile)->getValidator();
5558
$validator = ValidatorBuilder::fromJsonFile($jsonFile)->getValidator();
@@ -59,10 +62,15 @@ $validator = ValidatorBuilder::fromJsonFile($jsonFile)->getValidator();
5962
$validator = ValidatorBuilder::fromYamlString($yamlString)->getValidator();
6063
$validator = ValidatorBuilder::fromJsonString($jsonString)->getValidator();
6164

65+
// From a URL:
66+
67+
$validator = ValidatorBuilder::fromYamlUrl($yamlUrl)->getValidator();
68+
$validator = ValidatorBuilder::fromJsonUrl($jsonUrl)->getValidator();
69+
6270
// Automatic detection (slower):
6371

64-
$validator = ValidatorBuilder::fromYaml($yamlFileOrString)->getValidator();
65-
$validator = ValidatorBuilder::fromJson($jsonFileOrString)->getValidator();
72+
$validator = ValidatorBuilder::fromYaml($yamlFileOrStringOrUrl)->getValidator();
73+
$validator = ValidatorBuilder::fromJson($jsonFileOrStringOrUrl)->getValidator();
6674
```
6775

6876
> [!TIP]

src/ValidatorBuilder.php

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44

55
namespace Osteel\OpenApi\Testing;
66

7-
use cebe\openapi\Reader;
8-
use cebe\openapi\ReferenceContext;
97
use InvalidArgumentException;
108
use League\OpenAPIValidation\PSR7\ValidatorBuilder as BaseValidatorBuilder;
119
use Osteel\OpenApi\Testing\Adapters\HttpFoundationAdapter;
1210
use Osteel\OpenApi\Testing\Adapters\MessageAdapterInterface;
1311
use Osteel\OpenApi\Testing\Cache\CacheAdapterInterface;
1412
use Osteel\OpenApi\Testing\Cache\Psr16Adapter;
13+
use RuntimeException;
1514

1615
/**
1716
* This class creates Validator objects based on OpenAPI definitions.
@@ -35,9 +34,11 @@ public function __construct(private BaseValidatorBuilder $validatorBuilder)
3534
*/
3635
public static function fromYaml(string $definition): ValidatorBuilderInterface
3736
{
38-
return self::isUrl($definition) || is_file($definition)
39-
? self::fromYamlFile($definition)
40-
: self::fromYamlString($definition);
37+
return match (true) {
38+
self::isUrl($definition) => self::fromYamlUrl($definition),
39+
is_file($definition) => self::fromYamlFile($definition),
40+
default => self::fromYamlString($definition),
41+
};
4142
}
4243

4344
/**
@@ -47,9 +48,11 @@ public static function fromYaml(string $definition): ValidatorBuilderInterface
4748
*/
4849
public static function fromJson(string $definition): ValidatorBuilderInterface
4950
{
50-
return self::isUrl($definition) || is_file($definition)
51-
? self::fromJsonFile($definition)
52-
: self::fromJsonString($definition);
51+
return match (true) {
52+
self::isUrl($definition) => self::fromJsonUrl($definition),
53+
is_file($definition) => self::fromJsonFile($definition),
54+
default => self::fromJsonString($definition),
55+
};
5356
}
5457

5558
private static function isUrl(string $value): bool
@@ -70,7 +73,9 @@ private static function isUrl(string $value): bool
7073
*/
7174
public static function fromYamlFile(string $definition): ValidatorBuilderInterface
7275
{
73-
return self::fromMethod('readFromYamlFile', $definition);
76+
return self::isUrl($definition)
77+
? self::fromMethod('fromYamlUrl', $definition)
78+
: self::fromMethod('fromYamlFile', $definition);
7479
}
7580

7681
/**
@@ -80,7 +85,9 @@ public static function fromYamlFile(string $definition): ValidatorBuilderInterfa
8085
*/
8186
public static function fromJsonFile(string $definition): ValidatorBuilderInterface
8287
{
83-
return self::fromMethod('readFromJsonFile', $definition);
88+
return self::isUrl($definition)
89+
? self::fromMethod('fromJsonUrl', $definition)
90+
: self::fromMethod('fromJsonFile', $definition);
8491
}
8592

8693
/**
@@ -90,7 +97,7 @@ public static function fromJsonFile(string $definition): ValidatorBuilderInterfa
9097
*/
9198
public static function fromYamlString(string $definition): ValidatorBuilderInterface
9299
{
93-
return self::fromMethod('readFromYaml', $definition, resolveReferences: true);
100+
return self::fromMethod('fromYaml', $definition);
94101
}
95102

96103
/**
@@ -100,23 +107,59 @@ public static function fromYamlString(string $definition): ValidatorBuilderInter
100107
*/
101108
public static function fromJsonString(string $definition): ValidatorBuilderInterface
102109
{
103-
return self::fromMethod('readFromJson', $definition, resolveReferences: true);
110+
return self::fromMethod('fromJson', $definition);
104111
}
105112

106113
/**
107-
* Create a Validator object based on an OpenAPI definition.
114+
* @inheritDoc
108115
*
109-
* @param string $method the ValidatorBuilder object's method to use
110-
* @param string $definition the OpenAPI definition
111-
* @param bool $resolveReferences whether to resolve references in the definition
116+
* @param string $definition the OpenAPI definition's URL
117+
*
118+
* @throws InvalidArgumentException if the URL is invalid
119+
* @throws RuntimeException if the content of the URL cannot be read
112120
*/
113-
private static function fromMethod(string $method, string $definition, bool $resolveReferences = false): ValidatorBuilderInterface
121+
public static function fromYamlUrl(string $definition): ValidatorBuilderInterface
114122
{
115-
$specObject = Reader::{$method}($definition);
123+
return self::fromMethod('fromYaml', self::getUrlContent($definition));
124+
}
116125

117-
$resolveReferences && $specObject->resolveReferences(new ReferenceContext($specObject, '/'));
126+
/**
127+
* @inheritDoc
128+
*
129+
* @param string $definition the OpenAPI definition's URL
130+
*
131+
* @throws InvalidArgumentException if the URL is invalid
132+
* @throws RuntimeException if the content of the URL cannot be read
133+
*/
134+
public static function fromJsonUrl(string $definition): ValidatorBuilderInterface
135+
{
136+
return self::fromMethod('fromJson', self::getUrlContent($definition));
137+
}
118138

119-
$builder = (new BaseValidatorBuilder())->fromSchema($specObject);
139+
/**
140+
* @throws InvalidArgumentException if the URL is invalid
141+
* @throws RuntimeException if the content of the URL cannot be read
142+
*/
143+
private static function getUrlContent(string $url): string
144+
{
145+
self::isUrl($url) || throw new InvalidArgumentException(sprintf('Invalid URL: %s', $url));
146+
147+
if (($content = file_get_contents($url)) === false) {
148+
throw new RuntimeException(sprintf('Failed to read URL %s', $url));
149+
}
150+
151+
return $content;
152+
}
153+
154+
/**
155+
* Create a Validator object based on an OpenAPI definition.
156+
*
157+
* @param string $method the ValidatorBuilder object's method to use
158+
* @param string $definition the OpenAPI definition
159+
*/
160+
private static function fromMethod(string $method, string $definition): ValidatorBuilderInterface
161+
{
162+
$builder = (new BaseValidatorBuilder())->{$method}($definition);
120163

121164
return new ValidatorBuilder($builder);
122165
}

tests/ValidatorBuilderTest.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Osteel\OpenApi\Testing\Cache\CacheAdapterInterface;
1010
use Osteel\OpenApi\Testing\Validator;
1111
use Osteel\OpenApi\Testing\ValidatorBuilder;
12+
use Psr\SimpleCache\CacheInterface;
1213
use stdClass;
1314

1415
class ValidatorBuilderTest extends TestCase
@@ -17,17 +18,17 @@ public function definitionProvider(): array
1718
{
1819
return [
1920
['fromYaml', self::$yamlDefinition],
20-
['fromYaml', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.yaml'],
2121
['fromYaml', file_get_contents(self::$yamlDefinition)],
22+
['fromYaml', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.yaml'],
2223
['fromYamlFile', self::$yamlDefinition],
23-
['fromYamlFile', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.yaml'],
2424
['fromYamlString', file_get_contents(self::$yamlDefinition)],
25+
['fromYamlUrl', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.yaml'],
2526
['fromJson', self::$jsonDefinition],
26-
['fromJson', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.json'],
2727
['fromJson', file_get_contents(self::$jsonDefinition)],
28+
['fromJson', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.json'],
2829
['fromJsonFile', self::$jsonDefinition],
29-
['fromJsonFile', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.json'],
3030
['fromJsonString', file_get_contents(self::$jsonDefinition)],
31+
['fromJsonUrl', 'https://raw.githubusercontent.com/osteel/openapi-httpfoundation-testing/refs/heads/main/tests/stubs/example.json'],
3132
];
3233
}
3334

@@ -46,7 +47,15 @@ public function test_it_builds_a_validator(string $method, string $definition)
4647
$this->assertTrue($result->get($response, static::PATH));
4748
}
4849

49-
public function test_it_does_not_set_the_adapter_because_its_type_is_invalid()
50+
/** @dataProvider definitionProvider */
51+
public function test_it_sets_the_cache(string $method, string $definition)
52+
{
53+
ValidatorBuilder::$method($definition)->setCache($this->createMock(CacheInterface::class))->getValidator();
54+
55+
$this->addToAssertionCount(1);
56+
}
57+
58+
public function test_it_does_not_set_the_message_adapter_because_its_type_is_invalid()
5059
{
5160
$this->expectException(InvalidArgumentException::class);
5261
$this->expectExceptionMessage(sprintf(
@@ -58,7 +67,7 @@ public function test_it_does_not_set_the_adapter_because_its_type_is_invalid()
5867
ValidatorBuilder::fromYaml(self::$yamlDefinition)->setMessageAdapter(stdClass::class);
5968
}
6069

61-
public function test_it_sets_the_adapter()
70+
public function test_it_sets_the_message_adapter()
6271
{
6372
ValidatorBuilder::fromYaml(self::$yamlDefinition)
6473
->setMessageAdapter($this->createMock(MessageAdapterInterface::class)::class);

0 commit comments

Comments
 (0)