GherkinToDusk   B
last analyzed

Complexity

Total Complexity 47

Size/Duplication

Total Lines 361
Duplicated Lines 12.47 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 89.16%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 47
c 3
b 0
f 0
lcom 1
cbo 11
dl 45
loc 361
ccs 148
cts 166
cp 0.8916
rs 8.439

28 Methods

Rating   Name   Duplication   Size   Complexity  
B appendFeatures() 21 21 5
B initializeFeature() 24 24 5
A featureToBrowser() 0 10 1
A featureAppendToBrowser() 0 8 1
A featureAppendToUnit() 0 8 1
A featureToUnit() 0 10 1
A isComponent() 0 4 1
A setComponent() 0 4 1
A getFeatureContent() 0 4 1
A setFeatureContent() 0 4 1
A loadFileContent() 0 5 1
A passThroughParser() 0 4 1
A getParsedFeature() 0 4 1
A setParsedFeature() 0 4 1
A breakIntoMethods() 0 4 1
A iterateOverScenariosAndBuildUpClassMethods() 0 16 2
A buildOutSteps() 0 11 2
A getDuskClassAndMethods() 0 4 1
A setDuskClassAndMethods() 0 4 1
A getWriteBrowserTest() 0 9 2
A setWriteBrowserTest() 0 9 2
A getWriteUnitTest() 0 9 2
A setWriteUnitTest() 0 9 2
A getAppendUnitTest() 0 9 2
A setAppendUnitTest() 0 9 2
A checkIfFileExists() 0 8 2
A getAppendBrowserTest() 0 8 2
A setAppendBrowserTest() 0 9 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like GherkinToDusk often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GherkinToDusk, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace GD;
4
5
use Behat\Gherkin\Gherkin;
6
use Behat\Gherkin\Keywords\CucumberKeywords;
7
use Behat\Gherkin\Lexer;
8
use Behat\Gherkin\Loader\GherkinFileLoader;
9
use Behat\Gherkin\Loader\YamlFileLoader;
10
use Behat\Gherkin\Parser;
11
use GD\Exceptions\MustSetFileNameAndPath;
12
use GD\Helpers\AppendBrowserFile;
13
use GD\Helpers\AppendFile;
14
use GD\Helpers\BuildOutContent;
15
use GD\Helpers\WriteBrowserFile;
16
use GD\Helpers\WritePHPUnitFile;
17
use Illuminate\Filesystem\Filesystem;
18
use Illuminate\Support\Facades\App;
19
use Symfony\Component\Yaml\Yaml;
20
21
class GherkinToDusk extends BaseGherkinToDusk
22
{
23
    use BuildOutContent;
24
25
    protected $component = false;
26
27
    protected $string_contents = null;
28
29
    /**
30
     * Yml Content of a test yml
31
     * @var string
32
     */
33
    protected $feature_content;
34
35
    /**
36
     * @var \Behat\Gherkin\Node\FeatureNode
37
     */
38
    protected $parsed_feature;
39
40
    /**
41
     *
42
     */
43
    protected $dusk_class_and_methods;
44
45
46
    /**
47
     * @var WritePHPUnitFile
48
     */
49
    protected $write_unit_test;
50
51
    /**
52
     * @var AppendFile
53
     */
54
    protected $append_unit_test;
55
56
    /**
57
     * @var WriteBrowserFile
58
     */
59
    protected $write_browser_test;
60
61
    /**
62
     * @var \GD\Helpers\AppendBrowserFile
63
     */
64
    protected $append_browser_test;
65
    
66 24 View Code Duplication
    public function appendFeatures()
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...
67
    {
68 24
        $this->loadFileContent();
69 24
        $this->buildDuskTestName();
70 24
        $this->passThroughParser();
71 24
        $this->breakIntoMethods();
72
73 24
        switch ($this->context) {
74 24
            case 'unit':
75 24
            case 'domain':
76 12
                $this->featureAppendToUnit();
77 9
                break;
78 12
            case 'ui':
79 12
            case 'browser':
80 12
                $this->featureAppendToBrowser();
81 9
                break;
82
            default:
83
                //more coming soon
84
                break;
85 12
        }
86 18
    }
87
88 27 View Code Duplication
    public function initializeFeature()
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...
89
    {
90 27
        $this->loadFileContent();
91
92 27
        $this->buildDuskTestName();
93
94 27
        $this->passThroughParser();
95
96 27
        $this->breakIntoMethods();
97
98 27
        switch ($this->context) {
99 27
            case 'unit':
100 27
            case 'domain':
101 21
                $this->featureToUnit();
102 18
                break;
103 6
            case 'ui':
104 6
            case 'browser':
105 6
                $this->featureToBrowser();
106 6
                break;
107
            default:
108
                //more coming soon
109
                break;
110 16
        }
111 24
    }
112
113 6
    protected function featureToBrowser()
114
    {
115 6
        $this->checkIfFileExists();
116
117 6
        $this->getWriteBrowserTest()->writeTest(
118 6
            $this->getDestinationFolderRoot(),
119 6
            $this->getDuskTestName(),
120 6
            $this->getDuskClassAndMethods()
121 4
        );
122 6
    }
123
124 12
    protected function featureAppendToBrowser()
125
    {
126 12
        $this->getAppendBrowserTest()->writeTest(
127 12
            $this->getDestinationFolderRoot(),
128 12
            $this->getDuskTestName(),
129 12
            $this->getDuskClassAndMethods()
130 8
        );
131 9
    }
132
133 12
    protected function featureAppendToUnit()
134
    {
135 12
        $this->getAppendUnitTest()->writeTest(
136 12
            $this->getDestinationFolderRoot(),
137 12
            $this->getDuskTestName(),
138 12
            $this->getDuskClassAndMethods()
139 8
        );
140 9
    }
141
    
142 21
    protected function featureToUnit()
143
    {
144 21
        $this->checkIfFileExists();
145
146 18
        $this->getWriteUnitTest()->writeTest(
147 18
            $this->getDestinationFolderRoot(),
148 18
            $this->getDuskTestName(),
149 18
            $this->getDuskClassAndMethods()
150 12
        );
151 18
    }
152
153
154
    /**
155
     * @return boolean
156
     */
157
    public function isComponent()
158
    {
159
        return $this->component;
160
    }
161
162
    /**
163
     * @param boolean $component
164
     */
165
    public function setComponent($component)
166
    {
167
        $this->component = $component;
168
    }
169
170
    /**
171
     * @return mixed
172
     */
173 3
    public function getFeatureContent()
174
    {
175 3
        return $this->feature_content;
176
    }
177
178
    /**
179
     * @param mixed $feature_content
180
     */
181
    public function setFeatureContent($feature_content)
182
    {
183
        $this->feature_content = $feature_content;
184
    }
185
186 51
    private function loadFileContent()
187
    {
188 51
        $this->feature_content =
189 51
            $this->getFilesystem()->get($this->getFullPathToFileAndFileName());
190 51
    }
191
192 51
    private function passThroughParser()
193
    {
194 51
        $this->parsed_feature = $this->getParser()->parse($this->feature_content);
195 51
    }
196
197
    /**
198
     * @return \Behat\Gherkin\Node\FeatureNode
199
     */
200 3
    public function getParsedFeature()
201
    {
202 3
        return $this->parsed_feature;
203
    }
204
205
    /**
206
     * @param \Behat\Gherkin\Node\FeatureNode $parsed_feature
207
     */
208
    public function setParsedFeature($parsed_feature)
209
    {
210
        $this->parsed_feature = $parsed_feature;
211
    }
212
213 51
    private function breakIntoMethods()
214
    {
215 51
        $this->iterateOverScenariosAndBuildUpClassMethods();
216 51
    }
217
218 51
    private function iterateOverScenariosAndBuildUpClassMethods()
219
    {
220
        /** @var  $feature \Behat\Gherkin\Node\ScenarioNode */
221 51
        foreach ($this->parsed_feature->getScenarios() as $scenario_index => $scenario) {
222 51
            $parent_method_name = ucfirst(camel_case($scenario->getTitle()));
223
224 51
            $parent_method_name_camelized_and_prefix_test = sprintf('test%s', $parent_method_name);
225
226 51
            $this->dusk_class_and_methods[$scenario_index] = [
227 51
                'parent' => $parent_method_name_camelized_and_prefix_test,
228 51
                'parent_content' => $this->getParentLevelContent($parent_method_name_camelized_and_prefix_test)
229 34
            ];
230
231 51
            $this->buildOutSteps($scenario, $scenario_index);
232 34
        }
233 51
    }
234
235
    /**
236
     * @param $scenario \Behat\Gherkin\Node\ScenarioNode
237
     */
238 51
    protected function buildOutSteps($scenario, $scenario_index)
239
    {
240 51
        foreach ($scenario->getSteps() as $step_index => $step) {
241 51
            $method_name = camel_case(sprintf("%s %s", $step->getKeyword(), $step->getText()));
242 51
            $step_method_name_camalized = camel_case(sprintf("%s %s", $step->getKeyword(), $step->getText()));
243 51
            $this->dusk_class_and_methods[$scenario_index]['steps'][$step_index]['name'] =
244
                $method_name;
245 51
            $this->dusk_class_and_methods[$scenario_index]['steps'][$step_index] =
246 51
                $this->getStepLevelContent($step_method_name_camalized);
247 34
        }
248 51
    }
249
250
251
252
    /**
253
     * @return mixed
254
     */
255 48
    public function getDuskClassAndMethods()
256
    {
257 48
        return $this->dusk_class_and_methods;
258
    }
259
260
    /**
261
     * @param mixed $dusk_class_and_methods
262
     */
263
    public function setDuskClassAndMethods($dusk_class_and_methods)
264
    {
265
        $this->dusk_class_and_methods = $dusk_class_and_methods;
266
    }
267
268
269
270 6
    public function getWriteBrowserTest()
271
    {
272
273 6
        if (!$this->write_browser_test) {
274 6
            $this->setWriteBrowserTest();
275 4
        }
276
277 6
        return $this->write_browser_test;
278
    }
279
280
    /**
281
     * @param null $write_browser_test
282
     * @return GherkinToDusk
283
     * @internal param WritePHPUnitFile $write_unit_test
284
     */
285 6
    public function setWriteBrowserTest($write_browser_test = null)
286
    {
287 6
        if (!$write_browser_test) {
288 6
            $write_browser_test = new WriteBrowserFile();
289 4
        }
290
291 6
        $this->write_browser_test = $write_browser_test;
292 6
        return $this;
293
    }
294
295
296 18
    public function getWriteUnitTest()
297
    {
298
299 18
        if (!$this->write_unit_test) {
300 18
            $this->setWriteUnitTest();
301 12
        }
302
303 18
        return $this->write_unit_test;
304
    }
305
306
    /**
307
     * @param WritePHPUnitFile $write_unit_test
308
     * @return GherkinToDusk
309
     */
310 18
    public function setWriteUnitTest($write_unit_test = null)
311
    {
312 18
        if (!$write_unit_test) {
313 18
            $write_unit_test = new WritePHPUnitFile();
314 12
        }
315
316 18
        $this->write_unit_test = $write_unit_test;
317 18
        return $this;
318
    }
319
320
    /**
321
     * @return $append_unit_test AppendFile
0 ignored issues
show
Documentation introduced by
The doc-type $append_unit_test could not be parsed: Unknown type name "$append_unit_test" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
322
     */
323 12
    public function getAppendUnitTest()
324
    {
325
326 12
        if (!$this->append_unit_test) {
327 12
            $this->setAppendUnitTest();
328 8
        }
329
330 12
        return $this->append_unit_test;
331
    }
332
333
    /**
334
     * @param AppendFile $append_unit_test
335
     * @return GherkinToDusk
336
     */
337 12
    public function setAppendUnitTest($append_unit_test = null)
338
    {
339 12
        if (!$append_unit_test) {
340 12
            $append_unit_test = new AppendFile();
341 8
        }
342
343 12
        $this->append_unit_test = $append_unit_test;
344 12
        return $this;
345
    }
346
347 27
    private function checkIfFileExists()
348
    {
349 27
        if ($this->filesystem->exists($this->fullPathToDestinationFile())) {
350 3
            $path = $this->fullPathToDestinationFile();
351 3
            $message = sprintf("The test file exists already %s please use `append` command", $path);
352 3
            throw new \GD\Exceptions\TestFileExists($message);
353
        }
354 24
    }
355
356
    /**
357
     * @return Helpers\AppendBrowserFile
358
     */
359 12
    public function getAppendBrowserTest()
360
    {
361 12
        if (!$this->append_browser_test) {
362 12
            $this->setAppendBrowserTest();
363 8
        }
364
365 12
        return $this->append_browser_test;
366
    }
367
368
    /**
369
     * @param Helpers\AppendBrowserFile $append_browser_test
370
     * @return $this
371
     */
372 12
    public function setAppendBrowserTest($append_browser_test = null)
373
    {
374 12
        if (!$append_browser_test) {
375 12
            $append_browser_test = new AppendBrowserFile();
376 8
        }
377
378 12
        $this->append_browser_test = $append_browser_test;
379 12
        return $this;
380
    }
381
}
382