Issues (3627)

CoreBundle/Tests/Unit/Helper/UpdateHelperTest.php (6 issues)

1
<?php
2
3
/*
4
 * @copyright   2020 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        https://www.mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\CoreBundle\Tests\Unit\Helper;
13
14
use GuzzleHttp\Client;
15
use GuzzleHttp\Exception\RequestException;
16
use Mautic\CoreBundle\Helper\CoreParametersHelper;
17
use Mautic\CoreBundle\Helper\PathsHelper;
18
use Mautic\CoreBundle\Helper\Update\Exception\LatestVersionSupportedException;
19
use Mautic\CoreBundle\Helper\Update\Github\ReleaseParser;
20
use Mautic\CoreBundle\Helper\UpdateHelper;
21
use Monolog\Logger;
22
use PHPUnit\Framework\MockObject\MockObject;
23
use PHPUnit\Framework\TestCase;
24
use Psr\Http\Message\RequestInterface;
25
use Psr\Http\Message\ResponseInterface;
26
use Psr\Http\Message\StreamInterface;
27
28
class UpdateHelperTest extends TestCase
29
{
30
    /**
31
     * @var PathsHelper|MockObject
32
     */
33
    private $pathsHelper;
34
35
    /**
36
     * @var Logger|MockObject
37
     */
38
    private $logger;
39
40
    /**
41
     * @var CoreParametersHelper|MockObject
42
     */
43
    private $coreParametersHelper;
44
45
    /**
46
     * @var Client|MockObject
47
     */
48
    private $client;
49
50
    /**
51
     * @var ResponseInterface|MockObject
52
     */
53
    private $response;
54
55
    /**
56
     * @var StreamInterface|MockObject
57
     */
58
    private $streamBody;
59
60
    /**
61
     * @var ReleaseParser|MockObject
62
     */
63
    private $releaseParser;
64
65
    /**
66
     * @var UpdateHelper
67
     */
68
    private $helper;
69
70
    protected function setUp(): void
71
    {
72
        $this->pathsHelper = $this->createMock(PathsHelper::class);
73
        $this->pathsHelper->method('getSystemPath')
74
            ->with('cache')
75
            ->willReturn(__DIR__.'/resource/update/tmp');
76
77
        $this->logger               = $this->createMock(Logger::class);
78
        $this->coreParametersHelper = $this->createMock(CoreParametersHelper::class);
79
        $this->releaseParser        = $this->createMock(ReleaseParser::class);
80
81
        $this->response   = $this->createMock(ResponseInterface::class);
82
        $this->streamBody = $this->createMock(StreamInterface::class);
83
        $this->response
84
            ->method('getBody')
85
            ->willReturn($this->streamBody);
86
        $this->client = $this->createMock(Client::class);
87
88
        $this->helper = new UpdateHelper($this->pathsHelper, $this->logger, $this->coreParametersHelper, $this->client, $this->releaseParser);
89
    }
90
91
    protected function tearDown(): void
92
    {
93
        parent::tearDown();
94
95
        // Cleanup the files
96
        @unlink(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt');
97
    }
98
99
    public function testUpdatePackageFetchedAndSaved()
100
    {
101
        $this->response->expects($this->once())
102
            ->method('getStatusCode')
103
            ->willReturn(200);
104
105
        $this->streamBody->expects($this->once())
106
            ->method('getContents')
107
            ->willReturn(file_get_contents(__DIR__.'/resource/update/update.zip'));
108
109
        $this->client->expects($this->once())
110
            ->method('request')
111
            ->with('GET', 'update.zip')
112
            ->willReturn($this->response);
113
114
        $result = $this->helper->fetchPackage('update.zip');
115
        $this->assertTrue(isset($result['error']));
116
        $this->assertFalse($result['error']);
117
118
        $updatePackage = __DIR__.'/resource/update/tmp/update.zip';
119
        $this->assertTrue(file_exists($updatePackage));
120
        @unlink($updatePackage);
121
    }
122
123
    public function testConnectionErrorReturnsError()
124
    {
125
        $this->response->expects($this->exactly(2))
126
            ->method('getStatusCode')
127
            ->willReturn(404);
128
        $this->response->expects($this->never())
129
            ->method('getBody');
130
131
        $this->client->expects($this->once())
132
            ->method('request')
133
            ->with('GET', 'update.zip')
134
            ->willReturn($this->response);
135
136
        $result = $this->helper->fetchPackage('update.zip');
137
        $this->assertTrue(isset($result['error']));
138
        $this->assertTrue($result['error']);
139
        $this->assertEquals('mautic.core.updater.error.fetching.package', $result['message']);
140
    }
141
142
    public function testCacheIsRefreshedIfStabilityMismatches()
143
    {
144
        $cache = [
145
            'error'        => false,
146
            'message'      => 'mautic.core.updater.update.available',
147
            'version'      => '10.0.1',
148
            'announcement' => 'https://mautic.org',
149
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
150
            'stability'    => 'stable',
151
            'checkedTime'  => time() - 100,
152
        ];
153
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
154
155
        $this->coreParametersHelper->expects($this->exactly(3))
156
            ->method('get')
157
            ->withConsecutive(
158
                ['update_stability'],
159
                ['stats_update_url'],
160
                ['system_update_url']
161
            )
162
            ->willReturnOnConsecutiveCalls(
163
                'alpha',
164
                null,
165
                null
166
            );
167
168
        $this->helper->fetchData();
169
    }
170
171
    public function testCacheIsRefreshedIfExpired()
172
    {
173
        $cache = [
174
            'error'        => false,
175
            'message'      => 'mautic.core.updater.update.available',
176
            'version'      => '10.0.1',
177
            'announcement' => 'https://mautic.org',
178
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
179
            'stability'    => 'stable',
180
            'checkedTime'  => time() - 10800,
181
        ];
182
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
183
184
        $this->coreParametersHelper->expects($this->exactly(3))
185
            ->method('get')
186
            ->withConsecutive(
187
                ['update_stability'],
188
                ['stats_update_url'],
189
                ['system_update_url']
190
            )
191
            ->willReturnOnConsecutiveCalls(
192
                'stable',
193
                null,
194
                null
195
            );
196
197
        $this->helper->fetchData();
198
    }
199
200
    public function testCacheIsRefreshedIfForced()
201
    {
202
        $cache = [
203
            'error'        => false,
204
            'message'      => 'mautic.core.updater.update.available',
205
            'version'      => '10.0.1',
206
            'announcement' => 'https://mautic.org',
207
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
208
            'stability'    => 'stable',
209
            'checkedTime'  => time(),
210
        ];
211
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
212
213
        $this->coreParametersHelper->expects($this->exactly(3))
214
            ->method('get')
215
            ->withConsecutive(
216
                ['update_stability'],
217
                ['stats_update_url'],
218
                ['system_update_url']
219
            )
220
            ->willReturnOnConsecutiveCalls(
221
                'stable',
222
                null,
223
                null
224
            );
225
226
        $this->helper->fetchData(true);
227
    }
228
229
    public function testStatsAreSent()
230
    {
231
        $cache = [
232
            'error'        => false,
233
            'message'      => 'mautic.core.updater.update.available',
234
            'version'      => '10.0.1',
235
            'announcement' => 'https://mautic.org',
236
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
237
            'stability'    => 'stable',
238
            'checkedTime'  => time() - 10800,
239
        ];
240
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
241
242
        $statsUrl = 'https://mautic.org/stats';
243
        $this->coreParametersHelper->expects($this->exactly(6))
244
            ->method('get')
245
            ->withConsecutive(
246
                ['update_stability'],
247
                ['stats_update_url'],
248
                ['secret_key'],
249
                ['db_driver'],
250
                ['install_source', 'Mautic'],
251
                ['system_update_url']
252
            )
253
            ->willReturnOnConsecutiveCalls(
254
                'stable',
255
                $statsUrl,
256
                'abc123',
257
                'mysql',
258
                'Mautic',
259
                null
260
            );
261
262
        $this->client->expects($this->once())
263
            ->method('request')
264
            ->with(
265
                'POST',
266
                $statsUrl,
267
                $this->callback(
268
                    function (array $options) {
269
                        $this->assertArrayHasKey(\GuzzleHttp\RequestOptions::FORM_PARAMS, $options);
270
                        $this->assertArrayHasKey(\GuzzleHttp\RequestOptions::CONNECT_TIMEOUT, $options);
271
                        $this->assertArrayHasKey(\GuzzleHttp\RequestOptions::HEADERS, $options);
272
                        // We need to send an Accept header to the stats server or we'll get 500 errors
273
                        $this->assertEquals(['Accept' => '*/*'], $options[\GuzzleHttp\RequestOptions::HEADERS]);
274
275
                        return true;
276
                    }
277
                )
278
            )->willReturn($this->response);
279
280
        $this->helper->fetchData();
281
    }
282
283
    public function testStatsNotSentIfDisabled()
284
    {
285
        $cache = [
286
            'error'        => false,
287
            'message'      => 'mautic.core.updater.update.available',
288
            'version'      => '10.0.1',
289
            'announcement' => 'https://mautic.org',
290
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
291
            'stability'    => 'stable',
292
            'checkedTime'  => time() - 10800,
293
        ];
294
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
295
296
        $statsUrl = '';
297
        $this->coreParametersHelper->expects($this->exactly(3))
298
            ->method('get')
299
            ->withConsecutive(
300
                ['update_stability'],
301
                ['stats_update_url'],
302
                ['system_update_url']
303
            )
304
            ->willReturnOnConsecutiveCalls(
305
                'stable',
306
                $statsUrl,
307
                null
308
            );
309
310
        $this->client->expects($this->never())
311
            ->method('request');
312
313
        $this->helper->fetchData();
314
    }
315
316
    public function testExceptionDoesNotGoUncaughtWhenThrownDuringUpdatingStats()
317
    {
318
        $cache = [
319
            'error'        => false,
320
            'message'      => 'mautic.core.updater.update.available',
321
            'version'      => '10.0.1',
322
            'announcement' => 'https://mautic.org',
323
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
324
            'stability'    => 'stable',
325
            'checkedTime'  => time() - 10800,
326
        ];
327
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
328
329
        $statsUrl = 'https://mautic.org/stats';
330
        $this->coreParametersHelper->expects($this->exactly(6))
331
            ->method('get')
332
            ->withConsecutive(
333
                ['update_stability'],
334
                ['stats_update_url'],
335
                ['secret_key'],
336
                ['db_driver'],
337
                ['install_source', 'Mautic'],
338
                ['system_update_url']
339
            )
340
            ->willReturnOnConsecutiveCalls(
341
                'stable',
342
                $statsUrl,
343
                'abc123',
344
                'mysql',
345
                'Mautic',
346
                null
347
            );
348
349
        $this->client->expects($this->once())
350
            ->method('request')
351
            ->with('POST', $statsUrl, $this->anything())
352
            ->willReturnCallback(
353
                function (string $method, string $url, array $options) {
354
                    $request = $this->createMock(RequestInterface::class);
355
356
                    throw new \Exception('something bad happened');
357
                }
358
            );
359
360
        $this->logger->expects($this->once())
361
            ->method('error');
362
363
        $this->helper->fetchData();
364
    }
365
366
    public function testRequestExceptionDoesNotGoUncaughtWhenThrownDuringUpdatingStats()
367
    {
368
        $cache = [
369
            'error'        => false,
370
            'message'      => 'mautic.core.updater.update.available',
371
            'version'      => '10.0.1',
372
            'announcement' => 'https://mautic.org',
373
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
374
            'stability'    => 'stable',
375
            'checkedTime'  => time() - 10800,
376
        ];
377
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
378
379
        $statsUrl = 'https://mautic.org/stats';
380
        $this->coreParametersHelper->expects($this->exactly(6))
381
            ->method('get')
382
            ->withConsecutive(
383
                ['update_stability'],
384
                ['stats_update_url'],
385
                ['secret_key'],
386
                ['db_driver'],
387
                ['install_source', 'Mautic'],
388
                ['system_update_url']
389
            )
390
            ->willReturnOnConsecutiveCalls(
391
                'stable',
392
                $statsUrl,
393
                'abc123',
394
                'mysql',
395
                'Mautic',
396
                null
397
            );
398
399
        $this->client->expects($this->once())
400
            ->method('request')
401
            ->with('POST', $statsUrl, $this->anything())
402
            ->willReturnCallback(
403
                function (string $method, string $url, array $options) {
0 ignored issues
show
The parameter $method is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

403
                function (/** @scrutinizer ignore-unused */ string $method, string $url, array $options) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $url is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

403
                function (string $method, /** @scrutinizer ignore-unused */ string $url, array $options) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

403
                function (string $method, string $url, /** @scrutinizer ignore-unused */ array $options) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
404
                    $request = $this->createMock(RequestInterface::class);
405
406
                    throw new RequestException('something bad happened', $request, $this->response);
407
                }
408
            );
409
410
        $this->logger->expects($this->once())
411
            ->method('error');
412
413
        $this->helper->fetchData();
414
    }
415
416
    public function testRequestExceptionWithEmptyResponseDoesNotGoUncaughtWhenThrownDuringUpdatingStats()
417
    {
418
        $cache = [
419
            'error'        => false,
420
            'message'      => 'mautic.core.updater.update.available',
421
            'version'      => '10.0.1',
422
            'announcement' => 'https://mautic.org',
423
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
424
            'stability'    => 'stable',
425
            'checkedTime'  => time() - 10800,
426
        ];
427
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
428
429
        $statsUrl = 'https://mautic.org/stats';
430
        $this->coreParametersHelper->expects($this->exactly(6))
431
            ->method('get')
432
            ->withConsecutive(
433
                ['update_stability'],
434
                ['stats_update_url'],
435
                ['secret_key'],
436
                ['db_driver'],
437
                ['install_source', 'Mautic'],
438
                ['system_update_url']
439
            )
440
            ->willReturnOnConsecutiveCalls(
441
                'stable',
442
                $statsUrl,
443
                'abc123',
444
                'mysql',
445
                'Mautic',
446
                null
447
            );
448
449
        $this->client->expects($this->once())
450
            ->method('request')
451
            ->with('POST', $statsUrl, $this->anything())
452
            ->willReturnCallback(
453
                function (string $method, string $url, array $options) {
0 ignored issues
show
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

453
                function (string $method, string $url, /** @scrutinizer ignore-unused */ array $options) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $url is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

453
                function (string $method, /** @scrutinizer ignore-unused */ string $url, array $options) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $method is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

453
                function (/** @scrutinizer ignore-unused */ string $method, string $url, array $options) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
454
                    $request = $this->createMock(RequestInterface::class);
455
456
                    throw new RequestException('something bad happened', $request, null);
457
                }
458
            );
459
460
        $this->logger->expects($this->once())
461
            ->method('error');
462
463
        $this->helper->fetchData();
464
    }
465
466
    public function testNoErrorIfLatestVersionInstalled()
467
    {
468
        $cache = [
469
            'error'        => false,
470
            'message'      => 'mautic.core.updater.update.available',
471
            'version'      => '10.0.1',
472
            'announcement' => 'https://mautic.org',
473
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
474
            'stability'    => 'stable',
475
            'checkedTime'  => time() - 10800,
476
        ];
477
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
478
479
        $updateUrl = 'https://mautic.org/update';
480
        $this->coreParametersHelper->expects($this->exactly(3))
481
            ->method('get')
482
            ->withConsecutive(
483
                ['update_stability'],
484
                ['stats_update_url'],
485
                ['system_update_url']
486
            )
487
            ->willReturnOnConsecutiveCalls(
488
                'stable',
489
                null,
490
                $updateUrl
491
            );
492
493
        $this->client->expects($this->once())
494
            ->method('request')
495
            ->with('GET', $updateUrl)
496
            ->willReturn($this->response);
497
498
        $this->response->expects($this->once())
499
            ->method('getStatusCode')
500
            ->willReturn(200);
501
502
        $this->streamBody->expects($this->once())
503
            ->method('getContents')
504
            ->willReturn('[{"html_url": "https://github.com/10.0.1"}]');
505
506
        $this->releaseParser->expects($this->once())
507
            ->method('getLatestSupportedRelease')
508
            ->willThrowException(new LatestVersionSupportedException());
509
510
        $data = $this->helper->fetchData();
511
        $this->assertFalse($data['error']);
512
        $this->assertEquals('mautic.core.updater.running.latest.version', $data['message']);
513
    }
514
515
    public function testErrorIfLatestVersionCouldNotBeDetermined()
516
    {
517
        $cache = [
518
            'error'        => false,
519
            'message'      => 'mautic.core.updater.update.available',
520
            'version'      => '10.0.1',
521
            'announcement' => 'https://mautic.org',
522
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
523
            'stability'    => 'stable',
524
            'checkedTime'  => time() - 10800,
525
        ];
526
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
527
528
        $updateUrl = 'https://mautic.org/update';
529
        $this->coreParametersHelper->expects($this->exactly(3))
530
            ->method('get')
531
            ->withConsecutive(
532
                ['update_stability'],
533
                ['stats_update_url'],
534
                ['system_update_url']
535
            )
536
            ->willReturnOnConsecutiveCalls(
537
                'stable',
538
                null,
539
                $updateUrl
540
            );
541
542
        $this->client->expects($this->once())
543
            ->method('request')
544
            ->with('GET', $updateUrl)
545
            ->willReturn($this->response);
546
547
        $this->response->expects($this->exactly(2))
548
            ->method('getStatusCode')
549
            ->willReturn(404);
550
551
        $this->releaseParser->expects($this->never())
552
            ->method('getLatestSupportedRelease');
553
554
        $this->logger->expects($this->once())
555
            ->method('error');
556
557
        $data = $this->helper->fetchData();
558
        $this->assertTrue($data['error']);
559
        $this->assertEquals('mautic.core.updater.error.fetching.updates', $data['message']);
560
    }
561
562
    public function testErrorIfGuzzleException()
563
    {
564
        $cache = [
565
            'error'        => false,
566
            'message'      => 'mautic.core.updater.update.available',
567
            'version'      => '10.0.1',
568
            'announcement' => 'https://mautic.org',
569
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
570
            'stability'    => 'stable',
571
            'checkedTime'  => time() - 10800,
572
        ];
573
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
574
575
        $updateUrl = 'https://mautic.org/update';
576
        $this->coreParametersHelper->expects($this->exactly(3))
577
            ->method('get')
578
            ->withConsecutive(
579
                ['update_stability'],
580
                ['stats_update_url'],
581
                ['system_update_url']
582
            )
583
            ->willReturnOnConsecutiveCalls(
584
                'stable',
585
                null,
586
                $updateUrl
587
            );
588
589
        $this->client->expects($this->once())
590
            ->method('request')
591
            ->with('GET', $updateUrl)
592
            ->willThrowException(new RequestException('bad', $this->createMock(RequestInterface::class), $this->response));
593
594
        $this->releaseParser->expects($this->never())
595
            ->method('getLatestSupportedRelease');
596
597
        $this->logger->expects($this->once())
598
            ->method('error');
599
600
        $data = $this->helper->fetchData();
601
        $this->assertTrue($data['error']);
602
        $this->assertEquals('mautic.core.updater.error.fetching.updates', $data['message']);
603
    }
604
605
    public function testErrorForAnyException()
606
    {
607
        $cache = [
608
            'error'        => false,
609
            'message'      => 'mautic.core.updater.update.available',
610
            'version'      => '10.0.1',
611
            'announcement' => 'https://mautic.org',
612
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
613
            'stability'    => 'stable',
614
            'checkedTime'  => time() - 10800,
615
        ];
616
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
617
618
        $updateUrl = 'https://mautic.org/update';
619
        $this->coreParametersHelper->expects($this->exactly(3))
620
            ->method('get')
621
            ->withConsecutive(
622
                ['update_stability'],
623
                ['stats_update_url'],
624
                ['system_update_url']
625
            )
626
            ->willReturnOnConsecutiveCalls(
627
                'stable',
628
                null,
629
                $updateUrl
630
            );
631
632
        $this->client->expects($this->once())
633
            ->method('request')
634
            ->with('GET', $updateUrl)
635
            ->willThrowException(new \Exception());
636
637
        $this->releaseParser->expects($this->never())
638
            ->method('getLatestSupportedRelease');
639
640
        $this->logger->expects($this->once())
641
            ->method('error');
642
643
        $this->response->expects($this->never())
644
            ->method('getStatusCode');
645
646
        $data = $this->helper->fetchData();
647
        $this->assertTrue($data['error']);
648
        $this->assertEquals('mautic.core.updater.error.fetching.updates', $data['message']);
649
    }
650
651
    public function testNoErrorIfInAppUpdatesAreDisabled()
652
    {
653
        $cache = [
654
            'error'        => false,
655
            'message'      => 'mautic.core.updater.update.available',
656
            'version'      => '10.0.1',
657
            'announcement' => 'https://mautic.org',
658
            'package'      => 'https://mautic.org/10.0.1/upgrade.zip',
659
            'stability'    => 'stable',
660
            'checkedTime'  => time() - 10800,
661
        ];
662
        file_put_contents(__DIR__.'/resource/update/tmp/lastUpdateCheck.txt', json_encode($cache));
663
664
        $this->coreParametersHelper->expects($this->exactly(3))
665
            ->method('get')
666
            ->withConsecutive(
667
                ['update_stability'],
668
                ['stats_update_url'],
669
                ['system_update_url']
670
            )
671
            ->willReturnOnConsecutiveCalls(
672
                'stable',
673
                null,
674
                null
675
            );
676
677
        $this->client->expects($this->never())
678
            ->method('request');
679
680
        $this->releaseParser->expects($this->never())
681
            ->method('getLatestSupportedRelease');
682
683
        $data = $this->helper->fetchData();
684
        $this->assertFalse($data['error']);
685
        $this->assertEquals('mautic.core.updater.running.latest.version', $data['message']);
686
    }
687
}
688