Passed
Pull Request — master (#3)
by Mariano
01:30
created

Phiremock::extraConfigsBeforeSuite()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 5
rs 10
1
<?php
2
/**
3
 * This file is part of phiremock-codeception-module.
4
 *
5
 * phiremock-codeception-module is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * phiremock-codeception-module is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with phiremock-codeception-module.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
namespace Codeception\Module;
20
21
use Codeception\Exception\ConfigurationException;
22
use Codeception\Exception\ModuleException;
23
use Codeception\Exception\ParseException;
24
use Codeception\Lib\ModuleContainer;
25
use Codeception\Module as CodeceptionModule;
26
use Codeception\TestInterface;
27
use Exception;
28
use InvalidArgumentException;
29
use Mcustiel\Phiremock\Client\Connection\Scheme;
30
use Mcustiel\Phiremock\Client\Utils\ConditionsBuilder;
31
use Mcustiel\Phiremock\Codeception\Util\Config;
32
use Mcustiel\Phiremock\Codeception\Util\ExpectationAnnotationParser;
33
use Mcustiel\Phiremock\Domain\Expectation;
34
use Psr\Http\Client\ClientExceptionInterface;
35
36
class Phiremock extends CodeceptionModule
37
{
38
    /** @var array */
39
    protected $config = Config::DEFAULT_CONFIG;
40
41
    /** @var \Mcustiel\Phiremock\Client\Phiremock */
42
    private $phiremock;
43
44
    /** @var ExpectationAnnotationParser */
45
    private $expectationsParser;
46
47
    /** @var Config */
48
    private $moduleConfig;
49
50
    /** @var Phiremock[] */
51
    private $extraConnections = [];
52
53
    /** @var bool */
54
    private $isExtraConfig;
55
56
    /** @throws ModuleException */
57
    public function __construct(ModuleContainer $moduleContainer, $config = null, bool $isExtra = false)
58
    {
59
        parent::__construct($moduleContainer, $config);
60
        $this->isExtraConfig = $isExtra;
61
        $this->moduleConfig = new Config($this->config, $this->createDebugMethod());
62
        $this->setupExtraConnections();
63
    }
64
65
    /**
66
     * @throws ConfigurationException
67
     * @throws Exception
68
     */
69
    public function _beforeSuite($settings = [])
70
    {
71
        $this->config = array_merge($this->moduleConfig->asArray(), $settings);
72
        $this->moduleConfig = new Config($this->config, $this->createDebugMethod());
73
74
        $this->phiremock = $this->moduleConfig->getClientFactory()->createPhiremockClient(
75
            $this->moduleConfig->getHost(),
76
            $this->moduleConfig->getPort(),
77
            new Scheme($this->moduleConfig->isSecure() ? Scheme::HTTPS: Scheme::HTTP)
78
        );
79
        $this->expectationsParser = new ExpectationAnnotationParser(
80
            $this->moduleConfig->getExpectationsPath()
81
        );
82
        $this->extraConfigsBeforeSuite($settings);
83
    }
84
85
    /** @throws ClientExceptionInterface */
86
    public function _before(TestInterface $test)
87
    {
88
        $this->resetBeforeTestsIfConfigured();
89
        $this->loadExpectations($test);
90
        parent::_before($test);
91
        $this->extraConfigsBefore($test);
92
    }
93
94
    /** @throws ModuleException */
95
    public function takeConnection(string $name): Phiremock
96
    {
97
        if ($this->isExtraConfig) {
98
            throw new ModuleException($this, 'Trying to take a connection from an extra connection');
99
        }
100
        if ($name === 'default') {
101
            return $this;
102
        }
103
        if (!isset($this->extraConnections[$name])) {
104
            throw new InvalidArgumentException(
105
                sprintf('Connection %s does not exist', $name)
106
            );
107
        }
108
        return $this->extraConnections[$name];
109
    }
110
111
    /** @throws ClientExceptionInterface */
112
    public function expectARequestToRemoteServiceWithAResponse(Expectation $expectation): void
113
    {
114
        $this->phiremock->createExpectation($expectation);
115
    }
116
117
    /** @throws ClientExceptionInterface */
118
    public function haveACleanSetupInRemoteService(): void
119
    {
120
        $this->phiremock->reset();
121
    }
122
123
    /** @throws ClientExceptionInterface */
124
    public function dontExpectRequestsInRemoteService(): void
125
    {
126
        $this->phiremock->clearExpectations();
127
        $this->phiremock->resetRequestsCounter();
128
    }
129
130
    /** @throws ClientExceptionInterface */
131
    public function haveCleanScenariosInRemoteService(): void
132
    {
133
        $this->phiremock->resetScenarios();
134
    }
135
136
    /** @deprecated Name is confusing, sounds like an assertion */
137
    public function didNotReceiveRequestsInRemoteService(): void
138
    {
139
        $this->dontHaveLoggedRequestsToRemoteService();
140
    }
141
142
    /** @throws ClientExceptionInterface */
143
    public function dontHaveLoggedRequestsToRemoteService(): void
144
    {
145
        $this->phiremock->resetRequestsCounter();
146
    }
147
148
    /**
149
     * @throws ClientExceptionInterface
150
     * @throws Exception
151
     */
152
    public function seeRemoteServiceReceived(int $times, ConditionsBuilder $builder): void
153
    {
154
        $requests = $this->phiremock->countExecutions($builder);
155
        if ($times !== $requests) {
156
            throw new Exception(
157
                "Request expected to be executed $times times, called $requests times instead"
158
            );
159
        }
160
    }
161
162
    /** @throws ClientExceptionInterface */
163
    public function grabRequestsMadeToRemoteService(ConditionsBuilder $builder): array
164
    {
165
        return $this->phiremock->listExecutions($builder);
166
    }
167
168
    /** @throws ClientExceptionInterface */
169
    public function setScenarioState(string $name, string $state): void
170
    {
171
        $this->phiremock->setScenarioState($name, $state);
172
    }
173
174
    private function createDebugMethod(): callable
175
    {
176
        return function (string $msg) : void {
177
            $this->debug($msg);
178
        };
179
    }
180
181
    /** @throws ConfigurationException */
182
    private function extraConfigsBeforeSuite(array $settings): void
183
    {
184
        if (!$this->isExtraConfig) {
185
            foreach ($this->extraConnections as $module) {
186
                $module->_beforeSuite($settings);
187
            }
188
        }
189
    }
190
191
    /** @throws ClientExceptionInterface */
192
    private function resetBeforeTestsIfConfigured(): void
193
    {
194
        if ($this->moduleConfig->isResetBeforeEachTest()) {
195
            $this->haveACleanSetupInRemoteService();
196
        }
197
    }
198
199
    /** @throws ClientExceptionInterface */
200
    private function loadExpectations(TestInterface $test): void
201
    {
202
        try {
203
            $expectations = $this->expectationsParser->getExpectations($test);
204
            if (!empty($expectations)) {
205
                foreach ($expectations as $expectation) {
206
                    $this->phiremock->createExpectationFromJson(
207
                        file_get_contents($expectation)
208
                    );
209
                }
210
            }
211
        } catch (ParseException $exception) {
212
            $this->debug('Error parsing expectation annotations: ' . $exception->getMessage());
213
        }
214
    }
215
216
    /** @throws ClientExceptionInterface */
217
    private function extraConfigsBefore(TestInterface $test): void
218
    {
219
        if (!$this->isExtraConfig) {
220
            foreach ($this->extraConnections as $connection) {
221
                $connection->_before($test);
222
            }
223
        }
224
    }
225
226
    protected function setupExtraConnections(): void
227
    {
228
        if (!$this->isExtraConfig) {
229
            foreach ($this->moduleConfig->getExtraConnectionsConfigs() as $name => $connectionConfig) {
230
                if ($name === 'default') {
231
                    throw new ModuleException($this, 'The connection name "default" is reserved and can not be used for an extra connection');
232
                }
233
                $this->extraConnections[$name] = new self($this->moduleContainer, $connectionConfig->asArray(), true);
234
            }
235
        }
236
    }
237
}
238