Skip to content

Commit cc994cd

Browse files
authored
Merge pull request #68 from RonasIT/49-add-factory-tests
Add factory tests
2 parents eff8e16 + 875c2fd commit cc994cd

15 files changed

+231
-213
lines changed

config/entity-generator.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
'repositories' => 'app/Repositories',
1717
'tests' => 'tests',
1818
'routes' => 'routes/api.php',
19-
'factory' => 'database/factories/ModelFactory.php',
19+
'factories' => 'database/factories',
2020
'translations' => 'resources/lang/en/validation.php',
2121
'resources' => 'app/Http/Resources',
2222
'nova' => 'app/Nova',
@@ -32,8 +32,6 @@
3232
'routes' => 'entity-generator::routes',
3333
'use_routes' => 'entity-generator::use_routes',
3434
'factory' => 'entity-generator::factory',
35-
'legacy_factory' => 'entity-generator::legacy_factory',
36-
'legacy_empty_factory' => 'entity-generator::legacy_empty_factory',
3735
'seeder' => 'entity-generator::seeder',
3836
'legacy_seeder' => 'entity-generator::legacy_seeder',
3937
'database_empty_seeder' => 'entity-generator::database_empty_seeder',

src/Commands/MakeEntityCommand.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace RonasIT\Support\Commands;
44

5-
use Closure;
65
use Illuminate\Console\Command;
76
use Illuminate\Support\Arr;
87
use Illuminate\Support\Facades\Config;
@@ -217,10 +216,9 @@ protected function outputNewConfig($packageConfigs, $projectConfigs)
217216
}
218217

219218
$factories = 'database/factories';
220-
$factories = (version_compare(app()->version(), '8', '>=')) ? $factories : "{$factories}/ModelFactory.php";
221219

222-
if ($newConfig['paths.factory'] !== $factories) {
223-
$newConfig['paths.factory'] = $factories;
220+
if ($newConfig['paths.factories'] !== $factories) {
221+
$newConfig['paths.factories'] = $factories;
224222
}
225223

226224
$differences = array_diff_key($newConfig, $flattenedProjectConfigs);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace RonasIT\Support\Exceptions;
4+
5+
use Exception;
6+
7+
class FakerMethodNotFoundException extends Exception
8+
{
9+
}

src/Generators/AbstractTestsGenerator.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,11 @@ protected function getInserts(): array
8989
}, $this->buildRelationsTree($arrayModels));
9090
}
9191

92-
protected function isFactoryExists($modelName): bool
92+
protected function isFactoryExists(string $modelName): bool
9393
{
94-
$factory = app(LegacyFactories::class);
9594
$modelClass = $this->getModelClass($modelName);
9695

97-
$isNewStyleFactoryExists = $this->classExists('factory', "{$modelName}Factory") && method_exists($modelClass, 'factory');
98-
99-
return $isNewStyleFactoryExists || !empty($factory[$this->getModelClass($modelName)]);
96+
return $this->classExists('factories', "{$modelName}Factory") && method_exists($modelClass, 'factory');
10097
}
10198

10299
protected function isMethodExists($modelName, $method): bool
@@ -170,13 +167,14 @@ protected function getModelFields($model): array
170167

171168
protected function getMockModel($model): array
172169
{
173-
if (!$this->isFactoryExists($model)) {
170+
$hasFactory = $this->isFactoryExists($model);
171+
172+
if (!$hasFactory) {
174173
return [];
175174
}
176175

177176
$modelClass = $this->getModelClass($model);
178-
$hasFactory = method_exists($modelClass, 'factory') && $this->classExists('factory', "{$model}Factory");
179-
$factory = ($hasFactory) ? $modelClass::factory() : factory($modelClass);
177+
$factory = $modelClass::factory();
180178

181179
return $factory
182180
->make()

src/Generators/FactoryGenerator.php

Lines changed: 25 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
use Faker\Generator as Faker;
66
use Illuminate\Support\Arr;
77
use Illuminate\Support\Str;
8-
use RonasIT\Support\Exceptions\ModelFactoryNotFound;
8+
use InvalidArgumentException;
9+
use RonasIT\Support\Exceptions\FakerMethodNotFoundException;
910
use RonasIT\Support\Exceptions\ClassNotExistsException;
10-
use RonasIT\Support\Exceptions\ModelFactoryNotFoundedException;
1111
use RonasIT\Support\Exceptions\ClassAlreadyExistsException;
1212
use RonasIT\Support\Events\SuccessCreateMessage;
13-
use Exception;
1413

1514
class FactoryGenerator extends EntityGenerator
1615
{
@@ -26,109 +25,33 @@ class FactoryGenerator extends EntityGenerator
2625
'json' => '[]',
2726
];
2827

29-
protected function generateSeparateClass(): string
28+
public function generate(): void
3029
{
3130
if (!$this->classExists('models', $this->model)) {
3231
$this->throwFailureException(
33-
ClassNotExistsException::class,
34-
"Cannot create {$this->model}Factory cause {$this->model} Model does not exists.",
35-
"Create a {$this->model} Model by himself or run command 'php artisan make:entity {$this->model} --only-model'."
32+
exceptionClass: ClassNotExistsException::class,
33+
failureMessage: "Cannot create {$this->model}Factory cause {$this->model} Model does not exists.",
34+
recommendedMessage: "Create a {$this->model} Model by itself or run command 'php artisan make:entity {$this->model} --only-model'.",
3635
);
3736
}
3837

39-
if ($this->classExists('factory', "{$this->model}Factory")) {
38+
if ($this->classExists('factories', "{$this->model}Factory")) {
4039
$this->throwFailureException(
41-
ClassAlreadyExistsException::class,
42-
"Cannot create {$this->model}Factory cause {$this->model}Factory already exists.",
43-
"Remove {$this->model}Factory."
40+
exceptionClass: ClassAlreadyExistsException::class,
41+
failureMessage: "Cannot create {$this->model}Factory cause {$this->model}Factory already exists.",
42+
recommendedMessage: "Remove {$this->model}Factory.",
4443
);
4544
}
4645

4746
$factoryContent = $this->getStub('factory', [
48-
'namespace' => $this->getOrCreateNamespace('factory'),
47+
'namespace' => $this->getOrCreateNamespace('factories'),
4948
'entity' => $this->model,
50-
'fields' => $this->prepareFields()
49+
'fields' => $this->prepareFields(),
5150
]);
5251

53-
$this->saveClass('factory', "{$this->model}Factory", $factoryContent);
54-
55-
return "Created a new Factory: {$this->model}Factory";
56-
}
57-
58-
protected function generateToGenericClass(): string
59-
{
60-
if (!file_exists($this->paths['factory'])) {
61-
$this->prepareEmptyFactory();
62-
}
63-
64-
if (!$this->checkExistModelFactory() && $this->checkExistRelatedModelsFactories()) {
65-
$stubPath = config("entity-generator.stubs.legacy_factory");
66-
67-
$content = view($stubPath)->with([
68-
'entity' => $this->model,
69-
'fields' => $this->prepareFields(),
70-
'modelsNamespace' => $this->getOrCreateNamespace('models')
71-
])->render();
72-
73-
$content = "\n\n" . $content;
74-
75-
$createMessage = "Created a new Test factory for {$this->model} model in '{$this->paths['factory']}'";
76-
77-
file_put_contents($this->paths['factory'], $content, FILE_APPEND);
78-
79-
$this->prepareRelatedFactories();
80-
} else {
81-
$createMessage = "Factory for {$this->model} model has already created, so new factory not necessary create.";
82-
}
83-
84-
return $createMessage;
85-
}
52+
$this->saveClass('factories', "{$this->model}Factory", $factoryContent);
8653

87-
public function generate(): void
88-
{
89-
$createMessage = (version_compare(app()->version(), '8', '>='))
90-
? $this->generateSeparateClass()
91-
: $this->generateToGenericClass();
92-
93-
event(new SuccessCreateMessage($createMessage));
94-
}
95-
96-
protected function prepareEmptyFactory(): void
97-
{
98-
$stubPath = config('entity-generator.stubs.legacy_empty_factory');
99-
$content = "<?php \n\n" . view($stubPath, [
100-
'modelsNamespace' => $this->getOrCreateNamespace('models')
101-
])->render();
102-
103-
list($basePath, $databaseFactoryDir) = extract_last_part(config('entity-generator.paths.factory'), '/');
104-
105-
if (!is_dir($databaseFactoryDir)) {
106-
mkdir($databaseFactoryDir);
107-
}
108-
109-
file_put_contents($this->paths['factory'], $content);
110-
}
111-
112-
protected function checkExistRelatedModelsFactories(): bool
113-
{
114-
$modelFactoryContent = file_get_contents($this->paths['factory']);
115-
$relatedModels = $this->getRelatedModels($this->model, "{$this->model}Factory");
116-
$modelNamespace = $this->getOrCreateNamespace('models');
117-
118-
foreach ($relatedModels as $relatedModel) {
119-
$relatedFactoryClass = "{$modelNamespace}\\$relatedModel::class";
120-
$existModelFactory = strpos($modelFactoryContent, $relatedFactoryClass);
121-
122-
if (!$existModelFactory) {
123-
$this->throwFailureException(
124-
ModelFactoryNotFoundedException::class,
125-
"Not found $relatedModel factory for $relatedModel model in '{$this->paths['factory']}",
126-
"Please declare a factory for $relatedModel model on '{$this->paths['factory']}' path and run your command with option '--only-tests'."
127-
);
128-
}
129-
}
130-
131-
return true;
54+
event(new SuccessCreateMessage("Created a new Factory: {$this->model}Factory"));
13255
}
13356

13457
protected static function getFakerMethod($field): string
@@ -146,42 +69,10 @@ protected static function getCustomMethod($field): string
14669
return self::CUSTOM_METHODS[$field['type']];
14770
}
14871

149-
$message = $field['type'] . 'not found in CUSTOM_METHODS variable CUSTOM_METHODS = ' . self::CUSTOM_METHODS;
150-
throw new Exception($message);
151-
}
152-
153-
protected function prepareRelatedFactories(): void
154-
{
155-
$relations = array_merge(
156-
$this->relations['hasOne'],
157-
$this->relations['hasMany']
158-
);
159-
160-
foreach ($relations as $relation) {
161-
$modelFactoryContent = file_get_contents($this->paths['factory']);
162-
163-
if (!Str::contains($modelFactoryContent, $this->getModelClass($relation))) {
164-
$this->throwFailureException(
165-
ModelFactoryNotFound::class,
166-
"Model factory for mode {$relation} not found.",
167-
"Please create it and after thar you can run this command with flag '--only-tests'."
168-
);
169-
}
170-
171-
$matches = [];
172-
173-
preg_match($this->getFactoryPattern($relation), $modelFactoryContent, $matches);
174-
175-
foreach ($matches as $match) {
176-
$field = Str::snake($this->model) . '_id';
177-
178-
$newField = "\n \"{$field}\" => 1,";
72+
$message = "Cannot generate fake data for unsupported {$field['type']} field type. "
73+
. "Supported custom field types are " . implode(', ', array_keys(self::CUSTOM_METHODS));
17974

180-
$modelFactoryContent = str_replace($match, $match . $newField, $modelFactoryContent);
181-
}
182-
183-
file_put_contents($this->paths['factory'], $modelFactoryContent);
184-
}
75+
throw new FakerMethodNotFoundException($message);
18576
}
18677

18778
public static function getFactoryFieldsContent($field): string
@@ -193,49 +84,33 @@ public static function getFactoryFieldsContent($field): string
19384
return 1;
19485
}
19586

196-
if (property_exists($faker, $field['name'])) {
197-
return "\$faker-\>{$field['name']}";
87+
try {
88+
$faker->{$field['name']};
89+
$hasFormatter = true;
90+
} catch (InvalidArgumentException $e) {
91+
$hasFormatter = false;
19892
}
19993

200-
if (method_exists($faker, $field['name'])) {
201-
return "\$faker-\>{$field['name']}()";
94+
if ($hasFormatter) {
95+
return "\$faker->{$field['name']}";
20296
}
20397

20498
return self::getFakerMethod($field);
20599
}
206100

207-
protected function checkExistModelFactory(): int
208-
{
209-
$modelFactoryContent = file_get_contents($this->paths['factory']);
210-
$modelNamespace = $this->getOrCreateNamespace('models');
211-
$factoryClass = "{$modelNamespace}\\$this->model::class";
212-
213-
return strpos($modelFactoryContent, $factoryClass);
214-
}
215-
216101
protected function prepareFields(): array
217102
{
218103
$result = [];
219104

220105
foreach ($this->fields as $type => $fields) {
221106
foreach ($fields as $field) {
222-
$explodedType = explode('-', $type);
223-
224107
$result[] = [
225108
'name' => $field,
226-
'type' => head($explodedType)
109+
'type' => Str::before($type, '-'),
227110
];
228111
}
229112
}
230113

231114
return $result;
232115
}
233-
234-
protected function getFactoryPattern($model): string
235-
{
236-
$modelNamespace = "App\\\\Models\\\\" . $model;
237-
$return = "return \\[";
238-
239-
return "/{$modelNamespace}.*{$return}/sU";
240-
}
241116
}

stubs/factory.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ public function definition(): array
1717
@endforeach
1818
];
1919
}
20-
}
20+
}

stubs/legacy_empty_factory.blade.php

Lines changed: 0 additions & 30 deletions
This file was deleted.

stubs/legacy_factory.blade.php

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)