Skip to content

Commit f8a5a7f

Browse files
committed
add tests for HasManyArrayColumn and HasManyKeys relationships
1 parent a6f9f9f commit f8a5a7f

File tree

4 files changed

+593
-41
lines changed

4 files changed

+593
-41
lines changed
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
6+
use Illuminate\Database\Eloquent\Collection;
7+
use Illuminate\Database\Query\Builder as QueryBuilder;
8+
use Mrpunyapal\LaravelExtendedRelationships\Relations\BelongsToArrayColumn;
9+
use Mrpunyapal\LaravelExtendedRelationships\Tests\Models\Company;
10+
use Mrpunyapal\LaravelExtendedRelationships\Tests\Models\User;
11+
12+
it('can create a belongs to array column relationship', function () {
13+
$queryBuilder = Mockery::mock(QueryBuilder::class);
14+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
15+
$child = Mockery::mock(Company::class);
16+
$related = Mockery::mock(User::class);
17+
18+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
19+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
20+
$queryBuilder->shouldReceive('when')->once()->andReturn($queryBuilder);
21+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->andReturn($queryBuilder);
22+
23+
$relation = new BelongsToArrayColumn(
24+
$eloquentBuilder,
25+
$child,
26+
'id',
27+
'user_ids',
28+
null,
29+
false
30+
);
31+
32+
expect($relation)->toBeInstanceOf(BelongsToArrayColumn::class);
33+
});
34+
35+
it('can create a belongs to array column relationship with string flag', function () {
36+
$queryBuilder = Mockery::mock(QueryBuilder::class);
37+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
38+
$child = Mockery::mock(Company::class);
39+
$related = Mockery::mock(User::class);
40+
41+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
42+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
43+
$queryBuilder->shouldReceive('when')->once()->andReturn($queryBuilder);
44+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->andReturn($queryBuilder);
45+
46+
$relation = new BelongsToArrayColumn(
47+
$eloquentBuilder,
48+
$child,
49+
'id',
50+
'user_ids',
51+
null,
52+
true
53+
);
54+
55+
expect($relation)->toBeInstanceOf(BelongsToArrayColumn::class);
56+
});
57+
58+
it('gets owner key name correctly', function () {
59+
$queryBuilder = Mockery::mock(QueryBuilder::class);
60+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
61+
$child = Mockery::mock(Company::class);
62+
$related = Mockery::mock(User::class);
63+
64+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
65+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
66+
$queryBuilder->shouldReceive('when')->once()->andReturn($queryBuilder);
67+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->andReturn($queryBuilder);
68+
69+
$relation = new BelongsToArrayColumn(
70+
$eloquentBuilder,
71+
$child,
72+
'owner_id',
73+
'user_ids',
74+
null,
75+
false
76+
);
77+
78+
$ownerKey = $relation->getOwnerKeyName();
79+
80+
expect($ownerKey)->toBe('user_ids');
81+
});
82+
83+
it('adds constraints properly without string flag', function () {
84+
$queryBuilder = Mockery::mock(QueryBuilder::class);
85+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
86+
$child = Mockery::mock(Company::class);
87+
$related = Mockery::mock(User::class);
88+
89+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
90+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
91+
$child->shouldReceive('getAttribute')->with('owner_id')->andReturn(1);
92+
$queryBuilder->shouldReceive('when')->twice()->with(false, Mockery::type('Closure'), Mockery::type('Closure'));
93+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->twice();
94+
95+
$relation = new BelongsToArrayColumn(
96+
$eloquentBuilder,
97+
$child,
98+
'owner_id',
99+
'user_ids',
100+
null,
101+
false
102+
);
103+
104+
$relation->addConstraints();
105+
106+
expect(true)->toBeTrue(); // If we reach here, constraints were added successfully
107+
});
108+
109+
it('adds constraints properly with string flag', function () {
110+
$queryBuilder = Mockery::mock(QueryBuilder::class);
111+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
112+
$child = Mockery::mock(Company::class);
113+
$related = Mockery::mock(User::class);
114+
115+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
116+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
117+
$child->shouldReceive('getAttribute')->with('id')->andReturn(1);
118+
$queryBuilder->shouldReceive('when')->twice()->with(true, Mockery::type('Closure'), Mockery::type('Closure'));
119+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->twice();
120+
121+
$relation = new BelongsToArrayColumn(
122+
$eloquentBuilder,
123+
$child,
124+
'id',
125+
'user_ids',
126+
null,
127+
true
128+
);
129+
130+
$relation->addConstraints();
131+
132+
expect(true)->toBeTrue(); // If we reach here, constraints were added successfully
133+
});
134+
135+
it('adds eager constraints properly without string flag', function () {
136+
$queryBuilder = Mockery::mock(QueryBuilder::class);
137+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
138+
$child = Mockery::mock(Company::class);
139+
$related = Mockery::mock(User::class);
140+
141+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
142+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
143+
$queryBuilder->shouldReceive('when')->once()->andReturn($queryBuilder); // Constructor call
144+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->andReturn($queryBuilder);
145+
146+
// Mock the where call to execute the closure
147+
$eloquentBuilder->shouldReceive('where')->once()->with(Mockery::type('Closure'))->andReturnUsing(function ($closure) use ($queryBuilder) {
148+
// Create a mock query for the closure to use
149+
$mockQuery = Mockery::mock(QueryBuilder::class);
150+
$mockQuery->shouldReceive('when')->twice()->with(false, Mockery::type('Closure'), Mockery::type('Closure'))->andReturnUsing(function ($condition, $trueCallback, $falseCallback) use ($mockQuery) {
151+
if (! $condition) {
152+
$falseCallback($mockQuery);
153+
} else {
154+
$trueCallback($mockQuery);
155+
}
156+
157+
return $mockQuery;
158+
});
159+
$mockQuery->shouldReceive('orWhereJsonContains')->twice();
160+
161+
// Execute the closure with our mock
162+
$closure($mockQuery);
163+
164+
return $queryBuilder;
165+
});
166+
167+
$relation = new BelongsToArrayColumn(
168+
$eloquentBuilder,
169+
$child,
170+
'id',
171+
'user_ids',
172+
null,
173+
false
174+
);
175+
176+
$model1 = Mockery::mock(Company::class);
177+
$model1->shouldReceive('getAttribute')->with('id')->andReturn(1);
178+
179+
$model2 = Mockery::mock(Company::class);
180+
$model2->shouldReceive('getAttribute')->with('id')->andReturn(2);
181+
182+
$relation->addEagerConstraints([$model1, $model2]);
183+
184+
expect(true)->toBeTrue(); // If we reach here, eager constraints were added successfully
185+
});
186+
187+
it('matches models properly', function () {
188+
$queryBuilder = Mockery::mock(QueryBuilder::class);
189+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
190+
$child = Mockery::mock(Company::class);
191+
$related = Mockery::mock(User::class);
192+
193+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
194+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
195+
$queryBuilder->shouldReceive('when')->once()->andReturn($queryBuilder);
196+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->andReturn($queryBuilder);
197+
198+
$relation = new BelongsToArrayColumn(
199+
$eloquentBuilder,
200+
$child,
201+
'id',
202+
'user_ids',
203+
null,
204+
false
205+
);
206+
207+
$user1 = new User(['id' => 1, 'user_ids' => [1, 2]]);
208+
$user2 = new User(['id' => 2, 'user_ids' => [2, 3]]);
209+
$user3 = new User(['id' => 3, 'user_ids' => [4, 5]]);
210+
211+
$company1 = new Company(['id' => 1]);
212+
$company2 = new Company(['id' => 2]);
213+
$company3 = new Company(['id' => 6]); // No user has 6 in their user_ids
214+
215+
$results = new Collection([$user1, $user2, $user3]);
216+
$models = $relation->match([$company1, $company2, $company3], $results, 'users');
217+
218+
expect($models[0]->users)->toHaveCount(1)
219+
->and($models[0]->users->first()->id)->toBe(1)
220+
->and($models[1]->users)->toHaveCount(2)
221+
->and($models[1]->users->pluck('id')->toArray())->toBe([1, 2])
222+
->and($models[2]->users)->toHaveCount(0);
223+
});
224+
225+
it('gets results correctly', function () {
226+
$queryBuilder = Mockery::mock(QueryBuilder::class);
227+
$eloquentBuilder = Mockery::mock(EloquentBuilder::class, [$queryBuilder]);
228+
$child = Mockery::mock(Company::class);
229+
$related = Mockery::mock(User::class);
230+
231+
$eloquentBuilder->shouldReceive('getModel')->andReturn($related);
232+
$eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder);
233+
$eloquentBuilder->shouldReceive('get')->andReturn(new Collection([]));
234+
$queryBuilder->shouldReceive('when')->once()->andReturn($queryBuilder);
235+
$queryBuilder->shouldReceive('whereNotNull')->with('user_ids')->andReturn($queryBuilder);
236+
237+
$relation = new BelongsToArrayColumn(
238+
$eloquentBuilder,
239+
$child,
240+
'id',
241+
'user_ids',
242+
null,
243+
false
244+
);
245+
246+
$results = $relation->getResults();
247+
248+
expect($results)->toBeInstanceOf(Collection::class);
249+
});
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Eloquent\Collection;
6+
use Mrpunyapal\LaravelExtendedRelationships\Relations\BelongsToManyKeys;
7+
use Mrpunyapal\LaravelExtendedRelationships\Tests\Models\Post;
8+
use Mrpunyapal\LaravelExtendedRelationships\Tests\Models\User;
9+
10+
it('can create a belongs to many keys relationship', function () {
11+
$post = new Post;
12+
13+
$relation = $post->belongsToManyKeys(
14+
User::class,
15+
'id',
16+
['created_by' => 'creator', 'updated_by' => 'updater']
17+
);
18+
19+
expect($relation)->toBeInstanceOf(BelongsToManyKeys::class);
20+
});
21+
22+
it('matches models properly with actual data', function () {
23+
$post = new Post;
24+
$relation = $post->belongsToManyKeys(
25+
User::class,
26+
'id',
27+
['created_by' => 'creator', 'updated_by' => 'updater']
28+
);
29+
30+
$user1 = new User(['id' => 1]);
31+
$user2 = new User(['id' => 2]);
32+
$user3 = new User(['id' => 3]);
33+
34+
$model1 = new Post(['created_by' => 1, 'updated_by' => 2]);
35+
$model2 = new Post(['created_by' => 3, 'updated_by' => null]);
36+
37+
$results = new Collection([$user1, $user2, $user3]);
38+
$models = $relation->match([$model1, $model2], $results, 'auditors');
39+
40+
expect($models[0]->auditors->creator->id)->toBe(1)
41+
->and($models[0]->auditors->updater->id)->toBe(2)
42+
->and($models[1]->auditors->creator->id)->toBe(3)
43+
->and(isset($models[1]->auditors->updater))->toBeFalse();
44+
});
45+
46+
it('builds dictionary correctly', function () {
47+
$post = new Post;
48+
$relation = $post->belongsToManyKeys(
49+
User::class,
50+
'id',
51+
['created_by' => 'creator', 'updated_by' => 'updater']
52+
);
53+
54+
$user1 = new User(['id' => 1]);
55+
$user2 = new User(['id' => 2]);
56+
57+
$collection = new Collection([$user1, $user2]);
58+
$dictionary = $relation->buildDictionary($collection);
59+
60+
expect($dictionary[1])->toBe($user1)
61+
->and($dictionary[2])->toBe($user2);
62+
});
63+
64+
it('gets parent key correctly', function () {
65+
$post = new Post(['created_by' => 123, 'updated_by' => 456]);
66+
67+
$relation = $post->belongsToManyKeys(
68+
User::class,
69+
'id',
70+
['created_by' => 'creator', 'updated_by' => 'updater']
71+
);
72+
73+
$key = $relation->getParentKey('created_by');
74+
expect($key)->toBe(123);
75+
76+
$key = $relation->getParentKey('updated_by');
77+
expect($key)->toBe(456);
78+
});
79+
80+
it('initializes relation on models', function () {
81+
$post = new Post;
82+
$relation = $post->belongsToManyKeys(
83+
User::class,
84+
'id',
85+
['created_by' => 'creator', 'updated_by' => 'updater']
86+
);
87+
88+
$model1 = new Post;
89+
$model2 = new Post;
90+
91+
$result = $relation->initRelation([$model1, $model2], 'auditors');
92+
93+
expect($result)->toBe([$model1, $model2])
94+
->and($model1->auditors)->toBeInstanceOf(Collection::class)
95+
->and($model2->auditors)->toBeInstanceOf(Collection::class);
96+
});

0 commit comments

Comments
 (0)