Completed
Push — master ( 06b292...adafac )
by Nicolai
02:22
created

SetupGenerator::__get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
4
namespace SmartWeb\ModuleTesting\Codeception\SmartWeb;
5
6
use Illuminate\Contracts\Filesystem\Filesystem;
7
use InvalidArgumentException;
8
use SmartWeb\ModuleTesting\Codeception\GlobalConfiguration;
9
use SmartWeb\ModuleTesting\Codeception\GlobalConfigurationInterface;
10
use SmartWeb\ModuleTesting\Codeception\SetupGeneratorInterface;
11
use SmartWeb\ModuleTesting\Codeception\SetupInterface;
12
use SmartWeb\ModuleTesting\Codeception\SuiteInfoInterface;
13
use Symfony\Component\Process\Exception\ProcessFailedException;
14
use Symfony\Component\Process\Process;
15
use Symfony\Component\Yaml\Yaml;
16
use const DIRECTORY_SEPARATOR;
17
use function collect;
18
use function implode;
19
20
21
/**
22
 * Class Generator
23
 *
24
 * @package SmartWeb\Testing\Codeception
25
 */
26
class SetupGenerator implements SetupGeneratorInterface
27
{
28
    
29
    /**
30
     * @var SetupInterface
31
     */
32
    protected $setup;
33
    
34
    /**
35
     * @var Filesystem
36
     */
37
    protected $disk;
38
    
39
    /**
40
     * @var GlobalConfigurationInterface
41
     */
42
    protected $globalConfiguration;
43
    
44
    /**
45
     * Generator constructor.
46
     *
47
     * @param SetupInterface $setup
48
     */
49
    public function __construct(SetupInterface $setup)
50
    {
51
        $this->setup = $setup;
52
        $this->disk = $setup->getDisk();
53
    }
54
    
55
    /**
56
     * @param string $name
57
     *
58
     * @return mixed
59
     */
60
    public function __get($name)
61
    {
62
        if ($this->globalConfiguration->has($name)) {
63
            return $this->globalConfiguration->get($name);
64
        }
65
        
66
        throw new InvalidArgumentException("'{$name}' was not found in the global configuration");
67
    }
68
    
69
    /**
70
     * @param string[] $suites
71
     *
72
     * @return void
73
     */
74
    public function generate($suites = [])
75
    {
76
        $testDir = $this->setup->getTestsDir();
77
        $namespace = $this->setup->getNamespace() . '\\' . $testDir;
78
        
79
        $this->globalConfiguration = new GlobalConfiguration(
80
            [
81
                'namespace'  => $namespace,
82
                'actor'      => 'Tester',
83
                'paths'      => [
84
                    'tests'   => $testDir,
85
                    'data'    => $testDir . DIRECTORY_SEPARATOR . '_data',
86
                    'output'  => $testDir . DIRECTORY_SEPARATOR . '_output',
87
                    'support' => $testDir . DIRECTORY_SEPARATOR . '_support',
88
                    'envs'    => $testDir . DIRECTORY_SEPARATOR . '_envs',
89
                ],
90
                'extensions' => [
91
                    'enabled' => [
92
                        'Codeception\Extension\RunFailed',
93
                    ],
94
                ],
95
            ]
96
        );
97
        
98
        $this->createGlobalConfiguration();
99
        $this->createTestsDir();
100
        $this->createSupportingDirs();
101
        
102
        $this->createSuites($suites);
103
        $this->build();
104
    }
105
    
106
    /**
107
     * @param string $suite
108
     */
109
    public function createSuiteAndBuild(string $suite)
110
    {
111
        $this->generateSuite(new SuiteInfo($suite));
112
        $this->build();
113
    }
114
    
115
    /**
116
     * @param SuiteInfoInterface $suiteInfo
117
     *
118
     * @return void
119
     */
120
    protected function generateSuite(SuiteInfoInterface $suiteInfo)
121
    {
122
        $suite = $suiteInfo->getName();
123
        $actor = $suiteInfo->getActor();
124
        
125
        $this->executeCodeceptionCommand("g:suite {$suite} {$actor}");
126
    }
127
    
128
    /**
129
     * Build Actor classes
130
     *
131
     * @return void
132
     */
133
    protected function build()
134
    {
135
        $this->executeCodeceptionCommand('build');
136
    }
137
    
138
    /**
139
     * @param string $command
140
     */
141
    protected function executeCodeceptionCommand(string $command)
142
    {
143
        $command = $this->parseCommand(
144
            'vendor/bin/codecept',
145
            $command, "-c {$this->setup->getWorkDir()}", '--quiet'
146
        );
147
        
148
        $process = new Process($command);
149
        
150
        try {
151
            $process->mustRun();
152
            
153
            echo $process->getOutput();
154
        } catch (ProcessFailedException $e) {
155
            echo $e->getMessage();
156
        }
157
    }
158
    
159
    /**
160
     * @param string   $command
161
     * @param string[] ...$arguments
162
     *
163
     * @return string
164
     */
165
    protected function parseCommand(string $command, string ...$arguments) : string
166
    {
167
        return $command . ' ' . implode(' ', $arguments);
168
    }
169
    
170
    protected function createGlobalConfiguration()
171
    {
172
        $str = Yaml::dump($this->globalConfiguration->toArray(), 4);
173
        
174
        $this->createFile('codeception.yml', $str, true);
175
    }
176
    
177
    protected function createTestsDir()
178
    {
179
        $this->createDir($this->setup->getTestsDir(), true);
180
    }
181
    
182
    protected function createSupportingDirs()
183
    {
184
        foreach ($this->globalConfiguration->getSupportingDirs() as $dir) {
185
            $this->createEmptyDir($dir);
186
        }
187
    }
188
    
189
    /**
190
     * @param string[] $suites
191
     */
192
    protected function createSuites($suites)
193
    {
194
        collect($suites)
195
            ->mapInto(SuiteInfo::class)
196
            ->each(
197
                function (SuiteInfoInterface $suiteInfo)
198
                {
199
                    $this->generateSuite($suiteInfo);
200
                }
201
            );
202
    }
203
    
204
    /**
205
     * @param string          $path
206
     * @param string|resource $contents
207
     * @param bool            $inBasePath
208
     *
209
     * @return bool
210
     */
211 View Code Duplication
    protected function createFile(string $path, $contents, bool $inBasePath = false) : bool
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
212
    {
213
        $path = $this->getPath($path, $inBasePath);
214
        
215
        if (!$this->disk->exists($path)) {
216
            return $this->disk->put($path, $contents);
217
        }
218
        
219
        return false;
220
    }
221
    
222
    /**
223
     * @param string $path
224
     * @param bool   $inBasePath
225
     *
226
     * @return bool
227
     */
228 View Code Duplication
    protected function createDir(string $path, bool $inBasePath = false) : bool
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229
    {
230
        $path = $this->getPath($path, $inBasePath);
231
        
232
        if (!$this->disk->exists($path)) {
233
            return $this->disk->makeDirectory($path);
234
        }
235
        
236
        return false;
237
    }
238
    
239
    /**
240
     * @param string $path
241
     * @param bool   $inBasePath
242
     *
243
     * @return string
244
     */
245
    protected function getPath(string $path, bool $inBasePath = false) : string
246
    {
247
        $pathPrefix = $this->setup->getWorkDir() . DIRECTORY_SEPARATOR;
248
        
249
        return $inBasePath
250
            ? $pathPrefix . $path
251
            : $pathPrefix . $this->setup->getTestsDir() . DIRECTORY_SEPARATOR . $path;
252
    }
253
    
254
    /**
255
     * @param string $path
256
     * @param bool   $inBasePath
257
     *
258
     * @return bool
259
     */
260
    protected function createEmptyDir(string $path, bool $inBasePath = false) : bool
261
    {
262
        if ($this->createDir($path, $inBasePath)) {
263
            return $this->createGitKeep($path, $inBasePath);
264
        }
265
        
266
        return false;
267
    }
268
    
269
    /**
270
     * @param string $dir
271
     * @param bool   $inBasePath
272
     *
273
     * @return bool
274
     */
275
    protected function createGitKeep(string $dir, bool $inBasePath = false) : bool
276
    {
277
        return $this->createFile($dir . DIRECTORY_SEPARATOR . '.gitkeep', '', $inBasePath);
278
    }
279
    
280
}