123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731 |
- <?php namespace League\Fractal\Test;
- use League\Fractal\Manager;
- use League\Fractal\Pagination\Cursor;
- use League\Fractal\Resource\Collection;
- use League\Fractal\Resource\Item;
- use League\Fractal\Resource\NullResource;
- use League\Fractal\Resource\Primitive;
- use League\Fractal\Scope;
- use League\Fractal\Serializer\ArraySerializer;
- use League\Fractal\Test\Stub\ArraySerializerWithNull;
- use League\Fractal\Test\Stub\Transformer\DefaultIncludeBookTransformer;
- use League\Fractal\Test\Stub\Transformer\NullIncludeBookTransformer;
- use League\Fractal\Test\Stub\Transformer\PrimitiveIncludeBookTransformer;
- use Mockery;
- use PHPUnit\Framework\TestCase;
- class ScopeTest extends TestCase
- {
- protected $simpleItem = ['foo' => 'bar'];
- protected $simpleCollection = [['foo' => 'bar']];
- public function testEmbedChildScope()
- {
- $manager = new Manager();
- $resource = new Item(['foo' => 'bar'], function () {
- });
- $scope = new Scope($manager, $resource, 'book');
- $this->assertSame($scope->getScopeIdentifier(), 'book');
- $childScope = $scope->embedChildScope('author', $resource);
- $this->assertInstanceOf('League\Fractal\Scope', $childScope);
- }
- public function testGetManager()
- {
- $resource = new Item(['foo' => 'bar'], function () {
- });
- $scope = new Scope(new Manager(), $resource, 'book');
- $this->assertInstanceOf('League\Fractal\Manager', $scope->getManager());
- }
- public function testGetResource()
- {
- $resource = new Item(['foo' => 'bar'], function () {
- });
- $scope = new Scope(new Manager(), $resource, 'book');
- $this->assertInstanceOf('League\Fractal\Resource\ResourceAbstract', $scope->getResource());
- $this->assertInstanceOf('League\Fractal\Resource\Item', $scope->getResource());
- }
- /**
- * @covers \League\Fractal\Scope::toArray
- */
- public function testToArray()
- {
- $manager = new Manager();
- $resource = new Item(['foo' => 'bar'], function ($data) {
- return $data;
- });
- $scope = new Scope($manager, $resource);
- $this->assertSame(['data' => ['foo' => 'bar']], $scope->toArray());
- }
- public function testToJson()
- {
- $data = [
- 'foo' => 'bar',
- ];
- $manager = new Manager();
- $resource = new Item($data, function ($data) {
- return $data;
- });
- $scope = new Scope($manager, $resource);
- $expected = json_encode([
- 'data' => $data,
- ]);
- $this->assertSame($expected, $scope->toJson());
- }
- public function testToJsonWithOption()
- {
- $data = [
- 'foo' => 'bar',
- ];
- $manager = new Manager();
- $resource = new Item($data, function ($data) {
- return $data;
- });
- $scope = new Scope($manager, $resource);
- $expected = json_encode([
- 'data' => $data,
- ], JSON_PRETTY_PRINT);
- $this->assertSame($expected, $scope->toJson(JSON_PRETTY_PRINT));
- }
- public function testGetCurrentScope()
- {
- $manager = new Manager();
- $resource = new Item(['name' => 'Larry Ullman'], function () {
- });
- $scope = new Scope($manager, $resource, 'book');
- $this->assertSame('book', $scope->getScopeIdentifier());
- $childScope = $scope->embedChildScope('author', $resource);
- $this->assertSame('author', $childScope->getScopeIdentifier());
- $grandChildScope = $childScope->embedChildScope('profile', $resource);
- $this->assertSame('profile', $grandChildScope->getScopeIdentifier());
- }
- public function testGetIdentifier()
- {
- $manager = new Manager();
- $resource = new Item(['name' => 'Larry Ullman'], function () {
- });
- $scope = new Scope($manager, $resource, 'book');
- $this->assertSame('book', $scope->getIdentifier());
- $childScope = $scope->embedChildScope('author', $resource);
- $this->assertSame('book.author', $childScope->getIdentifier());
- $grandChildScope = $childScope->embedChildScope('profile', $resource);
- $this->assertSame('book.author.profile', $grandChildScope->getIdentifier());
- }
- public function testGetParentScopes()
- {
- $manager = new Manager();
- $resource = new Item(['name' => 'Larry Ullman'], function () {
- });
- $scope = new Scope($manager, $resource, 'book');
- $childScope = $scope->embedChildScope('author', $resource);
- $this->assertSame(['book'], $childScope->getParentScopes());
- $grandChildScope = $childScope->embedChildScope('profile', $resource);
- $this->assertSame(['book', 'author'], $grandChildScope->getParentScopes());
- }
- public function testIsRequested()
- {
- $manager = new Manager();
- $manager->parseIncludes(['foo', 'bar', 'baz.bart']);
- $scope = new Scope($manager, Mockery::mock('League\Fractal\Resource\ResourceAbstract'));
- $this->assertTrue($scope->isRequested('foo'));
- $this->assertTrue($scope->isRequested('bar'));
- $this->assertTrue($scope->isRequested('baz'));
- $this->assertTrue($scope->isRequested('baz.bart'));
- $this->assertFalse($scope->isRequested('nope'));
- $childScope = $scope->embedChildScope('baz', Mockery::mock('League\Fractal\Resource\ResourceAbstract'));
- $this->assertTrue($childScope->isRequested('bart'));
- $this->assertFalse($childScope->isRequested('foo'));
- $this->assertFalse($childScope->isRequested('bar'));
- $this->assertFalse($childScope->isRequested('baz'));
- }
- public function testIsExcluded()
- {
- $manager = new Manager();
- $manager->parseIncludes(['foo', 'bar', 'baz.bart']);
- $scope = new Scope($manager, Mockery::mock('League\Fractal\Resource\ResourceAbstract'));
- $childScope = $scope->embedChildScope('baz', Mockery::mock('League\Fractal\Resource\ResourceAbstract'));
- $manager->parseExcludes('bar');
- $this->assertFalse($scope->isExcluded('foo'));
- $this->assertTrue($scope->isExcluded('bar'));
- $this->assertFalse($scope->isExcluded('baz.bart'));
- $manager->parseExcludes('baz.bart');
- $this->assertFalse($scope->isExcluded('baz'));
- $this->assertTrue($scope->isExcluded('baz.bart'));
- }
- /**
- * @expectedException \InvalidArgumentException
- */
- public function testScopeRequiresConcreteImplementation()
- {
- $manager = new Manager();
- $manager->parseIncludes('book');
- $resource = Mockery::mock('League\Fractal\Resource\ResourceAbstract', [
- ['bar' => 'baz'],
- function () {},
- ])->makePartial();
- $scope = new Scope($manager, $resource);
- $scope->toArray();
- }
- public function testToArrayWithIncludes()
- {
- $manager = new Manager();
- $manager->parseIncludes('book,price');
- $transformer = Mockery::mock('League\Fractal\TransformerAbstract')->makePartial();
- $transformer->shouldReceive('getAvailableIncludes')->twice()->andReturn(['book']);
- $transformer->shouldReceive('transform')->once()->andReturnUsing(function (array $data) {
- return $data;
- });
- $transformer
- ->shouldReceive('processIncludedResources')
- ->once()
- ->andReturn(['book' => ['yin' => 'yang'], 'price' => 99]);
- $resource = new Item(['bar' => 'baz'], $transformer);
- $scope = new Scope($manager, $resource);
- $this->assertSame(['data' => ['bar' => 'baz', 'book' => ['yin' => 'yang'], 'price' => 99]], $scope->toArray());
- }
- public function testToArrayWithNumericKeysPreserved()
- {
- $manager = new Manager();
- $manager->setSerializer(new ArraySerializer());
- $resource = new Item(['1' => 'First', '2' => 'Second'], function ($data) {
- return $data;
- });
- $scope = new Scope($manager, $resource);
- $this->assertSame(['1' => 'First', '2' => 'Second'], $scope->toArray());
- }
- public function testToArrayWithSideloadedIncludes()
- {
- $serializer = Mockery::mock('League\Fractal\Serializer\ArraySerializer')->makePartial();
- $serializer->shouldReceive('sideloadIncludes')->andReturn(true);
- $serializer->shouldReceive('item')->andReturnUsing(function ($key, $data) {
- return ['data' => $data];
- });
- $serializer->shouldReceive('includedData')->andReturnUsing(function ($key, $data) {
- return ['sideloaded' => array_pop($data)];
- });
- $manager = new Manager();
- $manager->parseIncludes('book');
- $manager->setSerializer($serializer);
- $transformer = Mockery::mock('League\Fractal\TransformerAbstract')->makePartial();
- $transformer->shouldReceive('getAvailableIncludes')->twice()->andReturn(['book']);
- $transformer->shouldReceive('transform')->once()->andReturnUsing(function (array $data) {
- return $data;
- });
- $transformer->shouldReceive('processIncludedResources')->once()->andReturn(['book' => ['yin' => 'yang']]);
- $resource = new Item(['bar' => 'baz'], $transformer);
- $scope = new Scope($manager, $resource);
- $expected = [
- 'data' => ['bar' => 'baz'],
- 'sideloaded' => ['book' => ['yin' => 'yang']],
- ];
- $this->assertSame($expected, $scope->toArray());
- }
- public function testPushParentScope()
- {
- $manager = new Manager();
- $resource = new Item(['name' => 'Larry Ullman'], function () {
- });
- $scope = new Scope($manager, $resource);
- $this->assertSame(1, $scope->pushParentScope('book'));
- $this->assertSame(2, $scope->pushParentScope('author'));
- $this->assertSame(3, $scope->pushParentScope('profile'));
- $this->assertSame(['book', 'author', 'profile'], $scope->getParentScopes());
- }
- public function testRunAppropriateTransformerWithPrimitive()
- {
- $manager = new Manager();
- $transformer = Mockery::mock('League\Fractal\TransformerAbstract');
- $transformer->shouldReceive('transform')->once()->andReturn('simple string');
- $transformer->shouldReceive('setCurrentScope')->once()->andReturn([]);
- $transformer->shouldNotReceive('getAvailableIncludes');
- $transformer->shouldNotReceive('getDefaultIncludes');
- $resource = new Primitive('test', $transformer);
- $scope = $manager->createData($resource);
- $this->assertSame('simple string', $scope->transformPrimitiveResource());
- $resource = new Primitive(10, function ($x) {return $x + 10;});
- $scope = $manager->createData($resource);
- $this->assertSame(20, $scope->transformPrimitiveResource());
- }
- public function testRunAppropriateTransformerWithItem()
- {
- $manager = new Manager();
- $transformer = Mockery::mock('League\Fractal\TransformerAbstract');
- $transformer->shouldReceive('transform')->once()->andReturn($this->simpleItem);
- $transformer->shouldReceive('getAvailableIncludes')->once()->andReturn([]);
- $transformer->shouldReceive('getDefaultIncludes')->once()->andReturn([]);
- $transformer->shouldReceive('setCurrentScope')->once()->andReturn([]);
- $resource = new Item($this->simpleItem, $transformer);
- $scope = $manager->createData($resource);
- $this->assertSame(['data' => $this->simpleItem], $scope->toArray());
- }
- public function testRunAppropriateTransformerWithCollection()
- {
- $manager = new Manager();
- $transformer = Mockery::mock('League\Fractal\TransformerAbstract');
- $transformer->shouldReceive('transform')->once()->andReturn(['foo' => 'bar']);
- $transformer->shouldReceive('getAvailableIncludes')->once()->andReturn([]);
- $transformer->shouldReceive('getDefaultIncludes')->once()->andReturn([]);
- $transformer->shouldReceive('setCurrentScope')->once()->andReturn([]);
- $resource = new Collection([['foo' => 'bar']], $transformer);
- $scope = $manager->createData($resource);
- $this->assertSame(['data' => [['foo' => 'bar']]], $scope->toArray());
- }
- /**
- * @covers \League\Fractal\Scope::executeResourceTransformers
- * @expectedException \InvalidArgumentException
- * @expectedExceptionMessage Argument $resource should be an instance of League\Fractal\Resource\Item or League\Fractal\Resource\Collection
- */
- public function testCreateDataWithClassFuckKnows()
- {
- $manager = new Manager();
- $transformer = Mockery::mock('League\Fractal\TransformerAbstract')->makePartial();
- $resource = Mockery::mock('League\Fractal\Resource\ResourceAbstract', [$this->simpleItem, $transformer])->makePartial();
- $scope = $manager->createData($resource);
- $scope->toArray();
- }
- public function testPaginatorOutput()
- {
- $manager = new Manager();
- $collection = new Collection([['foo' => 'bar', 'baz' => 'ban']], function (array $data) {
- return $data;
- });
- $paginator = Mockery::mock('League\Fractal\Pagination\IlluminatePaginatorAdapter')->makePartial();
- $total = 100;
- $perPage = $count = 5;
- $currentPage = 2;
- $lastPage = 20;
- $paginator->shouldReceive('getTotal')->once()->andReturn($total);
- $paginator->shouldReceive('getCount')->once()->andReturn($count);
- $paginator->shouldReceive('getPerPage')->once()->andReturn($perPage);
- $paginator->shouldReceive('getCurrentPage')->once()->andReturn($currentPage);
- $paginator->shouldReceive('getLastPage')->once()->andReturn($lastPage);
- $paginator->shouldReceive('getUrl')->times(2)->andReturnUsing(function ($page) {
- return 'http://example.com/foo?page='.$page;
- });
- $collection->setPaginator($paginator);
- $rootScope = $manager->createData($collection);
- $expectedOutput = [
- 'data' => [
- [
- 'foo' => 'bar',
- 'baz' => 'ban',
- ],
- ],
- 'meta' => [
- 'pagination' => [
- 'total' => $total,
- 'count' => $count,
- 'per_page' => $perPage,
- 'current_page' => $currentPage,
- 'total_pages' => $lastPage,
- 'links' => [
- 'previous' => 'http://example.com/foo?page=1',
- 'next' => 'http://example.com/foo?page=3',
- ],
- ],
- ],
- ];
- $this->assertSame($expectedOutput, $rootScope->toArray());
- }
- public function testCursorOutput()
- {
- $manager = new Manager();
- $inputData = [
- [
- 'foo' => 'bar',
- 'baz' => 'ban',
- ],
- ];
- $collection = new Collection($inputData, function (array $data) {
- return $data;
- });
- $cursor = new Cursor(0, 'ban', 'ban', 2);
- $collection->setCursor($cursor);
- $rootScope = $manager->createData($collection);
- $expectedOutput = [
- 'data' => $inputData,
- 'meta' => [
- 'cursor' => [
- 'current' => 0,
- 'prev' => 'ban',
- 'next' => 'ban',
- 'count' => 2,
- ],
- ],
- ];
- $this->assertSame($expectedOutput, $rootScope->toArray());
- }
- public function testDefaultIncludeSuccess()
- {
- $manager = new Manager();
- $manager->setSerializer(new ArraySerializer());
- // Send this stub junk, it has a specific format anyhow
- $resource = new Item([], new DefaultIncludeBookTransformer());
- // Try without metadata
- $scope = new Scope($manager, $resource);
- $expected = [
- 'a' => 'b',
- 'author' => [
- 'c' => 'd',
- ],
- ];
- $this->assertSame($expected, $scope->toArray());
- }
- public function testPrimitiveResourceIncludeSuccess()
- {
- $manager = new Manager();
- $manager->setSerializer(new ArraySerializer());
- $resource = new Item(['price' => '49'], new PrimitiveIncludeBookTransformer);
- $scope = new Scope($manager, $resource);
- $expected = [
- 'a' => 'b',
- 'price' => 49,
- ];
- $this->assertSame($expected, $scope->toArray());
- }
- public function testNullResourceIncludeSuccess()
- {
- $manager = new Manager();
- $manager->setSerializer(new ArraySerializerWithNull);
- // Send this stub junk, it has a specific format anyhow
- $resource = new Item([], new NullIncludeBookTransformer);
- // Try without metadata
- $scope = new Scope($manager, $resource);
- $expected = [
- 'a' => 'b',
- 'author' => null,
- ];
- $this->assertSame($expected, $scope->toArray());
- }
- /**
- * @covers \League\Fractal\Scope::toArray
- */
- public function testNullResourceDataAndJustMeta()
- {
- $manager = new Manager();
- $manager->setSerializer(new ArraySerializerWithNull);
- $resource = new NullResource();
- $resource->setMeta(['foo' => 'bar']);
- $scope = new Scope($manager, $resource);
- $this->assertSame(['meta' => ['foo' => 'bar']], $scope->toArray());
- }
- /**
- * @covers \League\Fractal\Scope::toArray
- * @dataProvider fieldsetsProvider
- */
- public function testToArrayWithFieldsets($fieldsetsToParse, $expected)
- {
- $manager = new Manager();
- $resource = new Item(
- ['foo' => 'bar', 'baz' => 'qux'],
- function ($data) {
- return $data;
- },
- 'resourceName'
- );
- $scope = new Scope($manager, $resource);
- $manager->parseFieldsets($fieldsetsToParse);
- $this->assertSame($expected, $scope->toArray());
- }
- public function fieldsetsProvider()
- {
- return [
- [
- ['resourceName' => 'foo'],
- ['data' => ['foo' => 'bar']]
- ],
- [
- ['resourceName' => 'foo,baz'],
- ['data' => ['foo' => 'bar', 'baz' => 'qux']]
- ],
- [
- ['resourceName' => 'inexistentField'],
- ['data' => []]
- ]
- ];
- }
- /**
- * @covers \League\Fractal\Scope::toArray
- * @dataProvider fieldsetsWithMandatorySerializerFieldsProvider
- */
- public function testToArrayWithFieldsetsAndMandatorySerializerFields($fieldsetsToParse, $expected)
- {
- $serializer = Mockery::mock('League\Fractal\Serializer\DataArraySerializer')->makePartial();
- $serializer->shouldReceive('getMandatoryFields')->andReturn(['foo']);
- $resource = new Item(
- ['foo' => 'bar', 'baz' => 'qux'],
- function ($data) {
- return $data;
- },
- 'resourceName'
- );
- $manager = new Manager();
- $manager->setSerializer($serializer);
- $scope = new Scope($manager, $resource);
- $manager->parseFieldsets($fieldsetsToParse);
- $this->assertSame($expected, $scope->toArray());
- }
- public function fieldsetsWithMandatorySerializerFieldsProvider()
- {
- return [
- //Don't request for mandatory field
- [
- ['resourceName' => 'baz'],
- ['data' => ['foo' => 'bar', 'baz' => 'qux']]
- ],
- //Request required field anyway
- [
- ['resourceName' => 'foo,baz'],
- ['data' => ['foo' => 'bar', 'baz' => 'qux']]
- ]
- ];
- }
- /**
- * @dataProvider fieldsetsWithIncludesProvider
- */
- public function testToArrayWithIncludesAndFieldsets($fieldsetsToParse, $expected)
- {
- $transformer = $this->createTransformerWithIncludedResource('book', ['book' => ['yin' => 'yang']]);
- $resource = new Item(
- ['foo' => 'bar', 'baz' => 'qux'],
- $transformer,
- 'resourceName'
- );
- $manager = new Manager();
- $scope = new Scope($manager, $resource);
- $manager->parseIncludes('book');
- $manager->parseFieldsets($fieldsetsToParse);
- $this->assertSame($expected, $scope->toArray());
- }
- public function fieldsetsWithIncludesProvider()
- {
- return [
- //Included relation was not requested
- [
- ['resourceName' => 'foo'],
- ['data' => ['foo' => 'bar']]
- ],
- //Included relation was requested
- [
- ['resourceName' => 'foo,book', 'book' => 'yin'],
- ['data' => ['foo' => 'bar', 'book' => ['yin' => 'yang']]]
- ]
- ];
- }
- /**
- * @covers \League\Fractal\Scope::toArray
- * @dataProvider fieldsetsWithSideLoadIncludesProvider
- */
- public function testToArrayWithSideloadedIncludesAndFieldsets($fieldsetsToParse, $expected)
- {
- $serializer = Mockery::mock('League\Fractal\Serializer\DataArraySerializer')->makePartial();
- $serializer->shouldReceive('sideloadIncludes')->andReturn(true);
- $serializer->shouldReceive('item')->andReturnUsing(
- function ($key, $data) {
- return ['data' => $data];
- }
- );
- $serializer->shouldReceive('includedData')->andReturnUsing(
- function ($key, $data) {
- $data = array_pop($data);
- return empty($data) ? [] : ['sideloaded' => $data];
- }
- );
- $manager = new Manager();
- $manager->parseIncludes('book');
- $manager->setSerializer($serializer);
- $transformer = $this->createTransformerWithIncludedResource('book', ['book' => ['yin' => 'yang']]);
- $resource = new Item(['foo' => 'bar'], $transformer, 'resourceName');
- $scope = new Scope($manager, $resource);
- $manager->parseFieldsets($fieldsetsToParse);
- $this->assertSame($expected, $scope->toArray());
- }
- public function fieldsetsWithSideLoadIncludesProvider()
- {
- return [
- //Included relation was not requested
- [
- ['resourceName' => 'foo'],
- ['data' => ['foo' => 'bar']]
- ],
- //Included relation was requested
- [
- ['resourceName' => 'foo,book', 'book' => 'yin'],
- ['data' => ['foo' => 'bar'], 'sideloaded' => ['book' => ['yin' => 'yang']]]
- ]
- ];
- }
- public function tearDown()
- {
- Mockery::close();
- }
- protected function createTransformerWithIncludedResource($resourceName, $transformResult)
- {
- $transformer = Mockery::mock('League\Fractal\TransformerAbstract')->makePartial();
- $transformer->shouldReceive('getAvailableIncludes')->twice()->andReturn([$resourceName]);
- $transformer->shouldReceive('transform')->once()->andReturnUsing(
- function (array $data) {
- return $data;
- }
- );
- $transformer->shouldReceive('processIncludedResources')->once()->andReturn($transformResult);
- return $transformer;
- }
- }
|