can_customize_namespace_with_root_namespace_prefix()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 12
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Zenstruck\Foundry\Tests\Functional\Bundle\Maker;
4
5
use Symfony\Bundle\FrameworkBundle\Console\Application;
6
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
7
use Symfony\Component\Console\Tester\CommandTester;
8
use Zenstruck\Foundry\Tests\Fixtures\Document\Comment;
9
use Zenstruck\Foundry\Tests\Fixtures\Document\Post;
10
use Zenstruck\Foundry\Tests\Fixtures\Entity\Category;
11
use Zenstruck\Foundry\Tests\Fixtures\Entity\Tag;
12
13
/**
14
 * @author Kevin Bond <[email protected]>
15
 */
16
final class MakeFactoryTest extends MakerTestCase
17
{
18
    /**
19
     * @test
20
     */
21
    public function can_create_factory(): void
22
    {
23
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
24
25
        $this->assertFileDoesNotExist(self::tempFile('src/Factory/CategoryFactory.php'));
26
27
        $tester->execute(['entity' => Category::class]);
28
29
        $this->assertFileExists(self::tempFile('src/Factory/CategoryFactory.php'));
30
        $this->assertSame(<<<EOF
31
<?php
32
33
namespace App\\Factory;
34
35
use Zenstruck\\Foundry\\Tests\\Fixtures\\Entity\\Category;
36
use Zenstruck\\Foundry\\ModelFactory;
37
use Zenstruck\\Foundry\\Proxy;
38
39
/**
40
 * @extends ModelFactory<Category>
41
 *
42
 * @method static Category|Proxy createOne(array \$attributes = [])
43
 * @method static Category[]|Proxy[] createMany(int \$number, array|callable \$attributes = [])
44
 * @method static Category|Proxy find(object|array|mixed \$criteria)
45
 * @method static Category|Proxy findOrCreate(array \$attributes)
46
 * @method static Category|Proxy first(string \$sortedField = 'id')
47
 * @method static Category|Proxy last(string \$sortedField = 'id')
48
 * @method static Category|Proxy random(array \$attributes = [])
49
 * @method static Category|Proxy randomOrCreate(array \$attributes = [])
50
 * @method static Category[]|Proxy[] all()
51
 * @method static Category[]|Proxy[] findBy(array \$attributes)
52
 * @method static Category[]|Proxy[] randomSet(int \$number, array \$attributes = [])
53
 * @method static Category[]|Proxy[] randomRange(int \$min, int \$max, array \$attributes = [])
54
 * @method Category|Proxy create(array|callable \$attributes = [])
55
 */
56
final class CategoryFactory extends ModelFactory
57
{
58
    public function __construct()
59
    {
60
        parent::__construct();
61
62
        // TODO inject services if required (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services)
63
    }
64
65
    protected function getDefaults(): array
66
    {
67
        return [
68
            // TODO add your default values here (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories)
69
            'name' => self::faker()->text(),
70
        ];
71
    }
72
73
    protected function initialize(): self
74
    {
75
        // see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
76
        return \$this
77
            // ->afterInstantiate(function(Category \$category): void {})
78
        ;
79
    }
80
81
    protected static function getClass(): string
82
    {
83
        return Category::class;
84
    }
85
}
86
87
EOF
88
            , \file_get_contents(self::tempFile('src/Factory/CategoryFactory.php'))
89
        );
90
    }
91
92
    /**
93
     * @test
94
     */
95
    public function can_create_factory_interactively(): void
96
    {
97
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
98
99
        $this->assertFileDoesNotExist(self::tempFile('src/Factory/TagFactory.php'));
100
101
        $tester->setInputs([Tag::class]);
102
        $tester->execute([]);
103
        $output = $tester->getDisplay();
104
105
        $this->assertStringNotContainsString(Category::class, $output);
106
        $this->assertFileExists(self::tempFile('src/Factory/TagFactory.php'));
107
        $this->assertStringContainsString('Note: pass --test if you want to generate factories in your tests/ directory', $output);
108
        $this->assertSame(<<<EOF
109
<?php
110
111
namespace App\\Factory;
112
113
use Zenstruck\\Foundry\\Tests\\Fixtures\\Entity\\Tag;
114
use Zenstruck\\Foundry\\ModelFactory;
115
use Zenstruck\\Foundry\\Proxy;
116
117
/**
118
 * @extends ModelFactory<Tag>
119
 *
120
 * @method static Tag|Proxy createOne(array \$attributes = [])
121
 * @method static Tag[]|Proxy[] createMany(int \$number, array|callable \$attributes = [])
122
 * @method static Tag|Proxy find(object|array|mixed \$criteria)
123
 * @method static Tag|Proxy findOrCreate(array \$attributes)
124
 * @method static Tag|Proxy first(string \$sortedField = 'id')
125
 * @method static Tag|Proxy last(string \$sortedField = 'id')
126
 * @method static Tag|Proxy random(array \$attributes = [])
127
 * @method static Tag|Proxy randomOrCreate(array \$attributes = [])
128
 * @method static Tag[]|Proxy[] all()
129
 * @method static Tag[]|Proxy[] findBy(array \$attributes)
130
 * @method static Tag[]|Proxy[] randomSet(int \$number, array \$attributes = [])
131
 * @method static Tag[]|Proxy[] randomRange(int \$min, int \$max, array \$attributes = [])
132
 * @method Tag|Proxy create(array|callable \$attributes = [])
133
 */
134
final class TagFactory extends ModelFactory
135
{
136
    public function __construct()
137
    {
138
        parent::__construct();
139
140
        // TODO inject services if required (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services)
141
    }
142
143
    protected function getDefaults(): array
144
    {
145
        return [
146
            // TODO add your default values here (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories)
147
            'name' => self::faker()->text(),
148
        ];
149
    }
150
151
    protected function initialize(): self
152
    {
153
        // see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
154
        return \$this
155
            // ->afterInstantiate(function(Tag \$tag): void {})
156
        ;
157
    }
158
159
    protected static function getClass(): string
160
    {
161
        return Tag::class;
162
    }
163
}
164
165
EOF
166
            , \file_get_contents(self::tempFile('src/Factory/TagFactory.php'))
167
        );
168
    }
169
170
    /**
171
     * @test
172
     */
173
    public function can_create_factory_in_test_dir(): void
174
    {
175
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
176
177
        $this->assertFileDoesNotExist(self::tempFile('tests/Factory/CategoryFactory.php'));
178
179
        $tester->execute(['entity' => Category::class, '--test' => true]);
180
181
        $this->assertFileExists(self::tempFile('tests/Factory/CategoryFactory.php'));
182
        $this->assertSame(<<<EOF
183
<?php
184
185
namespace App\\Tests\\Factory;
186
187
use Zenstruck\\Foundry\\Tests\\Fixtures\\Entity\\Category;
188
use Zenstruck\\Foundry\\ModelFactory;
189
use Zenstruck\\Foundry\\Proxy;
190
191
/**
192
 * @extends ModelFactory<Category>
193
 *
194
 * @method static Category|Proxy createOne(array \$attributes = [])
195
 * @method static Category[]|Proxy[] createMany(int \$number, array|callable \$attributes = [])
196
 * @method static Category|Proxy find(object|array|mixed \$criteria)
197
 * @method static Category|Proxy findOrCreate(array \$attributes)
198
 * @method static Category|Proxy first(string \$sortedField = 'id')
199
 * @method static Category|Proxy last(string \$sortedField = 'id')
200
 * @method static Category|Proxy random(array \$attributes = [])
201
 * @method static Category|Proxy randomOrCreate(array \$attributes = [])
202
 * @method static Category[]|Proxy[] all()
203
 * @method static Category[]|Proxy[] findBy(array \$attributes)
204
 * @method static Category[]|Proxy[] randomSet(int \$number, array \$attributes = [])
205
 * @method static Category[]|Proxy[] randomRange(int \$min, int \$max, array \$attributes = [])
206
 * @method Category|Proxy create(array|callable \$attributes = [])
207
 */
208
final class CategoryFactory extends ModelFactory
209
{
210
    public function __construct()
211
    {
212
        parent::__construct();
213
214
        // TODO inject services if required (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services)
215
    }
216
217
    protected function getDefaults(): array
218
    {
219
        return [
220
            // TODO add your default values here (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories)
221
            'name' => self::faker()->text(),
222
        ];
223
    }
224
225
    protected function initialize(): self
226
    {
227
        // see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
228
        return \$this
229
            // ->afterInstantiate(function(Category \$category): void {})
230
        ;
231
    }
232
233
    protected static function getClass(): string
234
    {
235
        return Category::class;
236
    }
237
}
238
239
EOF
240
            , \file_get_contents(self::tempFile('tests/Factory/CategoryFactory.php'))
241
        );
242
    }
243
244
    /**
245
     * @test
246
     */
247
    public function can_create_factory_in_test_dir_interactively(): void
248
    {
249
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
250
251
        $this->assertFileDoesNotExist(self::tempFile('tests/Factory/TagFactory.php'));
252
253
        $tester->setInputs([Tag::class]);
254
        $tester->execute(['--test' => true]);
255
        $output = $tester->getDisplay();
256
257
        $this->assertFileExists(self::tempFile('tests/Factory/TagFactory.php'));
258
        $this->assertStringNotContainsString(Category::class, $output);
259
        $this->assertStringNotContainsString('Note: pass --test if you want to generate factories in your tests/ directory', $output);
260
        $this->assertSame(<<<EOF
261
<?php
262
263
namespace App\\Tests\\Factory;
264
265
use Zenstruck\\Foundry\\Tests\\Fixtures\\Entity\\Tag;
266
use Zenstruck\\Foundry\\ModelFactory;
267
use Zenstruck\\Foundry\\Proxy;
268
269
/**
270
 * @extends ModelFactory<Tag>
271
 *
272
 * @method static Tag|Proxy createOne(array \$attributes = [])
273
 * @method static Tag[]|Proxy[] createMany(int \$number, array|callable \$attributes = [])
274
 * @method static Tag|Proxy find(object|array|mixed \$criteria)
275
 * @method static Tag|Proxy findOrCreate(array \$attributes)
276
 * @method static Tag|Proxy first(string \$sortedField = 'id')
277
 * @method static Tag|Proxy last(string \$sortedField = 'id')
278
 * @method static Tag|Proxy random(array \$attributes = [])
279
 * @method static Tag|Proxy randomOrCreate(array \$attributes = [])
280
 * @method static Tag[]|Proxy[] all()
281
 * @method static Tag[]|Proxy[] findBy(array \$attributes)
282
 * @method static Tag[]|Proxy[] randomSet(int \$number, array \$attributes = [])
283
 * @method static Tag[]|Proxy[] randomRange(int \$min, int \$max, array \$attributes = [])
284
 * @method Tag|Proxy create(array|callable \$attributes = [])
285
 */
286
final class TagFactory extends ModelFactory
287
{
288
    public function __construct()
289
    {
290
        parent::__construct();
291
292
        // TODO inject services if required (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services)
293
    }
294
295
    protected function getDefaults(): array
296
    {
297
        return [
298
            // TODO add your default values here (https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories)
299
            'name' => self::faker()->text(),
300
        ];
301
    }
302
303
    protected function initialize(): self
304
    {
305
        // see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
306
        return \$this
307
            // ->afterInstantiate(function(Tag \$tag): void {})
308
        ;
309
    }
310
311
    protected static function getClass(): string
312
    {
313
        return Tag::class;
314
    }
315
}
316
317
EOF
318
            , \file_get_contents(self::tempFile('tests/Factory/TagFactory.php'))
319
        );
320
    }
321
322
    /**
323
     * @test
324
     */
325
    public function invalid_entity_throws_exception(): void
326
    {
327
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
328
329
        $this->assertFileDoesNotExist(self::tempFile('src/Factory/InvalidFactory.php'));
330
331
        try {
332
            $tester->execute(['entity' => 'Invalid']);
333
        } catch (RuntimeCommandException $e) {
334
            $this->assertSame('Entity "Invalid" not found.', $e->getMessage());
335
            $this->assertFileDoesNotExist(self::tempFile('src/Factory/InvalidFactory.php'));
336
337
            return;
338
        }
339
340
        $this->fail('Exception not thrown.');
341
    }
342
343
    /**
344
     * @test
345
     */
346
    public function can_customize_namespace(): void
347
    {
348
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
349
        $expectedFile = self::tempFile('src/My/Namespace/TagFactory.php');
350
351
        $this->assertFileDoesNotExist($expectedFile);
352
353
        $tester->setInputs([Tag::class]);
354
        $tester->execute(['--namespace' => 'My\\Namespace']);
355
356
        $this->assertFileExists($expectedFile);
357
        $this->assertStringContainsString('namespace App\\My\\Namespace;', \file_get_contents($expectedFile));
358
    }
359
360
    /**
361
     * @test
362
     */
363
    public function can_customize_namespace_with_test_flag(): void
364
    {
365
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
366
        $expectedFile = self::tempFile('tests/My/Namespace/TagFactory.php');
367
368
        $this->assertFileDoesNotExist($expectedFile);
369
370
        $tester->setInputs([Tag::class]);
371
        $tester->execute(['--namespace' => 'My\\Namespace', '--test' => true]);
372
373
        $this->assertFileExists($expectedFile);
374
        $this->assertStringContainsString('namespace App\\Tests\\My\\Namespace;', \file_get_contents($expectedFile));
375
    }
376
377
    /**
378
     * @test
379
     */
380
    public function can_customize_namespace_with_root_namespace_prefix(): void
381
    {
382
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
383
        $expectedFile = self::tempFile('src/My/Namespace/TagFactory.php');
384
385
        $this->assertFileDoesNotExist($expectedFile);
386
387
        $tester->setInputs([Tag::class]);
388
        $tester->execute(['--namespace' => 'App\\My\\Namespace']);
389
390
        $this->assertFileExists($expectedFile);
391
        $this->assertStringContainsString('namespace App\\My\\Namespace;', \file_get_contents($expectedFile));
392
    }
393
394
    /**
395
     * @test
396
     */
397
    public function can_customize_namespace_with_test_flag_with_root_namespace_prefix(): void
398
    {
399
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
400
        $expectedFile = self::tempFile('tests/My/Namespace/TagFactory.php');
401
402
        $this->assertFileDoesNotExist($expectedFile);
403
404
        $tester->setInputs([Tag::class]);
405
        $tester->execute(['--namespace' => 'App\\Tests\\My\\Namespace', '--test' => true]);
406
407
        $this->assertFileExists($expectedFile);
408
        $this->assertStringContainsString('namespace App\\Tests\\My\\Namespace;', \file_get_contents($expectedFile));
409
    }
410
411
    /**
412
     * @test
413
     */
414
    public function can_create_factory_with_all_interactively(): void
415
    {
416
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
417
418
        $this->assertFileDoesNotExist(self::tempFile('src/Factory/CategoryFactory.php'));
419
        $this->assertFileDoesNotExist(self::tempFile('src/Factory/PostFactory.php'));
420
421
        $tester->setInputs(['All']);
422
423
        try {
424
            $tester->execute([]);
425
        } catch (RuntimeCommandException $e) {
426
            // todo find a better solution
427
            // because we have fixtures with the same name, the maker will fail when creating the duplicate
428
        }
429
430
        $this->assertFileExists(self::tempFile('src/Factory/CategoryFactory.php'));
431
        $this->assertFileExists(self::tempFile('src/Factory/PostFactory.php'));
432
    }
433
434
    /**
435
     * @test
436
     * @dataProvider documentProvider
437
     */
438
    public function can_create_factory_for_odm(string $class, string $file): void
439
    {
440
        if (false === \getenv('MONGO_URL')) {
441
            self::markTestSkipped('doctrine/odm not enabled.');
442
        }
443
444
        $tester = new CommandTester((new Application(self::bootKernel()))->find('make:factory'));
445
446
        $this->assertFileDoesNotExist(self::tempFile("src/Factory/{$file}.php"));
447
448
        $tester->setInputs([$class]);
449
        $tester->execute([]);
450
451
        $this->assertFileExists(self::tempFile("src/Factory/{$file}.php"));
452
    }
453
454
    public function documentProvider(): iterable
455
    {
456
        yield 'document' => [Post::class, 'PostFactory'];
457
        yield 'embedded document' => [Comment::class, 'CommentFactory'];
458
    }
459
}
460