• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RonasIT / laravel-entity-generator / 12802573486

16 Jan 2025 05:16AM UTC coverage: 61.848% (+1.6%) from 60.217%
12802573486

Pull #73

github

web-flow
Merge 40fdcb29a into 3b523a66f
Pull Request #73: Add repository generator tests

1 of 1 new or added line in 1 file covered. (100.0%)

569 of 920 relevant lines covered (61.85%)

2.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.09
/src/Generators/AbstractTestsGenerator.php
1
<?php
2

3
namespace RonasIT\Support\Generators;
4

5
use DateTime;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Str;
8
use RonasIT\Support\Events\SuccessCreateMessage;
9
use RonasIT\Support\Exceptions\CircularRelationsFoundedException;
10

11
abstract class AbstractTestsGenerator extends EntityGenerator
12
{
13
    protected array $fakerProperties = [];
14
    protected array $getFields = [];
15
    protected bool $withAuth = false;
16

17
    const array FIXTURE_TYPES = [
18
        'create' => ['request', 'response'],
19
        'update' => ['request'],
20
    ];
21

22
    const string EMPTY_GUARDED_FIELD = '*';
23
    const string UPDATED_AT = 'updated_at';
24
    const string CREATED_AT = 'created_at';
25

26
    public function generate(): void
27
    {
28
        $this->createDump();
3✔
29
        $this->generateFixtures();
3✔
30
        $this->generateTests();
3✔
31
    }
32

33
    protected function getFixturesPath($fileName = null): string
34
    {
35
        $path = base_path("{$this->paths['tests']}/fixtures/{$this->getTestClassName()}");
3✔
36

37
        if (empty($fileName)) {
3✔
38
            return $path;
3✔
39
        }
40

41
        return "{$path}/{$fileName}";
3✔
42
    }
43

44
    protected function createDump(): void
45
    {
46
        if (!$this->isStubExists('dump')) {
3✔
47
            return;
1✔
48
        }
49

50
        $content = $this->getStub('dump', [
2✔
51
            'inserts' => $this->getInserts()
2✔
52
        ]);
2✔
53

54
        $this->createFixtureFolder();
2✔
55

56
        $dumpName = $this->getDumpName();
2✔
57

58
        file_put_contents($this->getFixturesPath($dumpName), $content);
2✔
59

60
        event(new SuccessCreateMessage("Created a new Test dump on path: "
2✔
61
            . "{$this->paths['tests']}/fixtures/{$this->getTestClassName()}/{$dumpName}"));
2✔
62
    }
63

64
    protected function getDumpName(): string
65
    {
66
        return 'dump.sql';
×
67
    }
68

69
    protected function getInserts(): array
70
    {
71
        $arrayModels = [$this->model];
2✔
72

73
        if ($this->canGenerateUserData()) {
2✔
74
            array_unshift($arrayModels, 'User');
×
75
            $this->withAuth = true;
×
76
        }
77

78
        return array_map(function ($model) {
2✔
79
            return [
2✔
80
                'name' => $this->getTableName($model),
2✔
81
                'items' => [
2✔
82
                    [
2✔
83
                        'fields' => $this->getModelFields($model),
2✔
84
                        'values' => $this->getDumpValuesList($model)
2✔
85
                    ]
2✔
86
                ]
2✔
87
            ];
2✔
88
        }, $this->buildRelationsTree($arrayModels));
2✔
89
    }
90

91
    protected function isFactoryExists(string $modelName): bool
92
    {
93
        return $this->classExists('factories', "{$modelName}Factory");
3✔
94
    }
95

96
    protected function isMethodExists($modelName, $method): bool
97
    {
98
        $modelClass = $this->getModelClass($modelName);
×
99

100
        return method_exists($modelClass, $method);
×
101
    }
102

103
    protected function getModelsWithFactories($models): array
104
    {
105
        return array_filter($models, function ($model) {
2✔
106
            return $this->isFactoryExists($model);
×
107
        });
2✔
108
    }
109

110
    protected function getDumpValuesList($model): array
111
    {
112
        $values = $this->buildEntityObject($model);
2✔
113

114
        array_walk($values, function (&$value) {
2✔
115
            if ($value instanceof DateTime) {
2✔
116
                $value = "'{$value->format('Y-m-d h:i:s')}'";
×
117
            } elseif (is_bool($value)) {
2✔
118
                $value = ($value) ? 'true' : 'false';
×
119
            } elseif (is_array($value)) {
2✔
120
                $value = json_encode($value);
×
121
            }
122

123
            $value = (is_string($value)) ? "'{$value}'" : $value;
2✔
124
        });
2✔
125

126
        return $values;
2✔
127
    }
128

129
    protected function getFixtureValuesList($model): array
130
    {
131
        $values = $this->buildEntityObject($model);
3✔
132

133
        array_walk($values, function (&$value) {
3✔
134
            if ($value instanceof DateTime) {
3✔
135
                $value = "{$value->format('Y-m-d h:i:s')}";
×
136
            }
137
        });
3✔
138

139
        return $values;
3✔
140
    }
141

142
    protected function buildEntityObject($model): array
143
    {
144
        $modelFields = $this->getModelFields($model);
3✔
145
        $mockEntity = $this->getMockModel($model);
3✔
146

147
        $result = [];
3✔
148

149
        foreach ($modelFields as $field) {
3✔
150
            $value = Arr::get($mockEntity, $field, 1);
3✔
151

152
            $result[$field] = $value;
3✔
153
        }
154

155
        return $result;
3✔
156
    }
157

158
    protected function getModelFields($model): array
159
    {
160
        $modelClass = $this->getModelClass($model);
3✔
161

162
        return $this->filterBadModelField($modelClass::getFields());
3✔
163
    }
164

165
    protected function getMockModel($model): array
166
    {
167
        $hasFactory = $this->isFactoryExists($model);
3✔
168

169
        if (!$hasFactory) {
3✔
170
            return [];
3✔
171
        }
172

173
        $factoryNamespace = "{$this->getOrCreateNamespace('factories')}\\{$model}Factory";
×
174
        $factory = $factoryNamespace::new();
×
175

176
        return $factory
×
177
            ->make()
×
178
            ->toArray();
×
179
    }
180

181
    protected function generateFixtures(): void
182
    {
183
        $object = $this->getFixtureValuesList($this->model);
3✔
184
        $entity = Str::snake($this->model);
3✔
185

186
        $this->createFixtureFolder();
3✔
187

188
        foreach (self::FIXTURE_TYPES as $type => $modifications) {
3✔
189
            if ($this->isFixtureNeeded($type)) {
3✔
190
                foreach ($modifications as $modification) {
3✔
191
                    $excepts = ($modification === 'request') ? ['id'] : [];
3✔
192

193
                    $this->generateFixture("{$type}_{$entity}_{$modification}.json", Arr::except($object, $excepts));
3✔
194
                }
195
            }
196
        }
197
    }
198

199
    protected function generateFixture($fixtureName, $data): void
200
    {
201
        $fixturePath = $this->getFixturesPath($fixtureName);
3✔
202
        $content = json_encode($data, JSON_PRETTY_PRINT);
3✔
203
        $fixtureRelativePath = "{$this->paths['tests']}/fixtures/{$this->getTestClassName()}/{$fixtureName}";
3✔
204

205
        file_put_contents($fixturePath, $content);
3✔
206

207
        event(new SuccessCreateMessage("Created a new Test fixture on path: {$fixtureRelativePath}"));
3✔
208
    }
209

210
    protected function buildRelationsTree($models): array
211
    {
212
        foreach ($models as $model) {
2✔
213
            $relations = $this->getRelatedModels($model, $this->getTestClassName());
2✔
214
            $relationsWithFactories = $this->getModelsWithFactories($relations);
2✔
215

216
            if (empty($relationsWithFactories)) {
2✔
217
                continue;
2✔
218
            }
219

220
            if (in_array($model, $relationsWithFactories)) {
×
221
                $this->throwFailureException(
×
222
                    CircularRelationsFoundedException::class,
×
223
                    'Circular relations founded.',
×
224
                    'Please resolve you relations in models, factories and database.'
×
225
                );
×
226
            }
227

228
            $relatedModels = $this->buildRelationsTree($relationsWithFactories);
×
229

230
            $models = array_merge($relatedModels, $models);
×
231
        }
232

233
        return array_unique($models);
2✔
234
    }
235

236
    protected function canGenerateUserData(): bool
237
    {
238
        return $this->classExists('models', 'User')
2✔
239
            && $this->isMethodExists('User', 'getFields');
2✔
240
    }
241

242
    protected function createFixtureFolder(): void
243
    {
244
        $fixturePath = $this->getFixturesPath();
3✔
245

246
        if (!file_exists($fixturePath)) {
3✔
247
            mkdir($fixturePath, 0777, true);
3✔
248
        }
249
    }
250

251
    abstract protected function getTestClassName(): string;
252

253
    abstract protected function isFixtureNeeded($type): bool;
254

255
    abstract protected function generateTests(): void;
256

257
    private function filterBadModelField($fields): array
258
    {
259
        return array_diff($fields, [
3✔
260
            self::EMPTY_GUARDED_FIELD,
3✔
261
            self::CREATED_AT,
3✔
262
            self::UPDATED_AT,
3✔
263
        ]);
3✔
264
    }
265
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc