Completed
Push — master ( f8ba2f...77b1ae )
by Kamil
04:21 queued 01:20
created

TestContext::thereIsFeatureFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the TestContext package.
5
 *
6
 * (c) FriendsOfBehat
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FriendsOfBehat\TestContext\Context;
13
14
use Behat\Behat\Context\Context;
15
use Symfony\Component\Filesystem\Filesystem;
16
use Symfony\Component\Process\PhpExecutableFinder;
17
use Symfony\Component\Process\Process;
18
19
/**
20
 * @author Kamil Kokot <[email protected]>
21
 */
22
final class TestContext implements Context
23
{
24
    /**
25
     * @var string
26
     */
27
    private static $workingDir;
28
29
    /**
30
     * @var Filesystem
31
     */
32
    private static $filesystem;
33
34
    /**
35
     * @var string
36
     */
37
    private static $phpBin;
38
39
    /**
40
     * @var Process
41
     */
42
    private $process;
43
44
    /**
45
     * @BeforeFeature
46
     */
47
    public static function beforeFeature()
48
    {
49
        self::$workingDir = sprintf('%s/%s/', sys_get_temp_dir(), uniqid('', true));
50
        self::$filesystem = new Filesystem();
51
        self::$phpBin = self::findPhpBinary();
52
    }
53
54
    /**
55
     * @BeforeScenario
56
     */
57
    public function beforeScenario()
58
    {
59
        self::$filesystem->remove(self::$workingDir);
60
        self::$filesystem->mkdir(self::$workingDir, 0777);
61
    }
62
63
    /**
64
     * @AfterScenario
65
     */
66
    public function afterScenario()
67
    {
68
        self::$filesystem->remove(self::$workingDir);
69
    }
70
71
    /**
72
     * @Given /^a Behat configuration containing(?: "([^"]+)"|:)$/
73
     */
74
    public function thereIsConfiguration($content)
75
    {
76
        $this->thereIsFile('behat.yml', $content);
77
    }
78
79
    /**
80
     * @Given /^a (?:.+ |)file "([^"]+)" containing(?: "([^"]+)"|:)$/
81
     */
82
    public function thereIsFile($file, $content)
83
    {
84
        self::$filesystem->dumpFile(self::$workingDir . '/' . $file, (string) $content);
85
    }
86
87
    /**
88
     * @Given /^a feature file containing(?: "([^"]+)"|:)$/
89
     */
90
    public function thereIsFeatureFile($content)
91
    {
92
        $this->thereIsFile(sprintf('features/%s.feature', md5(uniqid(null, true))), $content);
93
    }
94
95
    /**
96
     * @When /^I run Behat$/
97
     */
98
    public function iRunBehat()
99
    {
100
        $this->process = new Process(sprintf('%s %s --strict', self::$phpBin, escapeshellarg(BEHAT_BIN_PATH)));
101
        $this->process->setWorkingDirectory(self::$workingDir);
102
        $this->process->start();
103
        $this->process->wait();
104
    }
105
106
    /**
107
     * @Then /^it should pass$/
108
     */
109 View Code Duplication
    public function itShouldPass()
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...
110
    {
111
        if (0 === $this->getProcessExitCode()) {
112
            return;
113
        }
114
115
        throw new \DomainException(
116
            'Behat was expecting to pass, but failed with the following output:' . PHP_EOL . PHP_EOL . $this->getProcessOutput()
117
        );
118
    }
119
120
    /**
121
     * @Then /^it should pass with(?: "([^"]+)"|:)$/
122
     */
123
    public function itShouldPassWith($expectedOutput)
124
    {
125
        $this->itShouldPass();
126
        $this->assertOutputMatches((string) $expectedOutput);
127
    }
128
129
    /**
130
     * @Then /^it should fail$/
131
     */
132 View Code Duplication
    public function itShouldFail()
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...
133
    {
134
        if (0 !== $this->getProcessExitCode()) {
135
            return;
136
        }
137
138
        throw new \DomainException(
139
            'Behat was expecting to fail, but passed with the following output:' . PHP_EOL . PHP_EOL . $this->getProcessOutput()
140
        );
141
    }
142
143
    /**
144
     * @Then /^it should fail with(?: "([^"]+)"|:)$/
145
     */
146
    public function itShouldFailWith($expectedOutput)
147
    {
148
        $this->itShouldFail();
149
        $this->assertOutputMatches((string) $expectedOutput);
150
    }
151
152
    /**
153
     * @Then /^it should end with(?: "([^"]+)"|:)$/
154
     */
155
    public function itShouldEndWith($expectedOutput)
156
    {
157
        $this->assertOutputMatches((string) $expectedOutput);
158
    }
159
160
    /**
161
     * @param string $expectedOutput
162
     */
163
    private function assertOutputMatches($expectedOutput)
164
    {
165
        $pattern = '/' . preg_quote($expectedOutput, '/') . '/sm';
166
        $output = $this->getProcessOutput();
167
168
        $result = preg_match($pattern, $output);
169
        if (false === $result) {
170
            throw new \InvalidArgumentException('Invalid pattern given:' . $pattern);
171
        }
172
173
        if (0 === $result) {
174
            throw new \DomainException(sprintf(
175
                'Pattern "%s" does not match the following output:' . PHP_EOL . PHP_EOL . '%s',
176
                $pattern,
177
                $output
178
            ));
179
        }
180
    }
181
182
    /**
183
     * @return string
184
     */
185
    private function getProcessOutput()
186
    {
187
        $this->assertProcessIsAvailable();
188
189
        return $this->process->getErrorOutput() . $this->process->getOutput();
190
    }
191
192
    /**
193
     * @return int
194
     */
195
    private function getProcessExitCode()
196
    {
197
        $this->assertProcessIsAvailable();
198
199
        return $this->process->getExitCode();
200
    }
201
202
    /**
203
     * @throws \BadMethodCallException
204
     */
205
    private function assertProcessIsAvailable()
206
    {
207
        if (null === $this->process) {
208
            throw new \BadMethodCallException('Behat proccess cannot be found. Did you run it before making assertions?');
209
        }
210
    }
211
212
    /**
213
     * @return string
214
     *
215
     * @throws \RuntimeException
216
     */
217
    private static function findPhpBinary()
218
    {
219
        $phpBinary = (new PhpExecutableFinder())->find();
220
        if (false === $phpBinary) {
221
            throw new \RuntimeException('Unable to find the PHP executable.');
222
        }
223
224
        return $phpBinary;
225
    }
226
}
227