From 5b53512400c94e600d0dd03f57c0c422828e31e9 Mon Sep 17 00:00:00 2001 From: elb98rm Date: Fri, 26 Mar 2021 13:17:48 +0000 Subject: [PATCH] Ongoing refactoring to use JsonApi Objects throughout codebase. --- src/Models/Error.php | 268 ++++++++++++++++++++++++++++ src/Models/JsonApiFormatter.php | 83 +++++++-- src/Models/Link.php | 64 +++++++ src/Models/Links.php | 107 +++++++++++ src/Models/Meta.php | 63 +++++++ tests/Unit/ErrorTest.php | 116 ++++++++++++ tests/Unit/JsonApiFormatterTest.php | 152 ++++++++-------- tests/Unit/LinkTest.php | 72 ++++++++ tests/Unit/LinksTest.php | 153 ++++++++++++++++ tests/Unit/MetaTest.php | 72 ++++++++ 10 files changed, 1062 insertions(+), 88 deletions(-) create mode 100644 src/Models/Error.php create mode 100644 src/Models/Link.php create mode 100644 src/Models/Links.php create mode 100644 src/Models/Meta.php create mode 100644 tests/Unit/ErrorTest.php create mode 100644 tests/Unit/LinkTest.php create mode 100644 tests/Unit/LinksTest.php create mode 100644 tests/Unit/MetaTest.php diff --git a/src/Models/Error.php b/src/Models/Error.php new file mode 100644 index 0000000..57dccd4 --- /dev/null +++ b/src/Models/Error.php @@ -0,0 +1,268 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Models; + +/** + * Class Error + * + * Class to offer methods/properties to prepare data for an Error + * These are set to the v1.0 specification, defined at https://jsonapi.org/format/ + * + * @category None + * @package Floor9design\JsonApiFormatter\Models + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @link https://jsonapi.org/ + * @link https://jsonapi-validator.herokuapp.com/ + * @since File available since Release 1.0 + * @see https://jsonapi.org/format/ + */ +class Error +{ + // Properties + + /** + * @var string|null + */ + var ?string $id = null; + + /** + * @var Links|null + */ + var ?Links $links = null; + + /** + * @var string|null + */ + var ?string $status = null; + + /** + * @var string|null + */ + var ?string $code = null; + + /** + * @var string|null + */ + var ?string $title = null; + + /** + * @var string|null + */ + var ?string $detail = null; + + /** + * @var object|null + */ + var ?object $source = null; + + // accessors + + /** + * @return string|null + * @see $id + */ + public function getId(): ?string + { + return $this->id; + } + + /** + * @param string|null $id + * @return Error + * @see $id + */ + public function setId(?string $id): Error + { + $this->id = $id; + return $this; + } + + /** + * @return Links|null + * @see $links + */ + public function getLinks(): ?Links + { + return $this->links; + } + + /** + * @param Links|null $links + * @return Error + * @see $links + */ + public function setLinks(?Links $links): Error + { + $this->links = $links; + return $this; + } + + /** + * @return string|null + * @see $status + */ + public function getStatus(): ?string + { + return $this->status; + } + + /** + * @param string|null $status + * @return Error + * @see $status + */ + public function setStatus(?string $status): Error + { + $this->status = $status; + return $this; + } + + /** + * @return string|null + * @see $code + */ + public function getCode(): ?string + { + return $this->code; + } + + /** + * @param string|null $code + * @return Error + * @see $code + */ + public function setCode(?string $code): Error + { + $this->code = $code; + return $this; + } + + /** + * @return string|null + * @see $title + */ + public function getTitle(): ?string + { + return $this->title; + } + + /** + * @param string|null $title + * @return Error + * @see $title + */ + public function setTitle(?string $title): Error + { + $this->title = $title; + return $this; + } + + /** + * @return string|null + * @see $detail + */ + public function getDetail(): ?string + { + return $this->detail; + } + + /** + * @param string|null $detail + * @return Error + * @see $detail + */ + public function setDetail(?string $detail): Error + { + $this->detail = $detail; + return $this; + } + + /** + * @return object|null + * @see $source + */ + public function getSource(): ?object + { + return $this->source; + } + + /** + * @param object|null $source + * @return Error + * @see $source + */ + public function setSource(?object $source): Error + { + $this->source = $source; + return $this; + } + + // constructor + + /** + * Error constructor. + * @param string|null $id + * @param Links|null $links + * @param string|null $status + * @param string|null $code + * @param string|null $title + * @param string|null $detail + * @param string|null $source + */ + public function __construct( + ?string $id = null, + ?Links $links = null, + ?string $status = null, + ?string $code = null, + ?string $title = null, + ?string $detail = null, + ?object $source = null + ) { + $this + ->setId($id) + ->setLinks($links) + ->setStatus($status) + ->setCode($code) + ->setTitle($title) + ->setDetail($detail) + ->setSource($source); + } + + /** + * @return array + */ + public function toArray(): array + { + return [ + 'id' => $this->getId(), + 'links' => $this->getLinks(), + 'status' => $this->getStatus(), + 'code' => $this->getCode(), + 'title' => $this->getTitle(), + 'detail' => $this->getDetail(), + 'source' => $this->getSource(), + ]; + } + +} diff --git a/src/Models/JsonApiFormatter.php b/src/Models/JsonApiFormatter.php index 6355060..b1d8186 100644 --- a/src/Models/JsonApiFormatter.php +++ b/src/Models/JsonApiFormatter.php @@ -166,9 +166,17 @@ public function getErrors(): ?array * * @param array $errors * @return JsonApiFormatter + * @throws JsonApiFormatterException */ public function setErrors(array $errors): JsonApiFormatter { + foreach ($errors as $error) { + if (!$error instanceof Error) { + $error_message = '$errors needs to be an array of Error objects'; + throw new JsonApiFormatterException($error_message); + } + } + $this->base_response_array['errors'] = $errors; return $this; } @@ -177,11 +185,17 @@ public function setErrors(array $errors): JsonApiFormatter * Fluently adds error to $base_response_array['errors'] * @param array $extra_errors * @return JsonApiFormatter + * @throws JsonApiFormatterException */ public function addErrors(array $extra_errors): JsonApiFormatter { $errors = $this->getErrors() ?? []; foreach ($extra_errors as $error) { + if (!$error instanceof Error) { + $error_message = '$errors needs to be an array of Error objects'; + throw new JsonApiFormatterException($error_message); + } + $errors[] = $error; } @@ -202,7 +216,7 @@ public function unsetErrors(): JsonApiFormatter /** * @return null|stdClass */ - public function getMeta(): ?stdClass + public function getMeta(): ?Meta { return $this->getBaseResponseArray()['meta'] ?? null; } @@ -213,7 +227,7 @@ public function getMeta(): ?stdClass * @param stdClass $meta * @return JsonApiFormatter */ - public function setMeta(stdClass $meta): JsonApiFormatter + public function setMeta(Meta $meta): JsonApiFormatter { $this->base_response_array['meta'] = $meta; return $this; @@ -226,15 +240,15 @@ public function setMeta(stdClass $meta): JsonApiFormatter * @return JsonApiFormatter * @throws JsonApiFormatterException */ - public function addMeta(array $extra_meta, bool $overwrite = false): JsonApiFormatter + public function addMeta(Meta $extra_meta, bool $overwrite = false): JsonApiFormatter { $meta = $this->getMeta(); if (!$meta) { - $meta = new stdClass(); + $meta = new Meta(); } // catch duplicates - foreach ($extra_meta as $key => $new_meta) { + foreach ($extra_meta->toArray() as $key => $new_meta) { if (!$overwrite && property_exists($meta, $key)) { throw new JsonApiFormatterException( 'The meta provided clashes with existing meta - it should be added manually' @@ -295,7 +309,7 @@ public function autoIncludeJsonapi(): JsonApiFormatter /** * @return null|array */ - public function getLinks(): ?stdClass + public function getLinks(): ?Links { return $this->getBaseResponseArray()['links'] ?? null; } @@ -306,7 +320,7 @@ public function getLinks(): ?stdClass * @param stdClass $links * @return JsonApiFormatter */ - public function setLinks(stdClass $links): JsonApiFormatter + public function setLinks(Links $links): JsonApiFormatter { $this->base_response_array['links'] = $links; return $this; @@ -321,17 +335,17 @@ public function setLinks(stdClass $links): JsonApiFormatter */ public function addLinks(array $extra_links, bool $overwrite = false): JsonApiFormatter { - $links = $this->getLinks() ?? new stdClass(); + $links = $this->getLinks() ?? new Links(); // catch duplicates - foreach ($extra_links as $key => $new_link) { - if (!$overwrite && property_exists($links, $key)) { + foreach ($extra_links as $name => $new_link) { + if (!$overwrite && property_exists($links, $name)) { throw new JsonApiFormatterException( 'The link provided clashes with existing links - it should be added manually' ); } - $links->$key = $new_link; + $links->addLink($name, $new_link); } $this->setLinks($links); @@ -398,9 +412,9 @@ public function addIncluded(array $extra_included): JsonApiFormatter * @param stdClass|null $links */ public function __construct( - ?stdClass $meta = null, + ?Meta $meta = null, ?stdClass $json_api = null, - ?stdClass $links = null + ?Links $links = null ) { // Cant form an object before instantiation, so do it here: $this->base_response_array['jsonapi'] = (object)['version' => '1.0']; @@ -408,7 +422,7 @@ public function __construct( if ($meta ?? false) { $this->setMeta($meta); } else { - $this->setMeta((object)['status' => null]); + $this->setMeta(new Meta(['status' => null])); } if ($json_api ?? false) { @@ -479,7 +493,6 @@ public function import(string $json): JsonApiFormatter // attempt to set up data if ($decoded_json['data'] ?? false) { - // validate it $this->quickValidatorDataResourceArray($decoded_json['data']); @@ -494,7 +507,7 @@ public function import(string $json): JsonApiFormatter ); } else { // array - foreach($decoded_json['data'] as $datum) { + foreach ($decoded_json['data'] as $datum) { $this->addData( new DataResource( $datum['id'], @@ -508,12 +521,46 @@ public function import(string $json): JsonApiFormatter // attempt to set up errors if ($decoded_json['errors'] ?? false) { - $this->setErrors($decoded_json['errors']); + $errors = []; + + foreach ($decoded_json['errors'] as $error) { + // import links + if ($error['links'] ?? null) { + $links = new Links(); + + foreach ($error['links'] as $link) { + if (is_string($link)) { + $links[] = $link; + } else { + $new_link = new Link($link); + $links[] = $new_link; + } + } + } + + // format source + $source = $error['source'] ?? null; + if ($source) { + $source = (object)$source; + } + + $errors[] = new Error( + $error['id'] ?? null, + $links ?? null, + $error['status'] ?? null, + $error['code'] ?? null, + $error['title'] ?? null, + $error['detail'] ?? null, + $source + ); + } + + $this->setErrors($errors); } // attempt to set up meta if ($decoded_json['meta'] ?? false) { - $this->setMeta((object)$decoded_json['meta']); + $this->setMeta(new Meta($decoded_json['meta'])); } // attempt to set up included diff --git a/src/Models/Link.php b/src/Models/Link.php new file mode 100644 index 0000000..dcd3881 --- /dev/null +++ b/src/Models/Link.php @@ -0,0 +1,64 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Models; + +/** + * Class Link + * + * Class to offer methods/properties to prepare data for a Link object + * These are set to the v1.0 specification, defined at https://jsonapi.org/format/ + * + * @category None + * @package Floor9design\JsonApiFormatter\Models + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @link https://jsonapi.org/ + * @link https://jsonapi-validator.herokuapp.com/ + * @since File available since Release 1.0 + * @see https://jsonapi.org/format/ + */ +class Link +{ + // constructor + + /** + * Link constructor. + * Automatically sets up the provided array as properties + * @param array|null $array + */ + public function __construct(?array $array = []) + { + foreach ($array as $property => $value) { + $this->$property = $value; + } + } + + /** + * @return array + */ + public function toArray(): array + { + return (array)$this; + } + +} diff --git a/src/Models/Links.php b/src/Models/Links.php new file mode 100644 index 0000000..dd51ef6 --- /dev/null +++ b/src/Models/Links.php @@ -0,0 +1,107 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Models; + +use Floor9design\JsonApiFormatter\Exceptions\JsonApiFormatterException; + +/** + * Class Links + * + * Class to offer methods/properties to prepare data for a Links object + * These are set to the v1.0 specification, defined at https://jsonapi.org/format/ + * + * Note: links should be populated by either a Link object or a string + * + * @category None + * @package Floor9design\JsonApiFormatter\Models + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @link https://jsonapi.org/ + * @link https://jsonapi-validator.herokuapp.com/ + * @since File available since Release 1.0 + * @see https://jsonapi.org/format/ + */ +class Links +{ + // constructor + + /** + * Links constructor. + * Automatically sets up the provided array as properties + * @param array|null $array + * @throws JsonApiFormatterException + */ + public function __construct(?array $array = []) + { + foreach ($array as $name => $link) { + $this->addLink($name, $link); + } + } + + /** + * @param string $name + * @param string|Link $link + * @throws JsonApiFormatterException + */ + public function addLink(string $name, $link) + { + // validate: + $this->validateProperty($link); + $this->$name = $link; + } + + /** + * @param string $name + * @param string|Link $link + * @throws JsonApiFormatterException + */ + public function unsetLink(string $name) + { + unset($this->$name); + } + + /** + * @return array + */ + public function toArray(): array + { + return (array)$this; + } + + /** + * @param $value + * @return bool + * @throws JsonApiFormatterException + */ + private function validateProperty($value): bool + { + if ( + !($value instanceof Link || is_string($value)) + ) { + throw new JsonApiFormatterException('Links can only be populated with strings or Link objects'); + } + + return true; + } + +} diff --git a/src/Models/Meta.php b/src/Models/Meta.php new file mode 100644 index 0000000..a0ed3c9 --- /dev/null +++ b/src/Models/Meta.php @@ -0,0 +1,63 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Models; + +/** + * Class Meta + * + * Class to offer methods/properties to prepare data for a Meta object + * These are set to the v1.0 specification, defined at https://jsonapi.org/format/ + * + * @category None + * @package Floor9design\JsonApiFormatter\Models + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://www.floor9design.com + * @link https://jsonapi.org/ + * @link https://jsonapi-validator.herokuapp.com/ + * @since File available since Release 1.0 + * @see https://jsonapi.org/format/ + */ +class Meta +{ + // constructor + + /** + * Meta constructor. + * Automatically sets up the provided array as properties + * @param array|null $array + */ + public function __construct(?array $array= []) { + foreach($array as $property => $value) { + $this->$property = $value; + } + } + + /** + * @return array + */ + public function toArray(): array + { + return (array)$this; + } + +} diff --git a/tests/Unit/ErrorTest.php b/tests/Unit/ErrorTest.php new file mode 100644 index 0000000..a9728c0 --- /dev/null +++ b/tests/Unit/ErrorTest.php @@ -0,0 +1,116 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Tests\Unit; + +use Floor9design\JsonApiFormatter\Models\Error; +use Floor9design\JsonApiFormatter\Models\Links; +use Floor9design\TestDataGenerator\Generator; +use Floor9design\TestingTools\Exceptions\TestingToolsException; +use Floor9design\TestingTools\Traits\AccessorTesterTrait; +use PHPUnit\Framework\TestCase; +use StdClass; + +/** + * ErrorTest + * + * This test file tests the Error. + * + * @category None + * @package Floor9design\JsonApiFormatter\Tests\Unit + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + */ +class ErrorTest extends TestCase +{ + + use AccessorTesterTrait; + + // Accessors + + /** + * Test data accessors. + * + * @return void + * @throws TestingToolsException + */ + public function testBasicAccessors() + { + $error = new Error(); + + $this->accessorTestStrings( + [ + 'id' => [], + 'status' => [], + 'code' => [], + 'title' => [], + 'detail' => [] + ], + $error + ); + + $links = new Links(); + $error->setLinks($links); + $this->assertEquals($links, $error->getLinks()); + + $source = new StdClass(); + $error->setSource($source); + $this->assertEquals($source, $error->getSource()); + } + + + /** + * Test Error constructor. + * + * @return void + * @throws TestingToolsException + */ + public function testToArray() + { + $generator = new Generator(); + + $array = [ + 'id' => $generator->randomString(), + 'links' => new Links(), + 'status' => $generator->randomString(), + 'code' => $generator->randomString(), + 'title' => $generator->randomString(), + 'detail' => $generator->randomString(), + 'source' => new StdClass, + ]; + + $error = new Error( + $array['id'], + $array['links'], + $array['status'], + $array['code'], + $array['title'], + $array['detail'], + $array['source'] + ); + + $this->assertEquals($error->toArray(), $array); + } +} diff --git a/tests/Unit/JsonApiFormatterTest.php b/tests/Unit/JsonApiFormatterTest.php index 470e835..8216400 100644 --- a/tests/Unit/JsonApiFormatterTest.php +++ b/tests/Unit/JsonApiFormatterTest.php @@ -22,10 +22,13 @@ use Floor9design\JsonApiFormatter\Exceptions\JsonApiFormatterException; use Floor9design\JsonApiFormatter\Models\DataResource; +use Floor9design\JsonApiFormatter\Models\Error; use Floor9design\JsonApiFormatter\Models\JsonApiFormatter; +use Floor9design\JsonApiFormatter\Models\Links; +use Floor9design\JsonApiFormatter\Models\Meta; use PHPUnit\Framework\TestCase; use ReflectionClass; -use stdClass; +use StdClass; /** * JsonApiFormatterTest @@ -114,7 +117,7 @@ public function testDataAccessors() public function testDataAccessorsBadObject() { $json_api_formatter = new JsonApiFormatter(); - $test_bad_object = new \StdClass(); + $test_bad_object = new StdClass(); // Check bad data exception $this->expectException(JsonApiFormatterException::class); @@ -131,7 +134,7 @@ public function testDataAccessorsBadObject() public function testDataAccessorsBadArrayObject() { $json_api_formatter = new JsonApiFormatter(); - $test_bad_object = new \StdClass(); + $test_bad_object = new StdClass(); // Check bad data exception $this->expectException(JsonApiFormatterException::class); @@ -147,15 +150,15 @@ public function testDataAccessorsBadArrayObject() */ public function testErrorsAccessors() { - $error = new StdClass(); - $error->status = '400'; - $error->title = 'Bad request'; - $error->detail = 'The request was not formed well'; + $error = new Error(); + $error->setStatus('400'); + $error->setTitle('Bad request'); + $error->setDetail('The request was not formed well'); - $error2 = new StdClass(); - $error2->status = '400'; - $error2->title = 'Bad request 2'; - $error2->detail = 'The request was not formed well either'; + $error2 = new Error(); + $error2->setStatus('400'); + $error2->setTitle('Bad request 2'); + $error2->setDetail('The request was not formed well either'); $test_error = [$error]; $test_complete_errors = [$error, $error2]; @@ -187,23 +190,29 @@ public function testErrorsAccessors() */ public function testMetaAccessors() { - $test_default_meta = [ - 'status' => null - ]; + $test_default_meta = new Meta( + [ + 'status' => null + ] + ); - $test_partial_meta = [ - 'status' => '200' - ]; + $test_partial_meta = new Meta( + [ + 'status' => '200' + ] + ); - $test_complete_meta = [ - 'status' => '200', - 'info' => 'Request loaded in 34ms' - ]; + $test_complete_meta = new Meta( + [ + 'status' => '200', + 'info' => 'Request loaded in 34ms' + ] + ); $json_api_formatter = new JsonApiFormatter(); // check the default value - $this->assertEquals($json_api_formatter->getMeta(), (object)$test_default_meta); + $this->assertEquals($test_default_meta, $json_api_formatter->getMeta()); // Valid get and set $json_api_formatter->setMeta((object)$test_complete_meta); @@ -224,17 +233,17 @@ public function testMetaAccessors() // make a partial and extend $json_api_formatter->setMeta((object)$test_partial_meta); - $json_api_formatter->addMeta(['info' => 'Request loaded in 34ms']); + $json_api_formatter->addMeta(new Meta(['info' => 'Request loaded in 34ms'])); $this->assertEquals($json_api_formatter->getMeta(), (object)$test_complete_meta); // force add some meta - $json_api_formatter->addMeta(['info' => 'Request loaded in 34ms'], true); + $json_api_formatter->addMeta(new Meta(['info' => 'Request loaded in 34ms']), true); $this->assertEquals($json_api_formatter->getMeta(), (object)$test_complete_meta); // check that addMeta catches duplicates $this->expectException(JsonApiFormatterException::class); $this->expectExceptionMessage('The meta provided clashes with existing meta - it should be added manually'); - $json_api_formatter->addMeta(['info' => 'Request loaded in 34ms']); + $json_api_formatter->addMeta(new Meta(['info' => 'Request loaded in 34ms'])); } /** @@ -297,14 +306,14 @@ public function testIncludedAccessors() */ public function testLinksAccessors() { - $test_partial_links = (object)[ - 'self' => 'http://example.com/posts' - ]; + $test_partial_links = new Links(['self' => 'http://example.com/posts']); - $test_complete_links = (object)[ - 'self' => 'http://example.com/posts', - 'next' => 'http://example.com/more-posts' - ]; + $test_complete_links = new Links( + [ + 'self' => 'http://example.com/posts', + 'next' => 'http://example.com/more-posts' + ] + ); $json_api_formatter = new JsonApiFormatter(); @@ -348,16 +357,18 @@ public function testConstructor() $this->assertEquals($json_api_formatter->getContentType(), 'application/vnd.api+json'); $this->assertEquals($json_api_formatter->getData(), null); $this->assertEquals($json_api_formatter->getErrors(), []); - $this->assertEquals($json_api_formatter->getMeta(), (object)['status' => null]); + $this->assertEquals($json_api_formatter->getMeta(), new Meta(['status' => null])); $this->assertEquals($json_api_formatter->getJsonapi(), (object)['version' => '1.0']); $this->assertNull($json_api_formatter->getIncluded()); - $meta = (object)['hello' => 'world']; + $meta = new Meta(['hello' => 'world']); $json_api = (object)['application/vnd.api+jsonv2']; - $links = (object)[ - 'self' => 'http://example.com/posts', - 'next' => 'http://example.com/more-posts' - ]; + $links = new Links( + [ + 'self' => 'http://example.com/posts', + 'next' => 'http://example.com/more-posts' + ] + ); $json_api_formatter = new JsonApiFormatter( $meta, @@ -498,7 +509,7 @@ public function testDataResourceResponseObjectException() $this->expectException(JsonApiFormatterException::class); $this->expectExceptionMessage('$data_resources needs to be a data resource or array of data resources'); - $json_api_formatter->dataResourceResponse(new \StdCLass()); + $json_api_formatter->dataResourceResponse(new StdCLass()); } /** @@ -512,7 +523,7 @@ public function testDataResourceResponseArrayException() $this->expectException(JsonApiFormatterException::class); $this->expectExceptionMessage('$data_resources needs to be a data resource or array of data resources'); - $json_api_formatter->dataResourceResponse([new \StdCLass()]); + $json_api_formatter->dataResourceResponse([new StdCLass()]); } // Main functionality: error responses @@ -534,15 +545,15 @@ public function testErrorResponseException() */ public function testErrorResponse() { - $error = new StdClass(); - $error->status = '400'; - $error->title = 'Bad request'; - $error->detail = 'The request was not formed well'; + $error = new Error(); + $error->setStatus('400'); + $error->setTitle('Bad request'); + $error->setDetail('The request was not formed well'); - $error2 = new StdClass(); - $error2->status = '400'; - $error2->title = 'Bad request 2'; - $error2->detail = 'The request was not formed well either'; + $error2 = new Error(); + $error->setStatus('400'); + $error2->setTitle('Bad request 2'); + $error2->setDetail('The request was not formed well either'); $test_errors = [$error, $error2]; @@ -589,11 +600,11 @@ public function testExport() $data_attributes = ['test' => 'some_data']; $data = new DataResource($data_id, $data_type, $data_attributes); - $error = [ - 'status' => '400', - 'title' => 'Bad request', - 'detail' => 'The request was not formed well' - ]; + $error = new Error(); + $error + ->setStatus('400') + ->setTitle('Bad request') + ->setDetail('The request was not formed well'); // errors $json_api_formatter = new JsonApiFormatter(); @@ -627,10 +638,12 @@ public function testExport() // meta - $meta = (object)[ - 'status' => '200', - 'info' => 'Request loaded in 34ms' - ]; + $meta = new Meta( + [ + 'status' => '200', + 'info' => 'Request loaded in 34ms' + ] + ); $json_api_formatter = new JsonApiFormatter(); $json_api_formatter->unsetErrors(); @@ -663,11 +676,11 @@ public function testExportException() // Now add errors - $error = [ - 'status' => '400', - 'title' => 'Bad request', - 'detail' => 'The request was not formed well' - ]; + $error = new Error(); + $error + ->setStatus('400') + ->setTitle('Bad request') + ->setDetail('The request was not formed well'); // errors $json_api_formatter->addErrors([$error]); @@ -763,14 +776,13 @@ public function testImportDataArray() */ public function testImportErrors() { + $error = new Error(); + $error + ->setStatus('400') + ->setTitle('Bad request') + ->setDetail('The request was not formed well'); $json_array = [ - 'errors' => [ - [ - 'status' => '400', - 'title' => 'Bad request', - 'detail' => 'The request was not formed well', - ] - ], + 'errors' => [$error] ]; $errors_json = json_encode($json_array, true); @@ -804,7 +816,7 @@ public function testImportMeta() $json_api_formatter->import($meta_json); - $this->assertEquals($json_api_formatter->getMeta(), (object)$json_array['meta']); + $this->assertEquals($json_api_formatter->getMeta(), new Meta($json_array['meta'])); } // Main functionality : validation diff --git a/tests/Unit/LinkTest.php b/tests/Unit/LinkTest.php new file mode 100644 index 0000000..90d673b --- /dev/null +++ b/tests/Unit/LinkTest.php @@ -0,0 +1,72 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Tests\Unit; + +use Floor9design\JsonApiFormatter\Models\Link; +use Floor9design\TestingTools\Exceptions\TestingToolsException; +use PHPUnit\Framework\TestCase; + +/** + * LinkTest + * + * This test file tests the Link. + * + * @category None + * @package Floor9design\JsonApiFormatter\Tests\Unit + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + */ +class LinkTest extends TestCase +{ + // Accessors + + /** + * Test link constructor. + * + * @return void + * @throws TestingToolsException + */ + public function testConstructor() + { + $array = ['hello' => 'world']; + $link = new Link($array); + $this->assertEquals($link->hello, 'world'); + } + + /** + * Test link constructor. + * + * @return void + * @throws TestingToolsException + */ + public function testToArray() + { + $array = ['hello' => 'world']; + $link = new Link($array); + $this->assertEquals($link->toArray(), $array); + } + +} diff --git a/tests/Unit/LinksTest.php b/tests/Unit/LinksTest.php new file mode 100644 index 0000000..40ca697 --- /dev/null +++ b/tests/Unit/LinksTest.php @@ -0,0 +1,153 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Tests\Unit; + +use Floor9design\JsonApiFormatter\Exceptions\JsonApiFormatterException; +use Floor9design\JsonApiFormatter\Models\Link; +use Floor9design\JsonApiFormatter\Models\Links; +use Floor9design\TestingTools\Exceptions\TestingToolsException; +use PHPUnit\Framework\TestCase; + +/** + * LinksTest + * + * This test file tests the Links class. + * + * @category None + * @package Floor9design\JsonApiFormatter\Tests\Unit + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + */ +class LinksTest extends TestCase +{ + // Accessors + + /** + * Test link constructor. + * + * @return void + * @throws TestingToolsException + */ + public function testConstructor() + { + $array = ['hello' => 'world']; + $link = new Link($array); + $string = 'a string link'; + + $links = new Links( + [ + 'object' => $link, + 'string' => $string + ] + ); + + $this->assertEquals($link, $links->object); + $this->assertEquals($string, $links->string); + } + + /** + * Test addLinks + * + * @return void + * @throws TestingToolsException + */ + public function testAddLinks() + { + $array = ['hello' => 'world']; + $link = new Link($array); + $string = 'a string link'; + + $links = new Links(['object' => $link]); + $links->addLink('string', $string); + + $this->assertEquals($link, $links->object); + $this->assertEquals($string, $links->string); + } + + /** + * Test unsetLinks + * + * @return void + * @throws TestingToolsException + */ + public function testUnsetLinks() + { + $array = ['hello' => 'world']; + $link = new Link($array); + $string = 'a string link'; + + $links = new Links( + [ + 'object' => $link, + 'string' => $string + ] + ); + $links->unsetLink('string'); + + $this->assertEquals($link, $links->object); + $this->assertFalse(property_exists( $links, 'string')); + } + + /** + * Test unsetLinks + * + * @return void + * @throws TestingToolsException + */ + public function testToArray() + { + $array = ['hello' => 'world']; + $link = new Link($array); + $string = 'a string link'; + $object_array = [ + 'object' => $link, + 'string' => $string + ]; + + $links = new Links($object_array); + + $this->assertEquals($object_array, $links->toArray()); + } + + /** + * Test addLinks + * + * @return void + * @throws TestingToolsException + */ + public function testValidate() + { + $array = ['hello' => 'world']; + $link = new Link($array); + $bad_string = 2; + + $links = new Links(['object' => $link]); + $this->expectException(JsonApiFormatterException::class); + $this->expectExceptionMessage('Links can only be populated with strings or Link objects'); + $links->addLink('string', $bad_string); + } + +} diff --git a/tests/Unit/MetaTest.php b/tests/Unit/MetaTest.php new file mode 100644 index 0000000..36a7036 --- /dev/null +++ b/tests/Unit/MetaTest.php @@ -0,0 +1,72 @@ + + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + * + */ + +namespace Floor9design\JsonApiFormatter\Tests\Unit; + +use Floor9design\JsonApiFormatter\Models\Meta; +use Floor9design\TestingTools\Exceptions\TestingToolsException; +use PHPUnit\Framework\TestCase; + +/** + * MetaTest + * + * This test file tests the Meta. + * + * @category None + * @package Floor9design\JsonApiFormatter\Tests\Unit + * @author Rick Morice + * @copyright Floor9design Ltd + * @license MIT + * @version 1.0 + * @link https://github.com/floor9design-ltd/json-api-formatter + * @link https://floor9design.com + * @since File available since Release 1.0 + */ +class MetaTest extends TestCase +{ + // Accessors + + /** + * Test meta constructor. + * + * @return void + * @throws TestingToolsException + */ + public function testConstructor() + { + $array = ['hello' => 'world']; + $meta = new Meta($array); + $this->assertEquals($meta->hello, 'world'); + } + + /** + * Test meta constructor. + * + * @return void + * @throws TestingToolsException + */ + public function testToArray() + { + $array = ['hello' => 'world']; + $meta = new Meta($array); + $this->assertEquals($meta->toArray(), $array); + } + +}