Passed
Push — master ( 8ea059...6e0516 )
by Evgeniy
03:00
created

Pact::startServer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace SmartGamma\Behat\PactExtension\Infrastructure;
4
5
use GuzzleHttp\Exception\ClientException;
6
use GuzzleHttp\Psr7\Uri;
7
use PhpPact\Broker\Service\BrokerHttpClient;
8
use PhpPact\Consumer\InteractionBuilder;
9
use PhpPact\Http\GuzzleClient;
10
use PhpPact\Standalone\MockService\MockServerConfig;
11
use PhpPact\Standalone\MockService\MockServerEnvConfig;
12
use PhpPact\Standalone\MockService\Service\MockServerHttpService;
13
use SmartGamma\Behat\PactExtension\Infrastructure\Factory\InteractionBuilderFactory;
14
use SmartGamma\Behat\PactExtension\Infrastructure\Factory\MockServerFactory;
15
use SmartGamma\Behat\PactExtension\Infrastructure\Factory\MockServerHttpServiceFactory;
16
use SmartGamma\Behat\PactExtension\Infrastructure\Interaction\InteractionCompositor;
17
use SmartGamma\Behat\PactExtension\Infrastructure\Interaction\InteractionRequestDTO;
18
use SmartGamma\Behat\PactExtension\Infrastructure\Interaction\InteractionResponseDTO;
19
20
class Pact
21
{
22
    /**
23
     * @var MockServerFactory
24
     */
25
    private $mockServerFactory;
26
27
    /**
28
     * @var InteractionBuilderFactory
29
     */
30
    private $interactionBuilderFactory;
31
32
    /**
33
     * @var
34
     */
35
    private $mockServerHttpServiceFactory;
36
37
38
    /**
39
     * @var InteractionCompositor
40
     */
41
    private $interactionCompositor;
42
43
    /**
44
     * @var array
45
     */
46
    private $config = [];
47
48
    /**
49
     * @var array
50
     */
51
    private $providersConfig = [];
52
53
    /**
54
     * @var string
55
     */
56
    private $tag;
57
58
    /**
59
     * @var array
60
     */
61
    private $servers = [];
62
63
    /**
64
     * @var array
65
     */
66
    private $mockServerConfigs = [];
67
68
    /**
69
     * @var MockServerHttpService[]
70
     */
71
    private $mockServerHttpServices = [];
72
73
    /**
74
     * @var array
75
     */
76
    private $startedServers = [];
77
78
    /**
79
     * @var array
80
     */
81
    private $builders = [];
82
83
    /**
84
     * Pact constructor.
85
     *
86
     * @param MockServerFactory         $mockServerFactory
87
     * @param InteractionBuilderFactory $interactionBuilderFactory
88
     * @param InteractionCompositor     $interactionCompositor
89
     * @param array                     $config
90
     * @param array                     $providersConfig
91
     */
92 8
    public function __construct(
93
        MockServerFactory $mockServerFactory,
94
        InteractionBuilderFactory $interactionBuilderFactory,
95
        MockServerHttpServiceFactory $mockServerHttpServiceFactory,
96
        InteractionCompositor $interactionCompositor,
97
        array $config,
98
        array $providersConfig
99
    )
100
    {
101 8
        $this->mockServerFactory            = $mockServerFactory;
102 8
        $this->interactionBuilderFactory    = $interactionBuilderFactory;
103 8
        $this->mockServerHttpServiceFactory = $mockServerHttpServiceFactory;
104 8
        $this->interactionCompositor        = $interactionCompositor;
105 8
        $this->config                       = $config;
106 8
        $this->providersConfig              = $providersConfig;
107 8
        $this->tag                          = $this->getPactTag();
108 8
        $this->registerMockServerConfigs();
109 8
        $this->registerMockServerHttpServices();
110 8
        $this->registerServers();
111 8
        $this->registerBuilders();
112
    }
113
114
115 8
    private function registerMockServerConfigs(): void
116
    {
117 8
        foreach ($this->providersConfig as $providerName => $providerConfig) {
118 8
            $this->mockServerConfigs[$providerName] = $this->createMockServerConfig($providerConfig);
119
        }
120
    }
121
122 8
    private function registerMockServerHttpServices(): void
123
    {
124 8
        foreach ($this->mockServerConfigs as $providerName => $mockServerConfig) {
125 8
            $this->mockServerHttpServices[$providerName] = $this->mockServerHttpServiceFactory->create($mockServerConfig);
126
        }
127
    }
128
129 8
    private function registerServers(): void
130
    {
131 8
        foreach ($this->mockServerConfigs as $providerName => $mockServerConfig) {
132 8
            $this->servers[$providerName] = $this->mockServerFactory->create($mockServerConfig);
133
        }
134
    }
135
136
137 8
    private function registerBuilders(): void
138
    {
139 8
        foreach ($this->mockServerConfigs as $providerName => $mockServerConfig) {
140 8
            $this->builders[$providerName] = $this->interactionBuilderFactory->create($mockServerConfig);
141
        }
142
    }
143
144
    /**
145
     * @param array $providerConfig
146
     *
147
     * @return MockServerConfig
148
     */
149 8
    private function createMockServerConfig(array $providerConfig): MockServerConfig
150
    {
151 8
        $config = new MockServerConfig();
152
        $config
153 8
            ->setHost($providerConfig['PACT_MOCK_SERVER_HOST'])
154 8
            ->setPort($providerConfig['PACT_MOCK_SERVER_PORT'])
155 8
            ->setProvider($providerConfig['PACT_PROVIDER_NAME'])
156 8
            ->setConsumer($this->config['PACT_CONSUMER_NAME'])
157 8
            ->setPactDir($this->config['PACT_OUTPUT_DIR'])
158 8
            ->setCors($this->config['PACT_CORS'])
159 8
            ->setHealthCheckTimeout($this->config['PACT_MOCK_SERVER_HEALTH_CHECK_TIMEOUT'])
160 8
            ->setPactSpecificationVersion(MockServerEnvConfig::DEFAULT_SPECIFICATION_VERSION);
161
162 8
        return $config;
163
    }
164
165
    /**
166
     * @param string $consumerVersion
167
     *
168
     * @return bool
169
     */
170 2
    public function finalize(string $consumerVersion): bool
0 ignored issues
show
Coding Style introduced by
function finalize() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
171
    {
172 2
        foreach ($this->mockServerConfigs as $providerName => $mockServerConfig) {
173 2
            if (!isset($this->startedServers[$providerName])) {
174 1
                echo 'Ignoring ' . $providerName . ' as it was not started in the suite';
175 1
                continue;
176
            }
177
178 1
            if (!isset($this->config['PACT_BROKER_URI'])) {
179
                echo 'PACT_BROKER_URI environment variable was not set. Skipping PACT file upload for:' . $providerName;
180
                continue;
181
            }
182
183 1
            $json = $this->getPactJson($providerName);
184 1
            $this->publishToBroker($mockServerConfig, $json, $consumerVersion);
185
        }
186
187 2
        return true;
188
    }
189
190
    /**
191
     * @param string $providerName
192
     *
193
     * @return string
194
     */
195 1
    private function getPactJson(string $providerName): string
196
    {
197 1
        $this->mockServerHttpServices[$providerName]->verifyInteractions();
198
199 1
        return $this->mockServerHttpServices[$providerName]->getPactJson();
200
    }
201
202
    /**
203
     * @param MockServerConfig $config
204
     * @param string           $json
205
     * @param string           $consumerVersion
206
     */
207 1
    private function publishToBroker(MockServerConfig $config, string $json, string $consumerVersion): void
208
    {
209 1
        $clientConfig = [];
210 1
        if (isset($this->config['PACT_BROKER_HTTP_AUTH_USER'])
211 1
            && isset($this->config['PACT_BROKER_HTTP_AUTH_PASS'])) {
212
            $clientConfig = [
213
                'auth' => [
214
                    $this->config['PACT_BROKER_HTTP_AUTH_USER'],
215
                    $this->config['PACT_BROKER_HTTP_AUTH_PASS'],
216
                ],
217
            ];
218
        }
219
220 1
        $pactBrokerUri     = $this->config['PACT_BROKER_URI'];
221 1
        $brokerHttpService = new BrokerHttpClient(new GuzzleClient($clientConfig), new Uri($pactBrokerUri));
222
        try {
223 1
            $brokerHttpService->publishJson($json, $consumerVersion);
224
            $brokerHttpService->tag($config->getConsumer(), $consumerVersion, $this->tag);
225
            echo 'Pact file has been uploaded to the Broker successfully with version ' . $consumerVersion . ' by tag:' . $this->tag;
226 1
        } catch (ClientException $e) {
227 1
            echo 'Error: ' . $e->getMessage();
228
        }
229
    }
230
231
    /**
232
     * @return string
233
     */
234 8
    private function getPactTag(): string
235
    {
236 8
        if (!($tag = \getenv('PACT_CONSUMER_TAG'))) {
237 8
            $tag = $this->resolvePactTag($this->getCurrentGitBranch());
238
        }
239
240 8
        return $tag;
241
    }
242
243
    /**
244
     * @return string
245
     */
246 8
    private function getCurrentGitBranch(): string
247
    {
248 8
        $branch = 'none';
249 8
        if (is_dir(__DIR__ . '/.git')) {
250
            $output = exec('git symbolic-ref HEAD');
251
            $parts  = explode('/', $output);
252
            $branch = end($parts);
253
        }
254
255 8
        return $branch;
256
    }
257
258
    /**
259
     * @param string $branch
260
     *
261
     * @return string
262
     */
263 8
    private function resolvePactTag(string $branch)
264
    {
265 8
        return \in_array($branch, ['develop', 'master'], true) ? 'master' : $branch;
266
    }
267
268
    /**
269
     * @param string $providerName
270
     *
271
     * @return int
272
     */
273 3
    public function startServer(string $providerName): int
274
    {
275 3
        if (isset($this->startedServers[$providerName])) {
276 1
            return $this->startedServers[$providerName];
277
        }
278
279 3
        $pid                                 = $this->servers[$providerName]->start();
280 3
        $this->startedServers[$providerName] = $pid;
281
282 3
        return $pid;
283
    }
284
285
    /**
286
     * @return bool
287
     */
288 1
    public function verifyInteractions(): bool
0 ignored issues
show
Coding Style introduced by
function verifyInteractions() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
289
    {
290 1
        foreach ($this->startedServers as $providerName => $val) {
291
            $this->builders[$providerName]->verify();
292
            $this->mockServerHttpServices[$providerName]->deleteAllInteractions();
293
        }
294
295 1
        return true;
296
    }
297
298 1
    public function registerInteraction(InteractionRequestDTO $requestDTO, InteractionResponseDTO $responseDTO, string $providerState): void
299
    {
300 1
        $providerName = $requestDTO->getProviderName();
301
302 1
        $request  = $this->interactionCompositor->createRequestFromDTO($requestDTO);
303 1
        $response = $this->interactionCompositor->createResponseFromDTO($responseDTO);
304
305 1
        $this->builders[$providerName]
306 1
            ->given($providerState)
307 1
            ->uponReceiving($requestDTO->getDescription())
308 1
            ->with($request)
309 1
            ->willRespondWith($response);
310
    }
311
312
    /**
313
     * @return string
314
     */
315 1
    public function getConsumerVersion(): string
316
    {
317 1
        return $this->config['PACT_CONSUMER_VERSION'];
318
    }
319
}
320