Skip to content

Commit 72ba693

Browse files
committed
complete feature of passing objects to constructor
completed test coverage
1 parent 8e42370 commit 72ba693

File tree

7 files changed

+148
-4
lines changed

7 files changed

+148
-4
lines changed

src/SpecBaseObject.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public function __construct(array $data)
9999
}
100100
$this->_properties[$property] = [];
101101
foreach ($data[$property] as $key => $item) {
102-
if ($type[1] === 'string') {
102+
if ($type[1] === Type::STRING) {
103103
if (!is_string($item)) {
104104
$this->_errors[] = "property '$property' must be map<string, string>, but entry '$key' is of type " . \gettype($item) . '.';
105105
}

src/spec/MediaType.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,17 @@ public function __construct(array $data)
5050

5151
if (!empty($encoding)) {
5252
foreach ($encoding as $property => $encodingData) {
53-
$encoding[$property] = new Encoding($encodingData, $this->schema->properties[$property] ?? null);
53+
if ($encodingData instanceof Encoding) {
54+
$encoding[$property] = $encodingData;
55+
} elseif (is_array($encodingData)) {
56+
$encoding[$property] = new Encoding($encodingData, $this->schema->properties[$property] ?? null);
57+
} else {
58+
$givenType = gettype($encodingData);
59+
if ($givenType === 'object') {
60+
$givenType = get_class($encodingData);
61+
}
62+
throw new TypeErrorException(sprintf('Encoding MUST be either array or Encoding object, "%s" given', $givenType));
63+
}
5464
}
5565
$this->encoding = $encoding;
5666
}

src/spec/Responses.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Responses implements SpecObjectInterface, DocumentContextInterface, ArrayA
3838

3939
/**
4040
* Create an object from spec data.
41-
* @param array[]|Response[]|Reference[] $data spec data read from YAML or JSON
41+
* @param Response[]|Reference[]|array[] $data spec data read from YAML or JSON
4242
* @throws TypeErrorException in case invalid data is supplied.
4343
*/
4444
public function __construct(array $data)

src/spec/Schema.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ public function __construct(array $data)
121121
$e
122122
);
123123
}
124+
} elseif (!($data['additionalProperties'] instanceof Schema || is_bool($data['additionalProperties']))) {
125+
$givenType = gettype($data['additionalProperties']);
126+
if ($givenType === 'object') {
127+
$givenType = get_class($data['additionalProperties']);
128+
}
129+
throw new TypeErrorException(sprintf('Schema::$additionalProperties MUST be either array, boolean or a Schema object, "%s" given', $givenType));
124130
}
125131
}
126132
parent::__construct($data);

tests/spec/MediaTypeTest.php

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,54 @@ public function testRead()
6464
$this->assertEquals($expectedCat, $mediaType->examples['cat']->value);
6565

6666
}
67-
}
67+
68+
public function testCreateionFromObjects()
69+
{
70+
$mediaType = new MediaType([
71+
'schema' => new \cebe\openapi\spec\Schema([
72+
'type' => \cebe\openapi\spec\Type::OBJECT,
73+
'properties' => [
74+
'id' => new \cebe\openapi\spec\Schema(['type' => 'string', 'format' => 'uuid']),
75+
'profileImage' => new \cebe\openapi\spec\Schema(['type' => 'string', 'format' => 'binary']),
76+
],
77+
]),
78+
'encoding' => [
79+
'id' => [],
80+
'profileImage' => new \cebe\openapi\spec\Encoding([
81+
'contentType' => 'image/png, image/jpeg',
82+
'headers' => [
83+
'X-Rate-Limit-Limit' => new \cebe\openapi\spec\Header([
84+
'description' => 'The number of allowed requests in the current period',
85+
'schema' => new \cebe\openapi\spec\Schema(['type' => 'integer']),
86+
]),
87+
],
88+
]),
89+
],
90+
]);
91+
92+
// default value should be extracted
93+
$this->assertEquals('text/plain', $mediaType->encoding['id']->contentType);
94+
// object should be passed.
95+
$this->assertInstanceOf(\cebe\openapi\spec\Encoding::class, $mediaType->encoding['profileImage']);
96+
}
97+
98+
public function badEncodingProvider()
99+
{
100+
yield [['encoding' => ['id' => 'foo']], 'Encoding MUST be either array or Encoding object, "string" given'];
101+
yield [['encoding' => ['id' => 42]], 'Encoding MUST be either array or Encoding object, "integer" given'];
102+
yield [['encoding' => ['id' => false]], 'Encoding MUST be either array or Encoding object, "boolean" given'];
103+
yield [['encoding' => ['id' => new stdClass()]], 'Encoding MUST be either array or Encoding object, "stdClass" given'];
104+
// The last one can be supported in future, but now SpecBaseObjects::__construct() requires array explicitly
105+
}
106+
107+
/**
108+
* @dataProvider badEncodingProvider
109+
*/
110+
public function testPathsCanNotBeCreatedFromBullshit($config, $expectedException)
111+
{
112+
$this->expectException(\cebe\openapi\exceptions\TypeErrorException::class);
113+
$this->expectExceptionMessage($expectedException);
114+
115+
new MediaType($config);
116+
}
117+
}

tests/spec/ResponseTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,35 @@ public function testResponseCodes()
162162
$this->assertFalse($result);
163163

164164
}
165+
166+
public function testCreateionFromObjects()
167+
{
168+
$responses = new Responses([
169+
200 => new Response(['description' => 'A list of pets.']),
170+
404 => ['description' => 'The pets list is gone 🙀'],
171+
]);
172+
173+
$this->assertSame('A list of pets.', $responses->getResponse(200)->description);
174+
$this->assertSame('The pets list is gone 🙀', $responses->getResponse(404)->description);
175+
}
176+
177+
public function badResponseProvider()
178+
{
179+
yield [['200' => 'foo'], 'Response MUST be either an array, a Response or a Reference object, "string" given'];
180+
yield [['200' => 42], 'Response MUST be either an array, a Response or a Reference object, "integer" given'];
181+
yield [['200' => false], 'Response MUST be either an array, a Response or a Reference object, "boolean" given'];
182+
yield [['200' => new stdClass()], 'Response MUST be either an array, a Response or a Reference object, "stdClass" given'];
183+
// The last one can be supported in future, but now SpecBaseObjects::__construct() requires array explicitly
184+
}
185+
186+
/**
187+
* @dataProvider badResponseProvider
188+
*/
189+
public function testPathsCanNotBeCreatedFromBullshit($config, $expectedException)
190+
{
191+
$this->expectException(\cebe\openapi\exceptions\TypeErrorException::class);
192+
$this->expectExceptionMessage($expectedException);
193+
194+
new Responses($config);
195+
}
165196
}

tests/spec/SchemaTest.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,51 @@ public function testDiscriminator()
134134
'monster' => 'https://gigantic-server.com/schemas/Monster/schema.json',
135135
], $schema->discriminator->mapping);
136136
}
137+
138+
public function testCreateionFromObjects()
139+
{
140+
$schema = new Schema([
141+
'allOf' => [
142+
new Schema(['type' => 'integer']),
143+
new Schema(['type' => 'string']),
144+
],
145+
'additionalProperties' => new Schema([
146+
'type' => 'object',
147+
]),
148+
'discriminator' => new Discriminator([
149+
'mapping' => ['A' => 'B'],
150+
]),
151+
]);
152+
153+
$this->assertSame('integer', $schema->allOf[0]->type);
154+
$this->assertSame('string', $schema->allOf[1]->type);
155+
$this->assertInstanceOf(Schema::class, $schema->additionalProperties);
156+
$this->assertSame('object', $schema->additionalProperties->type);
157+
$this->assertSame(['A' => 'B'], $schema->discriminator->mapping);
158+
}
159+
160+
161+
public function badSchemaProvider()
162+
{
163+
yield [['properties' => ['a' => 'foo']], 'Unable to instantiate cebe\openapi\spec\Schema Object with data \'foo\''];
164+
yield [['properties' => ['a' => 42]], 'Unable to instantiate cebe\openapi\spec\Schema Object with data \'42\''];
165+
yield [['properties' => ['a' => false]], 'Unable to instantiate cebe\openapi\spec\Schema Object with data \'\''];
166+
yield [['properties' => ['a' => new stdClass()]], "Unable to instantiate cebe\openapi\spec\Schema Object with data 'stdClass Object\n(\n)\n'"];
167+
168+
yield [['additionalProperties' => 'foo'], 'Schema::$additionalProperties MUST be either array, boolean or a Schema object, "string" given'];
169+
yield [['additionalProperties' => 42], 'Schema::$additionalProperties MUST be either array, boolean or a Schema object, "integer" given'];
170+
yield [['additionalProperties' => new stdClass()], 'Schema::$additionalProperties MUST be either array, boolean or a Schema object, "stdClass" given'];
171+
// The last one can be supported in future, but now SpecBaseObjects::__construct() requires array explicitly
172+
}
173+
174+
/**
175+
* @dataProvider badSchemaProvider
176+
*/
177+
public function testPathsCanNotBeCreatedFromBullshit($config, $expectedException)
178+
{
179+
$this->expectException(\cebe\openapi\exceptions\TypeErrorException::class);
180+
$this->expectExceptionMessage($expectedException);
181+
182+
new Schema($config);
183+
}
137184
}

0 commit comments

Comments
 (0)