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

Phiremock::setupExtraConnections()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 5
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 8
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
    /**
137
     * @deprecated Name is confusing, sounds like an assertion
138
     * @throws ClientExceptionInterface
139
     */
140
    public function didNotReceiveRequestsInRemoteService(): void
141
    {
142
        $this->dontHaveLoggedRequestsToRemoteService();
143
    }
144
145
    /** @throws ClientExceptionInterface */
146
    public function dontHaveLoggedRequestsToRemoteService(): void
147
    {
148
        $this->phiremock->resetRequestsCounter();
149
    }
150
151
    /**
152
     * @throws ClientExceptionInterface
153
     * @throws Exception
154
     */
155
    public function seeRemoteServiceReceived(int $times, ConditionsBuilder $builder): void
156
    {
157
        $requests = $this->phiremock->countExecutions($builder);
158
        if ($times !== $requests) {
159
            throw new Exception(
160
                "Request expected to be executed $times times, called $requests times instead"
161
            );
162
        }
163
    }
164
165
    /** @throws ClientExceptionInterface */
166
    public function grabRequestsMadeToRemoteService(ConditionsBuilder $builder): array
167
    {
168
        return $this->phiremock->listExecutions($builder);
169
    }
170
171
    /** @throws ClientExceptionInterface */
172
    public function setScenarioState(string $name, string $state): void
173
    {
174
        $this->phiremock->setScenarioState($name, $state);
175
    }
176
177
    private function createDebugMethod(): callable
178
    {
179
        return function (string $msg) : void {
180
            $this->debug($msg);
181
        };
182
    }
183
184
    /** @throws ConfigurationException */
185
    private function extraConfigsBeforeSuite(array $settings): void
186
    {
187
        if (!$this->isExtraConfig) {
188
            foreach ($this->extraConnections as $module) {
189
                $module->_beforeSuite($settings);
190
            }
191
        }
192
    }
193
194
    /** @throws ClientExceptionInterface */
195
    private function resetBeforeTestsIfConfigured(): void
196
    {
197
        if ($this->moduleConfig->isResetBeforeEachTest()) {
198
            $this->haveACleanSetupInRemoteService();
199
        }
200
    }
201
202
    /** @throws ClientExceptionInterface */
203
    private function loadExpectations(TestInterface $test): void
204
    {
205
        try {
206
            $expectations = $this->expectationsParser->getExpectations($test);
207
            if (!empty($expectations)) {
208
                foreach ($expectations as $expectation) {
209
                    $this->phiremock->createExpectationFromJson(
210
                        file_get_contents($expectation)
211
                    );
212
                }
213
            }
214
        } catch (ParseException $exception) {
215
            $this->debug('Error parsing expectation annotations: ' . $exception->getMessage());
216
        }
217
    }
218
219
    /** @throws ClientExceptionInterface */
220
    private function extraConfigsBefore(TestInterface $test): void
221
    {
222
        if (!$this->isExtraConfig) {
223
            foreach ($this->extraConnections as $connection) {
224
                $connection->_before($test);
225
            }
226
        }
227
    }
228
229
    /** @throws ModuleException */
230
    protected function setupExtraConnections(): void
231
    {
232
        if (!$this->isExtraConfig) {
233
            foreach ($this->moduleConfig->getExtraConnectionsConfigs() as $name => $connectionConfig) {
234
                if ($name === 'default') {
235
                    throw new ModuleException($this, 'The connection name "default" is reserved and can not be used for an extra connection');
236
                }
237
                $this->extraConnections[$name] = new self($this->moduleContainer, $connectionConfig->asArray(), true);
238
            }
239
        }
240
    }
241
}
242