1
|
|
|
<?php namespace League\Fractal\Test; |
2
|
|
|
|
3
|
|
|
use League\Fractal\Manager; |
4
|
|
|
use League\Fractal\Pagination\Cursor; |
5
|
|
|
use League\Fractal\Resource\Collection; |
6
|
|
|
use League\Fractal\Resource\Item; |
7
|
|
|
use League\Fractal\Resource\NullResource; |
8
|
|
|
use League\Fractal\Scope; |
9
|
|
|
use League\Fractal\Serializer\ArraySerializer; |
10
|
|
|
use League\Fractal\Test\Stub\ArraySerializerWithNull; |
11
|
|
|
use League\Fractal\Test\Stub\Transformer\DefaultIncludeBookTransformer; |
12
|
|
|
use League\Fractal\Test\Stub\Transformer\NullIncludeBookTransformer; |
13
|
|
|
use Mockery; |
14
|
|
|
|
15
|
|
|
class ScopeTest extends \PHPUnit_Framework_TestCase |
16
|
|
|
{ |
17
|
|
|
protected $simpleItem = ['foo' => 'bar']; |
18
|
|
|
protected $simpleCollection = [['foo' => 'bar']]; |
19
|
|
|
|
20
|
|
|
public function testEmbedChildScope() |
21
|
|
|
{ |
22
|
|
|
$manager = new Manager(); |
23
|
|
|
|
24
|
|
|
$resource = new Item(['foo' => 'bar'], function () { |
25
|
|
|
}); |
26
|
|
|
|
27
|
|
|
$scope = new Scope($manager, $resource, 'book'); |
28
|
|
|
$this->assertSame($scope->getScopeIdentifier(), 'book'); |
29
|
|
|
$childScope = $scope->embedChildScope('author', $resource); |
30
|
|
|
|
31
|
|
|
$this->assertInstanceOf('League\Fractal\Scope', $childScope); |
32
|
|
|
} |
33
|
|
|
|
34
|
|
View Code Duplication |
public function testGetManager() |
35
|
|
|
{ |
36
|
|
|
$resource = new Item(['foo' => 'bar'], function () { |
37
|
|
|
}); |
38
|
|
|
|
39
|
|
|
$scope = new Scope(new Manager(), $resource, 'book'); |
40
|
|
|
|
41
|
|
|
$this->assertInstanceOf('League\Fractal\Manager', $scope->getManager()); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
View Code Duplication |
public function testGetResource() |
45
|
|
|
{ |
46
|
|
|
$resource = new Item(['foo' => 'bar'], function () { |
47
|
|
|
}); |
48
|
|
|
|
49
|
|
|
$scope = new Scope(new Manager(), $resource, 'book'); |
50
|
|
|
|
51
|
|
|
$this->assertInstanceOf('League\Fractal\Resource\ResourceAbstract', $scope->getResource()); |
52
|
|
|
$this->assertInstanceOf('League\Fractal\Resource\Item', $scope->getResource()); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @covers \League\Fractal\Scope::toArray |
57
|
|
|
*/ |
58
|
|
View Code Duplication |
public function testToArray() |
|
|
|
|
59
|
|
|
{ |
60
|
|
|
$manager = new Manager(); |
61
|
|
|
|
62
|
|
|
$resource = new Item(['foo' => 'bar'], function ($data) { |
63
|
|
|
return $data; |
64
|
|
|
}); |
65
|
|
|
|
66
|
|
|
$scope = new Scope($manager, $resource); |
67
|
|
|
|
68
|
|
|
|
69
|
|
|
$this->assertSame(['data' => ['foo' => 'bar']], $scope->toArray()); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
public function testToJson() |
73
|
|
|
{ |
74
|
|
|
$data = [ |
75
|
|
|
'foo' => 'bar', |
76
|
|
|
]; |
77
|
|
|
|
78
|
|
|
$manager = new Manager(); |
79
|
|
|
|
80
|
|
|
$resource = new Item($data, function ($data) { |
81
|
|
|
return $data; |
82
|
|
|
}); |
83
|
|
|
|
84
|
|
|
$scope = new Scope($manager, $resource); |
85
|
|
|
|
86
|
|
|
$expected = json_encode([ |
87
|
|
|
'data' => $data, |
88
|
|
|
]); |
89
|
|
|
|
90
|
|
|
$this->assertSame($expected, $scope->toJson()); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
View Code Duplication |
public function testGetCurrentScope() |
94
|
|
|
{ |
95
|
|
|
$manager = new Manager(); |
96
|
|
|
|
97
|
|
|
$resource = new Item(['name' => 'Larry Ullman'], function () { |
98
|
|
|
}); |
99
|
|
|
|
100
|
|
|
$scope = new Scope($manager, $resource, 'book'); |
101
|
|
|
$this->assertSame('book', $scope->getScopeIdentifier()); |
102
|
|
|
|
103
|
|
|
$childScope = $scope->embedChildScope('author', $resource); |
104
|
|
|
$this->assertSame('author', $childScope->getScopeIdentifier()); |
105
|
|
|
|
106
|
|
|
$grandChildScope = $childScope->embedChildScope('profile', $resource); |
107
|
|
|
$this->assertSame('profile', $grandChildScope->getScopeIdentifier()); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
View Code Duplication |
public function testGetIdentifier() |
111
|
|
|
{ |
112
|
|
|
$manager = new Manager(); |
113
|
|
|
|
114
|
|
|
$resource = new Item(['name' => 'Larry Ullman'], function () { |
115
|
|
|
}); |
116
|
|
|
|
117
|
|
|
$scope = new Scope($manager, $resource, 'book'); |
118
|
|
|
$this->assertSame('book', $scope->getIdentifier()); |
119
|
|
|
|
120
|
|
|
$childScope = $scope->embedChildScope('author', $resource); |
121
|
|
|
$this->assertSame('book.author', $childScope->getIdentifier()); |
122
|
|
|
|
123
|
|
|
$grandChildScope = $childScope->embedChildScope('profile', $resource); |
124
|
|
|
$this->assertSame('book.author.profile', $grandChildScope->getIdentifier()); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
public function testGetParentScopes() |
128
|
|
|
{ |
129
|
|
|
$manager = new Manager(); |
130
|
|
|
|
131
|
|
|
$resource = new Item(['name' => 'Larry Ullman'], function () { |
132
|
|
|
}); |
133
|
|
|
|
134
|
|
|
$scope = new Scope($manager, $resource, 'book'); |
135
|
|
|
|
136
|
|
|
$childScope = $scope->embedChildScope('author', $resource); |
137
|
|
|
|
138
|
|
|
$this->assertSame(['book'], $childScope->getParentScopes()); |
139
|
|
|
|
140
|
|
|
$grandChildScope = $childScope->embedChildScope('profile', $resource); |
141
|
|
|
$this->assertSame(['book', 'author'], $grandChildScope->getParentScopes()); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
public function testIsRequested() |
145
|
|
|
{ |
146
|
|
|
$manager = new Manager(); |
147
|
|
|
$manager->parseIncludes(['foo', 'bar', 'baz.bart']); |
148
|
|
|
|
149
|
|
|
$scope = new Scope($manager, Mockery::mock('League\Fractal\Resource\ResourceAbstract')); |
150
|
|
|
|
151
|
|
|
$this->assertTrue($scope->isRequested('foo')); |
152
|
|
|
$this->assertTrue($scope->isRequested('bar')); |
153
|
|
|
$this->assertTrue($scope->isRequested('baz')); |
154
|
|
|
$this->assertTrue($scope->isRequested('baz.bart')); |
155
|
|
|
$this->assertFalse($scope->isRequested('nope')); |
156
|
|
|
|
157
|
|
|
$childScope = $scope->embedChildScope('baz', Mockery::mock('League\Fractal\Resource\ResourceAbstract')); |
158
|
|
|
$this->assertTrue($childScope->isRequested('bart')); |
159
|
|
|
$this->assertFalse($childScope->isRequested('foo')); |
160
|
|
|
$this->assertFalse($childScope->isRequested('bar')); |
161
|
|
|
$this->assertFalse($childScope->isRequested('baz')); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
public function testIsExcluded() |
165
|
|
|
{ |
166
|
|
|
$manager = new Manager(); |
167
|
|
|
$manager->parseIncludes(['foo', 'bar', 'baz.bart']); |
168
|
|
|
|
169
|
|
|
$scope = new Scope($manager, Mockery::mock('League\Fractal\Resource\ResourceAbstract')); |
170
|
|
|
$childScope = $scope->embedChildScope('baz', Mockery::mock('League\Fractal\Resource\ResourceAbstract')); |
|
|
|
|
171
|
|
|
|
172
|
|
|
$manager->parseExcludes('bar'); |
173
|
|
|
|
174
|
|
|
$this->assertFalse($scope->isExcluded('foo')); |
175
|
|
|
$this->assertTrue($scope->isExcluded('bar')); |
176
|
|
|
$this->assertFalse($scope->isExcluded('baz.bart')); |
177
|
|
|
|
178
|
|
|
$manager->parseExcludes('baz.bart'); |
179
|
|
|
|
180
|
|
|
$this->assertFalse($scope->isExcluded('baz')); |
181
|
|
|
$this->assertTrue($scope->isExcluded('baz.bart')); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* @expectedException InvalidArgumentException |
186
|
|
|
*/ |
187
|
|
|
public function testScopeRequiresConcreteImplementation() |
188
|
|
|
{ |
189
|
|
|
$manager = new Manager(); |
190
|
|
|
$manager->parseIncludes('book'); |
191
|
|
|
|
192
|
|
|
$resource = Mockery::mock('League\Fractal\Resource\ResourceAbstract', [ |
193
|
|
|
['bar' => 'baz'], |
194
|
|
|
function () {}, |
195
|
|
|
])->makePartial(); |
196
|
|
|
|
197
|
|
|
$scope = new Scope($manager, $resource); |
|
|
|
|
198
|
|
|
$scope->toArray(); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
public function testToArrayWithIncludes() |
202
|
|
|
{ |
203
|
|
|
$manager = new Manager(); |
204
|
|
|
$manager->parseIncludes('book'); |
205
|
|
|
|
206
|
|
|
$transformer = Mockery::mock('League\Fractal\TransformerAbstract')->makePartial(); |
207
|
|
|
$transformer->shouldReceive('getAvailableIncludes')->twice()->andReturn(['book']); |
208
|
|
|
$transformer->shouldReceive('transform')->once()->andReturnUsing(function (array $data) { |
209
|
|
|
return $data; |
210
|
|
|
}); |
211
|
|
|
$transformer->shouldReceive('processIncludedResources')->once()->andReturn(['book' => ['yin' => 'yang']]); |
212
|
|
|
|
213
|
|
|
$resource = new Item(['bar' => 'baz'], $transformer); |
214
|
|
|
|
215
|
|
|
$scope = new Scope($manager, $resource); |
216
|
|
|
|
217
|
|
|
$this->assertSame(['data' => ['bar' => 'baz', 'book' => ['yin' => 'yang']]], $scope->toArray()); |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
public function testToArrayWithSideloadedIncludes() |
221
|
|
|
{ |
222
|
|
|
$serializer = Mockery::mock('League\Fractal\Serializer\ArraySerializer')->makePartial(); |
223
|
|
|
$serializer->shouldReceive('sideloadIncludes')->andReturn(true); |
224
|
|
|
$serializer->shouldReceive('item')->andReturnUsing(function ($key, $data) { |
225
|
|
|
return ['data' => $data]; |
226
|
|
|
}); |
227
|
|
|
$serializer->shouldReceive('includedData')->andReturnUsing(function ($key, $data) { |
228
|
|
|
return ['sideloaded' => array_pop($data)]; |
229
|
|
|
}); |
230
|
|
|
|
231
|
|
|
$manager = new Manager(); |
232
|
|
|
$manager->parseIncludes('book'); |
233
|
|
|
$manager->setSerializer($serializer); |
|
|
|
|
234
|
|
|
|
235
|
|
|
$transformer = Mockery::mock('League\Fractal\TransformerAbstract')->makePartial(); |
236
|
|
|
$transformer->shouldReceive('getAvailableIncludes')->twice()->andReturn(['book']); |
237
|
|
|
$transformer->shouldReceive('transform')->once()->andReturnUsing(function (array $data) { |
238
|
|
|
return $data; |
239
|
|
|
}); |
240
|
|
|
$transformer->shouldReceive('processIncludedResources')->once()->andReturn(['book' => ['yin' => 'yang']]); |
241
|
|
|
|
242
|
|
|
$resource = new Item(['bar' => 'baz'], $transformer); |
243
|
|
|
|
244
|
|
|
$scope = new Scope($manager, $resource); |
245
|
|
|
|
246
|
|
|
$expected = [ |
247
|
|
|
'data' => ['bar' => 'baz'], |
248
|
|
|
'sideloaded' => ['book' => ['yin' => 'yang']], |
249
|
|
|
]; |
250
|
|
|
|
251
|
|
|
$this->assertSame($expected, $scope->toArray()); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
public function testPushParentScope() |
255
|
|
|
{ |
256
|
|
|
$manager = new Manager(); |
257
|
|
|
|
258
|
|
|
$resource = new Item(['name' => 'Larry Ullman'], function () { |
259
|
|
|
}); |
260
|
|
|
|
261
|
|
|
$scope = new Scope($manager, $resource); |
262
|
|
|
|
263
|
|
|
$this->assertSame(1, $scope->pushParentScope('book')); |
264
|
|
|
$this->assertSame(2, $scope->pushParentScope('author')); |
265
|
|
|
$this->assertSame(3, $scope->pushParentScope('profile')); |
266
|
|
|
|
267
|
|
|
|
268
|
|
|
$this->assertSame(['book', 'author', 'profile'], $scope->getParentScopes()); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
public function testRunAppropriateTransformerWithItem() |
272
|
|
|
{ |
273
|
|
|
$manager = new Manager(); |
274
|
|
|
|
275
|
|
|
$transformer = Mockery::mock('League\Fractal\TransformerAbstract'); |
276
|
|
|
$transformer->shouldReceive('transform')->once()->andReturn($this->simpleItem); |
277
|
|
|
$transformer->shouldReceive('getAvailableIncludes')->once()->andReturn([]); |
278
|
|
|
$transformer->shouldReceive('getDefaultIncludes')->once()->andReturn([]); |
279
|
|
|
$transformer->shouldReceive('setCurrentScope')->once()->andReturn([]); |
280
|
|
|
|
281
|
|
|
$resource = new Item($this->simpleItem, $transformer); |
282
|
|
|
$scope = $manager->createData($resource); |
283
|
|
|
|
284
|
|
|
$this->assertSame(['data' => $this->simpleItem], $scope->toArray()); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
public function testRunAppropriateTransformerWithCollection() |
288
|
|
|
{ |
289
|
|
|
$manager = new Manager(); |
290
|
|
|
|
291
|
|
|
$transformer = Mockery::mock('League\Fractal\TransformerAbstract'); |
292
|
|
|
$transformer->shouldReceive('transform')->once()->andReturn(['foo' => 'bar']); |
293
|
|
|
$transformer->shouldReceive('getAvailableIncludes')->once()->andReturn([]); |
294
|
|
|
$transformer->shouldReceive('getDefaultIncludes')->once()->andReturn([]); |
295
|
|
|
$transformer->shouldReceive('setCurrentScope')->once()->andReturn([]); |
296
|
|
|
|
297
|
|
|
$resource = new Collection([['foo' => 'bar']], $transformer); |
298
|
|
|
$scope = $manager->createData($resource); |
299
|
|
|
|
300
|
|
|
$this->assertSame(['data' => [['foo' => 'bar']]], $scope->toArray()); |
301
|
|
|
|
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* @covers \League\Fractal\Scope::executeResourceTransformers |
306
|
|
|
* @expectedException InvalidArgumentException |
307
|
|
|
* @expectedExceptionMessage Argument $resource should be an instance of League\Fractal\Resource\Item or League\Fractal\Resource\Collection |
308
|
|
|
*/ |
309
|
|
|
public function testCreateDataWithClassFuckKnows() |
310
|
|
|
{ |
311
|
|
|
$manager = new Manager(); |
312
|
|
|
|
313
|
|
|
$transformer = Mockery::mock('League\Fractal\TransformerAbstract')->makePartial(); |
314
|
|
|
|
315
|
|
|
$resource = Mockery::mock('League\Fractal\Resource\ResourceAbstract', [$this->simpleItem, $transformer])->makePartial(); |
316
|
|
|
$scope = $manager->createData($resource); |
317
|
|
|
$scope->toArray(); |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
public function testPaginatorOutput() |
321
|
|
|
{ |
322
|
|
|
$manager = new Manager(); |
323
|
|
|
|
324
|
|
|
$collection = new Collection([['foo' => 'bar', 'baz' => 'ban']], function (array $data) { |
325
|
|
|
return $data; |
326
|
|
|
}); |
327
|
|
|
|
328
|
|
|
$paginator = Mockery::mock('League\Fractal\Pagination\IlluminatePaginatorAdapter')->makePartial(); |
329
|
|
|
|
330
|
|
|
$total = 100; |
331
|
|
|
$perPage = $count = 5; |
332
|
|
|
$currentPage = 2; |
333
|
|
|
$lastPage = 20; |
334
|
|
|
|
335
|
|
|
$paginator->shouldReceive('getTotal')->once()->andReturn($total); |
336
|
|
|
$paginator->shouldReceive('getCount')->once()->andReturn($count); |
337
|
|
|
$paginator->shouldReceive('getPerPage')->once()->andReturn($perPage); |
338
|
|
|
$paginator->shouldReceive('getCurrentPage')->once()->andReturn($currentPage); |
339
|
|
|
$paginator->shouldReceive('getLastPage')->once()->andReturn($lastPage); |
340
|
|
|
$paginator->shouldReceive('getUrl')->times(2)->andReturnUsing(function ($page) { |
341
|
|
|
return 'http://example.com/foo?page='.$page; |
342
|
|
|
}); |
343
|
|
|
|
344
|
|
|
$collection->setPaginator($paginator); |
345
|
|
|
|
346
|
|
|
$rootScope = $manager->createData($collection); |
347
|
|
|
|
348
|
|
|
|
349
|
|
|
$expectedOutput = [ |
350
|
|
|
'data' => [ |
351
|
|
|
[ |
352
|
|
|
'foo' => 'bar', |
353
|
|
|
'baz' => 'ban', |
354
|
|
|
], |
355
|
|
|
], |
356
|
|
|
'meta' => [ |
357
|
|
|
'pagination' => [ |
358
|
|
|
'total' => $total, |
359
|
|
|
'count' => $count, |
360
|
|
|
'per_page' => $perPage, |
361
|
|
|
'current_page' => $currentPage, |
362
|
|
|
'total_pages' => $lastPage, |
363
|
|
|
'links' => [ |
364
|
|
|
'previous' => 'http://example.com/foo?page=1', |
365
|
|
|
'next' => 'http://example.com/foo?page=3', |
366
|
|
|
|
367
|
|
|
], |
368
|
|
|
], |
369
|
|
|
], |
370
|
|
|
]; |
371
|
|
|
|
372
|
|
|
$this->assertSame($expectedOutput, $rootScope->toArray()); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
public function testCursorOutput() |
376
|
|
|
{ |
377
|
|
|
$manager = new Manager(); |
378
|
|
|
|
379
|
|
|
$inputData = [ |
380
|
|
|
[ |
381
|
|
|
'foo' => 'bar', |
382
|
|
|
'baz' => 'ban', |
383
|
|
|
], |
384
|
|
|
]; |
385
|
|
|
|
386
|
|
|
$collection = new Collection($inputData, function (array $data) { |
387
|
|
|
return $data; |
388
|
|
|
}); |
389
|
|
|
|
390
|
|
|
$cursor = new Cursor(0, 'ban', 'ban', 2); |
391
|
|
|
|
392
|
|
|
$collection->setCursor($cursor); |
393
|
|
|
|
394
|
|
|
$rootScope = $manager->createData($collection); |
395
|
|
|
|
396
|
|
|
|
397
|
|
|
$expectedOutput = [ |
398
|
|
|
'data' => $inputData, |
399
|
|
|
'meta' => [ |
400
|
|
|
'cursor' => [ |
401
|
|
|
'current' => 0, |
402
|
|
|
'prev' => 'ban', |
403
|
|
|
'next' => 'ban', |
404
|
|
|
'count' => 2, |
405
|
|
|
|
406
|
|
|
], |
407
|
|
|
], |
408
|
|
|
]; |
409
|
|
|
|
410
|
|
|
$this->assertSame($expectedOutput, $rootScope->toArray()); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
View Code Duplication |
public function testDefaultIncludeSuccess() |
|
|
|
|
414
|
|
|
{ |
415
|
|
|
$manager = new Manager(); |
416
|
|
|
$manager->setSerializer(new ArraySerializer()); |
417
|
|
|
|
418
|
|
|
// Send this stub junk, it has a specific format anyhow |
419
|
|
|
$resource = new Item([], new DefaultIncludeBookTransformer()); |
420
|
|
|
|
421
|
|
|
// Try without metadata |
422
|
|
|
$scope = new Scope($manager, $resource); |
423
|
|
|
|
424
|
|
|
$expected = [ |
425
|
|
|
'a' => 'b', |
426
|
|
|
'author' => [ |
427
|
|
|
'c' => 'd', |
428
|
|
|
], |
429
|
|
|
]; |
430
|
|
|
|
431
|
|
|
$this->assertSame($expected, $scope->toArray()); |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
public function testNullResourceIncludeSuccess() |
435
|
|
|
{ |
436
|
|
|
$manager = new Manager(); |
437
|
|
|
$manager->setSerializer(new ArraySerializerWithNull); |
438
|
|
|
|
439
|
|
|
// Send this stub junk, it has a specific format anyhow |
440
|
|
|
$resource = new Item([], new NullIncludeBookTransformer); |
441
|
|
|
|
442
|
|
|
// Try without metadata |
443
|
|
|
$scope = new Scope($manager, $resource); |
444
|
|
|
$expected = [ |
445
|
|
|
'a' => 'b', |
446
|
|
|
'author' => null, |
447
|
|
|
]; |
448
|
|
|
|
449
|
|
|
$this->assertSame($expected, $scope->toArray()); |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* @covers \League\Fractal\Scope::toArray |
454
|
|
|
*/ |
455
|
|
View Code Duplication |
public function testNullResourceDataAndJustMeta() |
|
|
|
|
456
|
|
|
{ |
457
|
|
|
$manager = new Manager(); |
458
|
|
|
$manager->setSerializer(new ArraySerializerWithNull); |
459
|
|
|
|
460
|
|
|
$resource = new NullResource(); |
461
|
|
|
$resource->setMeta(['foo' => 'bar']); |
462
|
|
|
|
463
|
|
|
$scope = new Scope($manager, $resource); |
464
|
|
|
|
465
|
|
|
$this->assertSame(['meta' => ['foo' => 'bar']], $scope->toArray()); |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
public function tearDown() |
469
|
|
|
{ |
470
|
|
|
Mockery::close(); |
471
|
|
|
} |
472
|
|
|
} |
473
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.