Skip to content

Commit 16c9ad5

Browse files
authored
fix : phpunit (#30)
* feat: add authorization capabilities with can method * refactor: rename 'field' to 'attribute' for clarity in relation methods * fix: collection and schema tests for improved accuracy and stability * feat: enhance pagination handling for Laravel 12 compatibility * feat: enhance pagination handling for Laravel 12 compatibility * fix: update test method signatures to include ignored parameter for consistency * docs: add Laravel policy on relationships to README * refactor: remove unused can method and related documentation from Relation.php
1 parent b1a2d05 commit 16c9ad5

File tree

11 files changed

+88
-72
lines changed

11 files changed

+88
-72
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@
4444
]
4545
}
4646
},
47-
"minimum-stability": "dev"
47+
"minimum-stability": "stable"
4848
}

readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ protected function toRelationships(Request $request): array
263263

264264
`toRelationships` must returns an array, keyed by string, of `JsonApiResource` or `JsonApiCollection`.
265265

266-
#### Laravel conditional relationships
266+
#### Laravel conditional relationships
267267
_**@see** [laravel: eloquent-conditional-relationships](https://laravel.com/docs/9.x/eloquent-resources#conditional-relationships)_
268268

269269
Support laravel conditional relationships.
@@ -331,6 +331,7 @@ protected function toRelationships(Request $request): array
331331
}
332332
```
333333

334+
334335
### toLinks
335336
_**@see** [{json:api}: resource-linkage](https://jsonapi.org/format/#document-resource-object-links)_
336337

src/Descriptors/Describer.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,17 @@ public function whenFilled(): static
8484
/**
8585
* @param \Illuminate\Http\Request $request
8686
* @param T $model
87-
* @param string $field
87+
* @param string $attribute
8888
*
8989
* @return mixed
9090
*/
91-
public function valueFor(Request $request, mixed $model, string $field): mixed
91+
public function valueFor(Request $request, mixed $model, string $attribute): mixed
9292
{
93-
if (!$this->check($request, $model, $field)) {
93+
if (!$this->check($request, $model, $attribute)) {
9494
return new MissingValue();
9595
}
9696

97-
return $this->resolveFor($request, $model, $field);
97+
return $this->resolveFor($request, $model, $attribute);
9898
}
9999

100100
/**
@@ -134,11 +134,11 @@ private function retrieveValue(mixed $model, string $attribute): mixed
134134
/**
135135
* @param \Illuminate\Http\Request $request
136136
* @param T $model
137-
* @param string $field
137+
* @param string $attribute
138138
*
139139
* @return mixed
140140
*/
141-
abstract protected function resolveFor(Request $request, mixed $model, string $field): mixed;
141+
abstract protected function resolveFor(Request $request, mixed $model, string $attribute): mixed;
142142

143143
/**
144144
* @return string|Closure|null

src/Descriptors/Relations/Relation.php

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Ark4ne\JsonApi\Descriptors\Describer;
66
use Ark4ne\JsonApi\Resources\Relationship;
7+
use Ark4ne\JsonApi\Support\Includes;
78
use Ark4ne\JsonApi\Traits\HasRelationLoad;
89
use Closure;
910
use Illuminate\Database\Eloquent\Model;
@@ -25,12 +26,13 @@ abstract class Relation extends Describer
2526

2627
/**
2728
* @param class-string<\Ark4ne\JsonApi\Resources\JsonApiResource|\Ark4ne\JsonApi\Resources\JsonApiCollection> $related
28-
* @param string|\Closure|null $relation
29+
* @param string|\Closure|null $relation
2930
*/
3031
public function __construct(
31-
protected string $related,
32+
protected string $related,
3233
protected null|string|Closure $relation
33-
) {
34+
)
35+
{
3436
}
3537

3638
/**
@@ -63,7 +65,7 @@ public function meta(Closure $meta): static
6365

6466
/**
6567
* @param bool|null $whenIncluded
66-
* @return $this
68+
* @return static
6769
*/
6870
public function whenIncluded(null|bool $whenIncluded = null): static
6971
{
@@ -73,39 +75,42 @@ public function whenIncluded(null|bool $whenIncluded = null): static
7375
$this->whenIncluded = $whenIncluded;
7476
}
7577

76-
return $this;
78+
return $this->when(fn(
79+
Request $request,
80+
Model $model,
81+
string $attribute
82+
): bool => !$this->whenIncluded || Includes::include($request, $attribute));
7783
}
7884

7985
/**
80-
* @see \Illuminate\Http\Resources\ConditionallyLoadsAttributes::whenLoaded
81-
*
8286
* @param string|null $relation
8387
*
8488
* @return static
89+
* @see \Illuminate\Http\Resources\ConditionallyLoadsAttributes::whenLoaded
8590
*/
86-
public function whenLoaded(null|string $relation = null): self
91+
public function whenLoaded(null|string $relation = null): static
8792
{
8893
return $this->when(fn(
8994
Request $request,
90-
Model $model,
91-
string $attribute
95+
Model $model,
96+
string $attribute
9297
): bool => $model->relationLoaded($relation ?? (is_string($this->relation) ? $this->relation : $attribute)));
9398
}
9499

95100
/**
96-
* @see \Illuminate\Http\Resources\ConditionallyLoadsAttributes::whenPivotLoadedAs
97-
*
98-
* @param string $table
101+
* @param string $table
99102
* @param string|null $accessor
100103
*
101104
* @return static
105+
* @see \Illuminate\Http\Resources\ConditionallyLoadsAttributes::whenPivotLoadedAs
106+
*
102107
*/
103-
public function whenPivotLoaded(string $table, null|string $accessor = null): self
108+
public function whenPivotLoaded(string $table, null|string $accessor = null): static
104109
{
105110
return $this->when(fn(
106111
Request $request,
107-
Model $model,
108-
string $attribute
112+
Model $model,
113+
string $attribute
109114
): bool => ($pivot = $model->{$accessor ?? (is_string($this->relation) ? $this->relation : $attribute)})
110115
&& (
111116
$pivot instanceof $table ||
@@ -114,21 +119,21 @@ public function whenPivotLoaded(string $table, null|string $accessor = null): se
114119
);
115120
}
116121

117-
public function resolveFor(Request $request, mixed $model, string $field): Relationship
122+
public function resolveFor(Request $request, mixed $model, string $attribute): Relationship
118123
{
119124
$retriever = $this->retriever();
120125

121126
if ($retriever instanceof Closure) {
122-
$value = static fn() => $retriever($model, $field);
127+
$value = static fn() => $retriever($model, $attribute);
123128
} else {
124129
$value = static fn() => match (true) {
125-
$model instanceof Model => $model->getRelationValue($retriever ?? $field),
126-
Arr::accessible($model) => $model[$retriever ?? $field],
127-
default => $model->{$retriever ?? $field}
130+
$model instanceof Model => $model->getRelationValue($retriever ?? $attribute),
131+
Arr::accessible($model) => $model[$retriever ?? $attribute],
132+
default => $model->{$retriever ?? $attribute}
128133
};
129134
}
130135

131-
$relation = $this->value(fn() => $this->check($request, $model, $field) ? $value() : new MissingValue());
136+
$relation = $this->value(fn() => $this->check($request, $model, $attribute) ? $value() : new MissingValue());
132137

133138
if ($this->whenIncluded !== null) {
134139
$relation->whenIncluded($this->whenIncluded);
@@ -139,14 +144,14 @@ public function resolveFor(Request $request, mixed $model, string $field): Relat
139144

140145
/**
141146
* @param \Illuminate\Http\Request $request
142-
* @param T $model
143-
* @param string $field
147+
* @param T $model
148+
* @param string $attribute
144149
*
145150
* @return mixed
146151
*/
147-
public function valueFor(Request $request, mixed $model, string $field): mixed
152+
public function valueFor(Request $request, mixed $model, string $attribute): mixed
148153
{
149-
return $this->resolveFor($request, $model, $field);
154+
return $this->resolveFor($request, $model, $attribute);
150155
}
151156

152157
abstract protected function value(Closure $value): Relationship;

src/Descriptors/Relations/RelationRaw.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ protected function value(Closure $value): Relationship
2222

2323
public static function fromRelationship(Relationship $relationship): self
2424
{
25-
return new self($relationship->getResource(), fn() => $relationship);
25+
return new self($relationship->getResource(), static fn() => $relationship);
2626
}
2727
}

src/Resources/Concerns/ConditionallyLoadsAttributes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ protected function applyWhen(bool|Closure $condition, iterable $data): MergeValu
6666
$value = new ValueMixed(is_callable($raw) ? $raw : static fn () => $raw);
6767
}
6868

69-
return $value->when(fn () => value($condition));
69+
return $value->when(static fn () => value($condition));
7070
}));
7171
}
7272

tests/Feature/Comment/CollectionTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Test\Feature\Comment;
44

55
use DateTimeInterface;
6+
use Illuminate\Foundation\Application;
67
use Illuminate\Http\Request;
78
use Illuminate\Support\Collection;
89
use Test\app\Http\Resources\PostResource;
@@ -82,6 +83,8 @@ private function getJsonResult(Collection $comments, ?array $attributes = null,
8283
))
8384
->reduce(fn(Collection $all, Collection $value) => $all->merge($value), collect());
8485

86+
$isLaravel12 = ((int)explode('.', Application::VERSION, 2)[0]) >= 12;
87+
8588
return collect(array_filter([
8689
'data' => $data,
8790
'included' => $include->uniqueStrict()->values()->all(),
@@ -99,21 +102,25 @@ private function getJsonResult(Collection $comments, ?array $attributes = null,
99102
[
100103
'active' => false,
101104
'label' => "&laquo; Previous",
105+
...($isLaravel12 ? ['page' => null] : []),
102106
'url' => null,
103107
],
104108
[
105109
'active' => true,
106110
'label' => '1',
111+
...($isLaravel12 ? ['page' => 1] : []),
107112
'url' => "http://localhost/comment?page=1",
108113
],
109114
...(array_map(static fn($value) => [
110115
'active' => false,
111116
'label' => (string)$value,
117+
...($isLaravel12 ? ['page' => $value] : []),
112118
'url' => "http://localhost/comment?page=$value",
113119
], range(2, 10))),
114120
[
115121
'active' => false,
116122
'label' => "Next &raquo;",
123+
...($isLaravel12 ? ['page' => 2] : []),
117124
'url' => "http://localhost/comment?page=2",
118125
],
119126
],

tests/Feature/SchemaTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function testSchema()
4141
$user->loads['main-post'] = 'post';
4242
$user->loads['posts'] = 'posts';
4343
$user->loads['comments'] = [
44-
'comments' => fn(Builder $q) => $q->where('content', 'like', '%e%')
44+
'comments' => UserResource::schema()->loads['comments']['comments']
4545
];
4646

4747
$post->relationships['user'] = $user;

tests/Unit/Descriptors/ValueTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public static function modelsValues()
9191
* @dataProvider values
9292
*/
9393
#[DataProvider('values')]
94-
public function testConvertValue($class, $value, $excepted)
94+
public function testConvertValue($class, $value, $excepted, $_ignored)
9595
{
9696
/** @var \Ark4ne\JsonApi\Descriptors\Values\Value $v */
9797
$v = new $class(null);
@@ -102,7 +102,7 @@ public function testConvertValue($class, $value, $excepted)
102102
* @dataProvider modelsValues
103103
*/
104104
#[DataProvider('modelsValues')]
105-
public function testValueFor($model, $class, $value, $excepted)
105+
public function testValueFor($model, $class, $value, $excepted, $_ignored)
106106
{
107107
data_set($model, 'attr', $value);
108108

@@ -118,7 +118,7 @@ public function testValueFor($model, $class, $value, $excepted)
118118
* @dataProvider modelsValues
119119
*/
120120
#[DataProvider('modelsValues')]
121-
public function testValueForWithNull($model, $class, $value, $excepted)
121+
public function testValueForWithNull($model, $class, $value, $excepted, $_ignored)
122122
{
123123
data_set($model, 'attr', null);
124124

tests/Unit/Resources/Concerns/ConditionallyLoadsAttributesTest.php

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -78,46 +78,49 @@ public function testApplyWhen()
7878
'missing.1' => 'abc',
7979
'missing.2' => 123,
8080
]);
81-
$this->assertEquals(new MergeValue([
82-
'missing.1' => (new ValueMixed(fn() => 'abc'))->when(fn() => false),
83-
'missing.2' => (new ValueMixed(fn() => 123))->when(fn() => false),
84-
]), $actual);
81+
$this->assertInstanceOf(MergeValue::class, $actual);
82+
$this->assertInstanceOf(ValueMixed::class, $actual->data['missing.1']);
83+
$this->assertInstanceOf(ValueMixed::class, $actual->data['missing.2']);
84+
$this->assertEquals('abc', $actual->data['missing.1']->retriever()());
85+
$this->assertEquals(123, $actual->data['missing.2']->retriever()());
8586
$actual = Reflect::invoke($stub, 'applyWhen', true, [
8687
'present.1' => 'abc',
8788
'present.2' => 123,
8889
]);
89-
$this->assertEquals(new MergeValue([
90-
'present.1' => (new ValueMixed(fn() => 'abc'))->when(fn() => true),
91-
'present.2' => (new ValueMixed(fn() => 123))->when(fn() => true),
92-
]), $actual);
90+
$this->assertInstanceOf(ValueMixed::class, $actual->data['present.1']);
91+
$this->assertInstanceOf(ValueMixed::class, $actual->data['present.2']);
92+
$this->assertEquals('abc', $actual->data['present.1']->retriever()());
93+
$this->assertEquals(123, $actual->data['present.2']->retriever()());
94+
9395
$actual = Reflect::invoke($stub, 'applyWhen', true, [
94-
'present.1' => (new ValueMixed(fn() => 'abc')),
95-
'present.2' => (new ValueMixed(fn() => 123)),
96-
'present.3' => (new RelationOne('present', fn() => 'abc')),
97-
'present.4' => (new RelationOne('present', fn() => 123)),
98-
'present.5' => (new Relationship(UserResource::class, fn() => null)),
96+
'present.1' => $p1 = (new ValueMixed(fn() => 'abc')),
97+
'present.2' => $p2 = (new ValueMixed(fn() => 123)),
98+
'present.3' => $p3 = (new RelationOne('present', fn() => 'abc')),
99+
'present.4' => $p4 = (new RelationOne('present', fn() => 123)),
100+
'present.5' => $p5 = (new Relationship(UserResource::class, fn() => null)),
99101
]);
100-
$this->assertEquals(new MergeValue([
101-
'present.1' => (new ValueMixed(fn() => 'abc'))->when(fn() => true),
102-
'present.2' => (new ValueMixed(fn() => 123))->when(fn() => true),
103-
'present.3' => (new RelationOne('present', fn() => 'abc'))->when(fn() => true),
104-
'present.4' => (new RelationOne('present', fn() => 123))->when(fn() => true),
105-
'present.5' => RelationRaw::fromRelationship(new Relationship(UserResource::class, fn() => null))->when(fn() => true),
106-
]), $actual);
102+
$this->assertInstanceOf(MergeValue::class, $actual);
103+
$this->assertEquals($p1, $actual->data['present.1']);
104+
$this->assertEquals($p2, $actual->data['present.2']);
105+
$this->assertEquals($p3, $actual->data['present.3']);
106+
$this->assertEquals($p4, $actual->data['present.4']);
107+
$this->assertInstanceOf(RelationRaw::class, $actual->data['present.5']);
108+
$this->assertInstanceOf(Relationship::class, $actual->data['present.5']->retriever()());
109+
107110
$actual = Reflect::invoke($stub, 'applyWhen', false, [
108-
'missing.1' => (new ValueMixed(fn() => 'abc')),
109-
'missing.2' => (new ValueMixed(fn() => 123)),
110-
'missing.3' => (new RelationOne('present', fn() => 'abc')),
111-
'missing.4' => (new RelationOne('present', fn() => 123)),
111+
'missing.1' => $p1 = (new ValueMixed(fn() => 'abc')),
112+
'missing.2' => $p2 = (new ValueMixed(fn() => 123)),
113+
'missing.3' => $p3 = (new RelationOne('present', fn() => 'abc')),
114+
'missing.4' => $p4 = (new RelationOne('present', fn() => 123)),
112115
'missing.5' => (new Relationship(UserResource::class, fn() => null)),
113116
]);
114-
$this->assertEquals(new MergeValue([
115-
'missing.1' => (new ValueMixed(fn() => 'abc'))->when(fn() => false),
116-
'missing.2' => (new ValueMixed(fn() => 123))->when(fn() => false),
117-
'missing.3' => (new RelationOne('present', fn() => 'abc'))->when(fn() => false),
118-
'missing.4' => (new RelationOne('present', fn() => 123))->when(fn() => false),
119-
'missing.5' => RelationRaw::fromRelationship(new Relationship(UserResource::class, fn() => null))->when(fn() => false),
120-
]), $actual);
117+
$this->assertInstanceOf(MergeValue::class, $actual);
118+
$this->assertEquals($p1, $actual->data['missing.1']);
119+
$this->assertEquals($p2, $actual->data['missing.2']);
120+
$this->assertEquals($p3, $actual->data['missing.3']);
121+
$this->assertEquals($p4, $actual->data['missing.4']);
122+
$this->assertInstanceOf(RelationRaw::class, $actual->data['missing.5']);
123+
$this->assertInstanceOf(Relationship::class, $actual->data['missing.5']->retriever()());
121124
}
122125

123126
public function testWhenHas()

0 commit comments

Comments
 (0)