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

RonasIT / laravel-entity-generator / 16143130415

08 Jul 2025 12:24PM UTC coverage: 100.0%. Remained the same
16143130415

Pull #164

github

web-flow
Merge 8c78f97eb into befbe86b8
Pull Request #164: feat: test with php8.4

905 of 905 relevant lines covered (100.0%)

11.41 hits per line

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

100.0
/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
        if ($this->canGenerateUserData()) {
22✔
29
            $this->withAuth = true;
10✔
30
        }
31

32
        $this->createDump();
22✔
33
        $this->generateFixtures();
16✔
34
        $this->generateTests();
16✔
35
    }
36

37
    protected function getFixturesPath($fileName = null): string
38
    {
39
        $path = base_path("{$this->paths['tests']}/fixtures/{$this->getTestClassName()}");
16✔
40

41
        if (empty($fileName)) {
16✔
42
            return $path;
16✔
43
        }
44

45
        return "{$path}/{$fileName}";
16✔
46
    }
47

48
    protected function createDump(): void
49
    {
50
        if (!$this->isStubExists('dump')) {
22✔
51
            return;
4✔
52
        }
53

54
        $content = $this->getStub('dump', [
18✔
55
            'inserts' => $this->getInserts()
18✔
56
        ]);
18✔
57

58
        $this->createFixtureFolder();
12✔
59

60
        $dumpName = $this->getDumpName();
12✔
61

62
        file_put_contents($this->getFixturesPath($dumpName), $content);
12✔
63

64
        event(new SuccessCreateMessage("Created a new Test dump on path: "
12✔
65
            . "{$this->paths['tests']}/fixtures/{$this->getTestClassName()}/{$dumpName}"));
12✔
66
    }
67

68
    protected function getDumpName(): string
69
    {
70
        return 'dump.sql';
8✔
71
    }
72

73
    protected function getInserts(): array
74
    {
75
        $arrayModels = [$this->model];
18✔
76

77
        if ($this->withAuth) {
18✔
78
            array_unshift($arrayModels, 'User');
8✔
79
        }
80

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

94
    protected function isFactoryExists(string $modelName): bool
95
    {
96
        return $this->classExists('factories', "{$modelName}Factory");
18✔
97
    }
98

99
    protected function isMethodExists($modelName, $method): bool
100
    {
101
        $modelClass = $this->getModelClass($modelName);
12✔
102

103
        return method_exists($modelClass, $method);
12✔
104
    }
105

106
    protected function getModelsWithFactories($models): array
107
    {
108
        return array_filter($models, function ($model) {
14✔
109
            return $this->isFactoryExists($model);
8✔
110
        });
14✔
111
    }
112

113
    protected function getDumpValuesList($model): array
114
    {
115
        $values = $this->buildEntityObject($model);
12✔
116

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

126
            $value = (is_string($value)) ? "'{$value}'" : $value;
12✔
127
        });
12✔
128

129
        return $values;
12✔
130
    }
131

132
    protected function getFixtureValuesList($model): array
133
    {
134
        $values = $this->buildEntityObject($model);
16✔
135

136
        array_walk($values, function (&$value) {
16✔
137
            if ($value instanceof DateTime) {
16✔
138
                $value = "{$value->format('Y-m-d h:i:s')}";
10✔
139
            }
140
        });
16✔
141

142
        return $values;
16✔
143
    }
144

145
    protected function buildEntityObject($model): array
146
    {
147
        $modelFields = $this->getModelFields($model);
16✔
148
        $mockEntity = $this->getMockModel($model);
16✔
149

150
        $result = [];
16✔
151

152
        foreach ($modelFields as $field) {
16✔
153
            $value = Arr::get($mockEntity, $field, 1);
16✔
154

155
            $result[$field] = $value;
16✔
156
        }
157

158
        return $result;
16✔
159
    }
160

161
    protected function getModelFields($model): array
162
    {
163
        $modelClass = $this->getModelClass($model);
16✔
164

165
        return $this->filterBadModelField($modelClass::getFields());
16✔
166
    }
167

168
    protected function getMockModel($model): array
169
    {
170
        $hasFactory = $this->isFactoryExists($model);
16✔
171

172
        if (!$hasFactory) {
16✔
173
            return [];
6✔
174
        }
175

176
        $factoryNamespace = "{$this->getOrCreateNamespace('factories')}\\{$model}Factory";
10✔
177
        $factory = $factoryNamespace::new();
10✔
178

179
        return $factory
10✔
180
            ->make()
10✔
181
            ->toArray();
10✔
182
    }
183

184
    protected function generateFixtures(): void
185
    {
186
        $object = $this->getFixtureValuesList($this->model);
16✔
187
        $entity = Str::snake($this->model);
16✔
188

189
        $this->createFixtureFolder();
16✔
190

191
        foreach (self::FIXTURE_TYPES as $type => $modifications) {
16✔
192
            if ($this->isFixtureNeeded($type)) {
16✔
193
                foreach ($modifications as $modification) {
14✔
194
                    $excepts = ($modification === 'request') ? ['id'] : [];
14✔
195

196
                    $this->generateFixture("{$type}_{$entity}_{$modification}.json", Arr::except($object, $excepts));
14✔
197
                }
198
            }
199
        }
200
    }
201

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

208
        file_put_contents($fixturePath, $content);
8✔
209

210
        event(new SuccessCreateMessage("Created a new Test fixture on path: {$fixtureRelativePath}"));
8✔
211
    }
212

213
    protected function buildRelationsTree($models): array
214
    {
215
        foreach ($models as $model) {
18✔
216
            $relations = $this->getRelatedModels($model, $this->getTestClassName());
18✔
217
            $relationsWithFactories = $this->getModelsWithFactories($relations);
14✔
218

219
            if (empty($relationsWithFactories)) {
14✔
220
                continue;
14✔
221
            }
222

223
            if (in_array($model, $relationsWithFactories)) {
8✔
224
                $this->throwFailureException(
2✔
225
                    CircularRelationsFoundedException::class,
2✔
226
                    'Circular relations founded.',
2✔
227
                    'Please resolve you relations in models, factories and database.'
2✔
228
                );
2✔
229
            }
230

231
            $relatedModels = $this->buildRelationsTree($relationsWithFactories);
8✔
232

233
            $models = array_merge($relatedModels, $models);
8✔
234
        }
235

236
        return array_unique($models);
14✔
237
    }
238

239
    protected function canGenerateUserData(): bool
240
    {
241
        return $this->classExists('models', 'User')
22✔
242
            && $this->isMethodExists('User', 'getFields');
22✔
243
    }
244

245
    protected function createFixtureFolder(): void
246
    {
247
        $fixturePath = $this->getFixturesPath();
16✔
248

249
        if (!file_exists($fixturePath)) {
16✔
250
            mkdir($fixturePath, 0777, true);
16✔
251
        }
252
    }
253

254
    abstract protected function getTestClassName(): string;
255

256
    abstract protected function isFixtureNeeded($type): bool;
257

258
    abstract protected function generateTests(): void;
259

260
    private function filterBadModelField($fields): array
261
    {
262
        return array_diff($fields, [
16✔
263
            self::EMPTY_GUARDED_FIELD,
16✔
264
            self::CREATED_AT,
16✔
265
            self::UPDATED_AT,
16✔
266
        ]);
16✔
267
    }
268
}
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