Passed
Pull Request — master (#123)
by Kevin
02:36
created

many_to_one_unmanaged_raw_entity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 4
c 1
b 1
f 0
dl 0
loc 9
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Zenstruck\Foundry\Tests\Functional;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
7
use Zenstruck\Foundry\Test\Factories;
8
use Zenstruck\Foundry\Test\ResetDatabase;
9
use Zenstruck\Foundry\Tests\Fixtures\Entity\Category;
10
use Zenstruck\Foundry\Tests\Fixtures\Factories\CategoryFactory;
11
use Zenstruck\Foundry\Tests\Fixtures\Factories\CommentFactory;
12
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactory;
13
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactoryWithInvalidInitialize;
14
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactoryWithNullInitialize;
15
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactoryWithValidInitialize;
16
use Zenstruck\Foundry\Tests\Fixtures\Factories\TagFactory;
17
use Zenstruck\Foundry\Tests\Fixtures\Factories\UserFactory;
18
19
/**
20
 * @author Kevin Bond <[email protected]>
21
 */
22
final class ModelFactoryTest extends KernelTestCase
23
{
24
    use Factories, ResetDatabase;
25
26
    /**
27
     * @test
28
     */
29
    public function can_find_or_create(): void
30
    {
31
        CategoryFactory::repository()->assertCount(0);
32
        CategoryFactory::findOrCreate(['name' => 'php']);
33
        CategoryFactory::repository()->assertCount(1);
34
        CategoryFactory::findOrCreate(['name' => 'php']);
35
        CategoryFactory::repository()->assertCount(1);
36
    }
37
38
    /**
39
     * @test
40
     */
41
    public function can_override_initialize(): void
42
    {
43
        $this->assertFalse(PostFactory::createOne()->isPublished());
0 ignored issues
show
Bug introduced by
The method isPublished() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
        $this->assertFalse(PostFactory::createOne()->/** @scrutinizer ignore-call */ isPublished());
Loading history...
44
        $this->assertTrue(PostFactoryWithValidInitialize::createOne()->isPublished());
45
    }
46
47
    /**
48
     * @test
49
     */
50
    public function initialize_must_return_an_instance_of_the_current_factory(): void
51
    {
52
        $this->expectException(\TypeError::class);
53
        $this->expectExceptionMessage(\sprintf('"%1$s::initialize()" must return an instance of "%1$s".', PostFactoryWithInvalidInitialize::class));
54
55
        PostFactoryWithInvalidInitialize::new();
56
    }
57
58
    /**
59
     * @test
60
     */
61
    public function initialize_must_return_a_value(): void
62
    {
63
        $this->expectException(\TypeError::class);
64
        $this->expectExceptionMessage(\sprintf('"%1$s::initialize()" must return an instance of "%1$s".', PostFactoryWithNullInitialize::class));
65
66
        PostFactoryWithNullInitialize::new();
67
    }
68
69
    /**
70
     * @test
71
     */
72
    public function can_find_random_object(): void
73
    {
74
        CategoryFactory::createMany(5);
75
76
        $ids = [];
77
78
        while (5 !== \count(\array_unique($ids))) {
79
            $ids[] = CategoryFactory::random()->getId();
0 ignored issues
show
Bug introduced by
The method getId() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

79
            $ids[] = CategoryFactory::random()->/** @scrutinizer ignore-call */ getId();
Loading history...
80
        }
81
82
        $this->assertCount(5, \array_unique($ids));
83
    }
84
85
    /**
86
     * @test
87
     */
88
    public function can_create_random_object_if_none_exists(): void
89
    {
90
        CategoryFactory::repository()->assertCount(0);
91
        $this->assertInstanceOf(Category::class, CategoryFactory::randomOrCreate()->object());
92
        CategoryFactory::repository()->assertCount(1);
93
        $this->assertInstanceOf(Category::class, CategoryFactory::randomOrCreate()->object());
94
        CategoryFactory::repository()->assertCount(1);
95
    }
96
97
    /**
98
     * @test
99
     */
100
    public function can_get_or_create_random_object_with_attributes(): void
101
    {
102
        CategoryFactory::createMany(5, ['name' => 'name1']);
103
104
        CategoryFactory::repository()->assertCount(5);
105
        $this->assertSame('name2', CategoryFactory::randomOrCreate(['name' => 'name2'])->getName());
0 ignored issues
show
Bug introduced by
The method getName() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        $this->assertSame('name2', CategoryFactory::randomOrCreate(['name' => 'name2'])->/** @scrutinizer ignore-call */ getName());
Loading history...
106
        CategoryFactory::repository()->assertCount(6);
107
        $this->assertSame('name2', CategoryFactory::randomOrCreate(['name' => 'name2'])->getName());
108
        CategoryFactory::repository()->assertCount(6);
109
    }
110
111
    /**
112
     * @test
113
     */
114
    public function can_find_random_set_of_objects(): void
115
    {
116
        CategoryFactory::createMany(5);
117
118
        $objects = CategoryFactory::randomSet(3);
119
120
        $this->assertCount(3, $objects);
121
        $this->assertCount(3, \array_unique(\array_map(static function($category) { return $category->getId(); }, $objects)));
122
    }
123
124
    /**
125
     * @test
126
     */
127
    public function can_find_random_set_of_objects_with_attributes(): void
128
    {
129
        CategoryFactory::createMany(20, ['name' => 'name1']);
130
        CategoryFactory::createMany(5, ['name' => 'name2']);
131
132
        $objects = CategoryFactory::randomSet(2, ['name' => 'name2']);
133
134
        $this->assertCount(2, $objects);
135
        $this->assertSame('name2', $objects[0]->getName());
136
        $this->assertSame('name2', $objects[1]->getName());
137
    }
138
139
    /**
140
     * @test
141
     */
142
    public function can_find_random_range_of_objects(): void
143
    {
144
        CategoryFactory::createMany(5);
145
146
        $counts = [];
147
148
        while (4 !== \count(\array_unique($counts))) {
149
            $counts[] = \count(CategoryFactory::randomRange(0, 3));
150
        }
151
152
        $this->assertCount(4, \array_unique($counts));
153
        $this->assertContains(0, $counts);
154
        $this->assertContains(1, $counts);
155
        $this->assertContains(2, $counts);
156
        $this->assertContains(3, $counts);
157
        $this->assertNotContains(4, $counts);
158
        $this->assertNotContains(5, $counts);
159
    }
160
161
    /**
162
     * @test
163
     */
164
    public function can_find_random_range_of_objects_with_attributes(): void
165
    {
166
        CategoryFactory::createMany(20, ['name' => 'name1']);
167
        CategoryFactory::createMany(5, ['name' => 'name2']);
168
169
        $objects = CategoryFactory::randomRange(2, 4, ['name' => 'name2']);
170
171
        $this->assertGreaterThanOrEqual(2, \count($objects));
172
        $this->assertLessThanOrEqual(4, \count($objects));
173
174
        foreach ($objects as $object) {
175
            $this->assertSame('name2', $object->getName());
176
        }
177
    }
178
179
    /**
180
     * @test
181
     */
182
    public function one_to_many_with_nested_collection_relationship(): void
183
    {
184
        $post = PostFactory::createOne([
185
            'comments' => CommentFactory::new()->many(4),
186
        ]);
187
188
        $this->assertCount(4, $post->getComments());
0 ignored issues
show
Bug introduced by
The method getComments() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

188
        $this->assertCount(4, $post->/** @scrutinizer ignore-call */ getComments());
Loading history...
189
        UserFactory::repository()->assertCount(4);
190
        CommentFactory::repository()->assertCount(4);
191
        PostFactory::repository()->assertCount(1);
192
    }
193
194
    /**
195
     * @test
196
     */
197
    public function create_multiple_one_to_many_with_nested_collection_relationship(): void
198
    {
199
        $user = UserFactory::createOne();
200
        $posts = PostFactory::createMany(2, [
201
            'comments' => CommentFactory::new(['user' => $user])->many(4),
202
        ]);
203
204
        $this->assertCount(4, $posts[0]->getComments());
205
        $this->assertCount(4, $posts[1]->getComments());
206
        UserFactory::repository()->assertCount(1);
207
        CommentFactory::repository()->assertCount(8);
208
        PostFactory::repository()->assertCount(2);
209
    }
210
211
    /**
212
     * @test
213
     */
214
    public function many_to_many_with_nested_collection_relationship(): void
215
    {
216
        $post = PostFactory::createOne([
217
            'tags' => TagFactory::new()->many(3),
218
        ]);
219
220
        $this->assertCount(3, $post->getTags());
0 ignored issues
show
Bug introduced by
The method getTags() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

220
        $this->assertCount(3, $post->/** @scrutinizer ignore-call */ getTags());
Loading history...
221
        TagFactory::repository()->assertCount(5); // 3 created by this test and 2 in global state
222
        PostFactory::repository()->assertCount(1);
223
    }
224
225
    /**
226
     * @test
227
     */
228
    public function inverse_many_to_many_with_nested_collection_relationship(): void
229
    {
230
        $tag = TagFactory::createOne([
231
            'posts' => PostFactory::new()->many(3),
232
        ]);
233
234
        $this->assertCount(3, $tag->getPosts());
0 ignored issues
show
Bug introduced by
The method getPosts() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

234
        $this->assertCount(3, $tag->/** @scrutinizer ignore-call */ getPosts());
Loading history...
235
        TagFactory::repository()->assertCount(3); // 1 created by this test and 2 in global state
236
        PostFactory::repository()->assertCount(3);
237
    }
238
239
    /**
240
     * @test
241
     */
242
    public function create_multiple_many_to_many_with_nested_collection_relationship(): void
243
    {
244
        $posts = PostFactory::createMany(2, [
245
            'tags' => TagFactory::new()->many(3),
246
        ]);
247
248
        $this->assertCount(3, $posts[0]->getTags());
249
        $this->assertCount(3, $posts[1]->getTags());
250
        TagFactory::repository()->assertCount(8); // 6 created by this test and 2 in global state
251
        PostFactory::repository()->assertCount(2);
252
    }
253
254
    /**
255
     * @test
256
     */
257
    public function unpersisted_one_to_many_with_nested_collection_relationship(): void
258
    {
259
        $post = PostFactory::new()->withoutPersisting()->create([
260
            'comments' => CommentFactory::new()->many(4),
261
        ]);
262
263
        $this->assertCount(4, $post->getComments());
264
        UserFactory::repository()->assertEmpty();
265
        CommentFactory::repository()->assertEmpty();
266
        PostFactory::repository()->assertEmpty();
267
    }
268
269
    /**
270
     * @test
271
     */
272
    public function unpersisted_many_to_many_with_nested_collection_relationship(): void
273
    {
274
        $post = PostFactory::new()->withoutPersisting()->create([
275
            'tags' => TagFactory::new()->many(3),
276
        ]);
277
278
        $this->assertCount(3, $post->getTags());
279
        TagFactory::repository()->assertCount(2); // 2 created in global state
280
        PostFactory::repository()->assertEmpty();
281
    }
282
283
    /**
284
     * @test
285
     * @dataProvider dataProvider
286
     */
287
    public function can_use_model_factories_in_a_data_provider(PostFactory $factory, bool $published): void
288
    {
289
        $post = $factory->create();
290
291
        $post->assertPersisted();
292
        $this->assertSame($published, $post->isPublished());
293
    }
294
295
    public static function dataProvider(): array
296
    {
297
        return [
298
            [PostFactory::new(), false],
299
            [PostFactory::new()->published(), true],
0 ignored issues
show
Bug introduced by
The method published() does not exist on Zenstruck\Foundry\ModelFactory. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

299
            [PostFactory::new()->/** @scrutinizer ignore-call */ published(), true],
Loading history...
300
        ];
301
    }
302
303
    /**
304
     * @test
305
     */
306
    public function many_to_one_unmanaged_entity(): void
307
    {
308
        $category = CategoryFactory::createOne(['name' => 'My Category']);
309
310
        self::$container->get(EntityManagerInterface::class)->clear();
311
312
        $post = PostFactory::createOne(['category' => $category]);
313
314
        $this->assertSame('My Category', $post->getCategory()->getName());
0 ignored issues
show
Bug introduced by
The method getCategory() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

314
        $this->assertSame('My Category', $post->/** @scrutinizer ignore-call */ getCategory()->getName());
Loading history...
315
    }
316
317
    /**
318
     * @test
319
     */
320
    public function many_to_one_unmanaged_raw_entity(): void
321
    {
322
        $category = CategoryFactory::createOne(['name' => 'My Category'])->object();
323
324
        self::$container->get(EntityManagerInterface::class)->clear();
325
326
        $post = PostFactory::createOne(['category' => $category]);
327
328
        $this->assertSame('My Category', $post->getCategory()->getName());
329
    }
330
331
    /**
332
     * @test
333
     */
334
    public function first_and_last_return_the_correct_object(): void
335
    {
336
        $categoryA = CategoryFactory::createOne(['name' => '3']);
337
        $categoryB = CategoryFactory::createOne(['name' => '2']);
0 ignored issues
show
Unused Code introduced by
The assignment to $categoryB is dead and can be removed.
Loading history...
338
        $categoryC = CategoryFactory::createOne(['name' => '1']);
339
340
        $this->assertSame($categoryA->getId(), CategoryFactory::first()->getId());
341
        $this->assertSame($categoryC->getId(), CategoryFactory::first('name')->getId());
342
        $this->assertSame($categoryC->getId(), CategoryFactory::last()->getId());
343
        $this->assertSame($categoryA->getId(), CategoryFactory::last('name')->getId());
344
    }
345
346
    /**
347
     * @test
348
     */
349
    public function first_throws_exception_if_no_entities_exist(): void
350
    {
351
        $this->expectException(\RuntimeException::class);
352
353
        CategoryFactory::first();
354
    }
355
356
    /**
357
     * @test
358
     */
359
    public function last_throws_exception_if_no_entities_exist(): void
360
    {
361
        $this->expectException(\RuntimeException::class);
362
363
        CategoryFactory::last();
364
    }
365
366
    /**
367
     * @test
368
     */
369
    public function can_count_and_truncate_model_factory(): void
370
    {
371
        $this->assertSame(0, CategoryFactory::count());
372
373
        CategoryFactory::createMany(4);
374
375
        $this->assertSame(4, CategoryFactory::count());
376
377
        CategoryFactory::truncate();
378
379
        $this->assertSame(0, CategoryFactory::count());
380
    }
381
382
    /**
383
     * @test
384
     */
385
    public function can_get_all_entities(): void
386
    {
387
        $this->assertSame([], CategoryFactory::all());
388
389
        CategoryFactory::createMany(4);
390
391
        $categories = CategoryFactory::all();
392
393
        $this->assertCount(4, $categories);
394
        $this->assertInstanceOf(Category::class, $categories[0]->object());
395
        $this->assertInstanceOf(Category::class, $categories[1]->object());
396
        $this->assertInstanceOf(Category::class, $categories[2]->object());
397
        $this->assertInstanceOf(Category::class, $categories[3]->object());
398
    }
399
400
    /**
401
     * @test
402
     */
403
    public function can_find_entity(): void
404
    {
405
        CategoryFactory::createOne(['name' => 'first']);
406
        CategoryFactory::createOne(['name' => 'second']);
407
        $category = CategoryFactory::createOne(['name' => 'third']);
408
409
        $this->assertSame('second', CategoryFactory::find(['name' => 'second'])->getName());
410
        $this->assertSame('third', CategoryFactory::find(['id' => $category->getId()])->getName());
411
        $this->assertSame('third', CategoryFactory::find($category->getId())->getName());
412
        $this->assertSame('third', CategoryFactory::find($category->object())->getName());
413
        $this->assertSame('third', CategoryFactory::find($category)->getName());
414
    }
415
416
    /**
417
     * @test
418
     */
419
    public function find_throws_exception_if_no_entities_exist(): void
420
    {
421
        $this->expectException(\RuntimeException::class);
422
423
        CategoryFactory::find('id');
424
    }
425
426
    /**
427
     * @test
428
     */
429
    public function can_find_by(): void
430
    {
431
        $this->assertSame([], CategoryFactory::findBy(['name' => 'name2']));
432
433
        CategoryFactory::createOne(['name' => 'name1']);
434
        CategoryFactory::createOne(['name' => 'name2']);
435
        CategoryFactory::createOne(['name' => 'name2']);
436
437
        $categories = CategoryFactory::findBy(['name' => 'name2']);
438
439
        $this->assertCount(2, $categories);
440
        $this->assertSame('name2', $categories[0]->getName());
441
        $this->assertSame('name2', $categories[1]->getName());
442
    }
443
}
444