Completed
Pull Request — master (#2751)
by Jeroen
06:20
created

VersionCheckTest   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 13
dl 0
loc 227
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 13 2
A testDeprecatedCacheConstructorParameter() 0 4 1
A testCacheConstructorParameterType() 0 7 1
A testTranslatorConstructorParameterType() 0 7 1
A setUpVersionCheckerMock() 0 10 1
A testIsEnabled() 0 12 1
A testPeriodicallyCheck() 0 20 1
A testCheckWithInvalidResponse() 0 32 1
B testCheck() 0 68 4
A provider() 0 11 1
A getVersionChecker() 0 4 1
1
<?php
2
3
namespace Kunstmaan\AdminBundle\Tests\Helper;
4
5
use Doctrine\Common\Cache\ArrayCache;
6
use GuzzleHttp\Client;
7
use GuzzleHttp\Handler\MockHandler;
8
use GuzzleHttp\HandlerStack;
9
use GuzzleHttp\Psr7\Response;
10
use Kunstmaan\AdminBundle\Helper\VersionCheck\Exception\ParseException;
11
use Kunstmaan\AdminBundle\Helper\VersionCheck\VersionChecker;
12
use PHPUnit\Framework\TestCase;
13
use Symfony\Component\Cache\Adapter\AdapterInterface;
14
use Symfony\Component\Cache\Adapter\ArrayAdapter;
15
use Symfony\Component\Cache\CacheItem;
16
use Symfony\Component\DependencyInjection\ContainerInterface;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\RequestStack;
19
use Symfony\Component\HttpKernel\Kernel;
20
use Symfony\Component\Translation\Translator;
21
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
22
use Symfony\Contracts\Cache\ItemInterface;
23
use Symfony\Contracts\Translation\TranslatorInterface;
24
25
class VersionCheckTest extends TestCase
26
{
27
    /** @var \PHPUnit\Framework\MockObject\MockObject|LegacyTranslatorInterface|TranslatorInterface */
28
    private $translator;
29
    /** @var ContainerInterface (mock) */
30
    private $container;
31
32
    /** @var ArrayAdapter */
33
    private $cache;
34
35
    public function setUp()
36
    {
37
        /* @var ContainerInterface $container */
38
        $this->container = $this->createMock(ContainerInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(\Symfo...tainerInterface::class) of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Symfony\Component...ion\ContainerInterface> of property $container.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
39
40
        $this->cache = $this->createMock(AdapterInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(\Symfo...dapterInterface::class) of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Symfony\Component...e\Adapter\ArrayAdapter> of property $cache.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
41
42
        if (\interface_exists(TranslatorInterface::class)) {
43
            $this->translator = $this->createMock(TranslatorInterface::class);
44
        } else {
45
            $this->translator = $this->createMock(LegacyTranslatorInterface::class);
46
        }
47
    }
48
49
    /**
50
     * @group legacy
51
     * @expectedDeprecation Passing an instance of "Doctrine\Common\Cache\Cache" as the second argument in "Kunstmaan\AdminBundle\Helper\VersionCheck\VersionChecker::__construct" is deprecated since KunstmaanAdminBundle 5.7 and an instance of "Symfony\Component\Cache\Adapter\AdapterInterface" will be required in KunstmaanAdminBundle 6.0.
52
     */
53
    public function testDeprecatedCacheConstructorParameter()
54
    {
55
        new VersionChecker($this->createMock(ContainerInterface::class), new ArrayCache(), $this->translator);
0 ignored issues
show
Documentation introduced by
$this->createMock(\Symfo...tainerInterface::class) is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component...ion\ContainerInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
56
    }
57
58
    /**
59
     * @group legacy
60
     */
61
    public function testCacheConstructorParameterType()
62
    {
63
        $this->expectException(\InvalidArgumentException::class);
64
        $this->expectExceptionMessage('The "$cache" parameter should implement "Doctrine\Common\Cache\Cache" or "Symfony\Component\Cache\Adapter\AdapterInterface"');
65
66
        new VersionChecker($this->createMock(ContainerInterface::class), new \stdClass(), $this->translator);
0 ignored issues
show
Documentation introduced by
$this->createMock(\Symfo...tainerInterface::class) is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component...ion\ContainerInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
new \stdClass() is of type object<stdClass>, but the function expects a object<Doctrine\Common\C...apter\AdapterInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
67
    }
68
69
    /**
70
     * @group legacy
71
     */
72
    public function testTranslatorConstructorParameterType()
73
    {
74
        $this->expectException(\InvalidArgumentException::class);
75
        $this->expectExceptionMessage('The "$translator" parameter should be instance of "Symfony\Contracts\Translation\TranslatorInterface" or "Symfony\Component\Translation\TranslatorInterface"');
76
77
        new VersionChecker($this->createMock(ContainerInterface::class), new ArrayCache(), new \stdClass());
0 ignored issues
show
Documentation introduced by
$this->createMock(\Symfo...tainerInterface::class) is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component...ion\ContainerInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
78
    }
79
80
    /**
81
     * @param array|null $methods
82
     *
83
     * @return \PHPUnit\Framework\MockObject\MockObject|VersionChecker
84
     */
85
    public function setUpVersionCheckerMock(?array $methods)
86
    {
87
        $versionCheckerMock = $this->getMockBuilder(VersionChecker::class)
88
            ->setConstructorArgs([$this->container, $this->cache, $this->translator])
89
            ->setMethods($methods)
90
            ->getMock()
91
        ;
92
93
        return $versionCheckerMock;
94
    }
95
96
    public function testIsEnabled()
97
    {
98
        $this->container
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...ion\ContainerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
99
            ->expects($this->exactly(3))
100
            ->method('getParameter')
101
            ->will($this->onConsecutiveCalls('url', 300, true))
102
        ;
103
104
        $versionChecker = $this->getVersionChecker($this->container,  new ArrayAdapter(), $this->translator);
105
106
        $this->assertTrue($versionChecker->isEnabled());
107
    }
108
109
    public function testPeriodicallyCheck()
110
    {
111
        $this->container
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...ion\ContainerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
112
            ->expects($this->exactly(3))
113
            ->method('getParameter')
114
            ->will($this->onConsecutiveCalls('url', 300, true))
115
        ;
116
117
        $cacheItem = $this->createMock(ItemInterface::class);
118
        $cacheItem->method('isHit')->willReturn(true);
119
        $cacheItem->method('get')->willReturn([]);
120
121
        $this->cache
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...e\Adapter\ArrayAdapter>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
122
            ->expects($this->once())
123
            ->method('getItem')
124
            ->willReturn($cacheItem)
125
        ;
126
        $versionCheckerMock = $this->setUpVersionCheckerMock(null);
127
        $versionCheckerMock->periodicallyCheck();
0 ignored issues
show
Bug introduced by
The method periodicallyCheck does only exist in Kunstmaan\AdminBundle\He...ionCheck\VersionChecker, but not in PHPUnit\Framework\MockObject\MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
128
    }
129
130
    public function testCheckWithInvalidResponse()
131
    {
132
        $this->container
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...ion\ContainerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
133
            ->expects($this->exactly(4))
134
            ->method('getParameter')
135
            ->will($this->onConsecutiveCalls('url', 300, true, 'title'))
136
        ;
137
138
        $requestMock = $this->createMock(Request::class);
139
140
        $stackMock = $this->createMock(RequestStack::class);
141
        $stackMock
142
            ->expects($this->once())
143
            ->method('getCurrentRequest')
144
            ->willReturn($requestMock)
145
        ;
146
        $kernelMock = $this->createMock(Kernel::class);
147
148
        $this->container
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...ion\ContainerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
149
            ->expects($this->exactly(2))
150
            ->method('get')
151
            ->will($this->onConsecutiveCalls($stackMock, $kernelMock))
152
        ;
153
154
        $versionCheckerMock = $this->setUpVersionCheckerMock(['parseComposer']);
155
        $versionCheckerMock
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit\Framework\MockObject\MockObject, but not in Kunstmaan\AdminBundle\He...ionCheck\VersionChecker.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
156
            ->expects($this->once())
157
            ->method('parseComposer')
158
            ->willReturn(['name' => 'box/spout'])
159
        ;
160
        $this->assertFalse($versionCheckerMock->check());
0 ignored issues
show
Bug introduced by
The method check does only exist in Kunstmaan\AdminBundle\He...ionCheck\VersionChecker, but not in PHPUnit\Framework\MockObject\MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
161
    }
162
163
    /**
164
     * @dataProvider provider
165
     */
166
    public function testCheck(string $lockPath, string $expectedType, string $expected)
167
    {
168
        if ('exception' === $expectedType) {
169
            $this->expectException(ParseException::class);
170
            $this->expectExceptionMessage($expected);
171
        }
172
173
        $this->container
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...ion\ContainerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
174
            ->expects($this->any())
175
            ->method('getParameter')
176
            ->will($this->onConsecutiveCalls('url', 300, true, 'title'))
177
        ;
178
179
        $requestStack = new RequestStack();
180
        $requestStack->push(new Request());
181
182
        $translatorMock = $this->createMock(Translator::class);
183
        $translatorMock
184
            ->expects($this->any())
185
            ->method('trans')
186
            ->willReturn('translated')
187
        ;
188
189
        $kernelMock = $this->createMock(Kernel::class);
190
191
        if ('instanceOf' === $expectedType) {
192
            $cacheItem = $this->createMock(ItemInterface::class);
193
            $cacheItem->method('isHit')->willReturn(false);
194
            $cacheItem->expects($this->once())->method('expiresAfter')->with(300);
195
            $cacheItem->expects($this->once())->method('set')->with($this->isInstanceOf($expected));
196
197
            $this->cache
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...e\Adapter\ArrayAdapter>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
198
                ->expects($this->once())
199
                ->method('getItem')
200
                ->willReturn($cacheItem);
201
        }
202
203
        $this->container
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...ion\ContainerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
204
            ->expects($this->exactly(3))
205
            ->method('get')
206
            ->will($this->onConsecutiveCalls($requestStack, $kernelMock, $translatorMock))
207
        ;
208
209
        $mock = new MockHandler([
210
            new Response(200, ['X-Foo' => 'Bar'], \json_encode(['foo' => 'bar'])),
211
        ]);
212
213
        $handler = HandlerStack::create($mock);
214
        $client = new Client(['handler' => $handler]);
215
216
        $versionCheckerMock = $this->setUpVersionCheckerMock(['getClient', 'getLockPath']);
217
        $versionCheckerMock
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit\Framework\MockObject\MockObject, but not in Kunstmaan\AdminBundle\He...ionCheck\VersionChecker.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
218
            ->expects($this->any())
219
            ->method('getClient')
220
            ->willReturn($client)
221
        ;
222
        $versionCheckerMock
223
            ->expects($this->once())
224
            ->method('getLockPath')
225
            ->willReturn($lockPath)
226
        ;
227
228
        if ('instanceOf' === $expectedType) {
229
            $this->assertInstanceOf($expected, $versionCheckerMock->check());
0 ignored issues
show
Bug introduced by
The method check does only exist in Kunstmaan\AdminBundle\He...ionCheck\VersionChecker, but not in PHPUnit\Framework\MockObject\MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
230
        } else {
231
            $versionCheckerMock->check();
232
        }
233
    }
234
235
    public function provider()
236
    {
237
        $baseDir = __DIR__ . '/testdata';
238
239
        return [
240
            'composer.lock ok' => [$baseDir.'/composer_ok.lock', 'instanceOf', \stdClass::class],
241
            'composer.lock broken' => [$baseDir.'/composer_broken.lock', 'exception', 'translated (#4)'],
242
            'composer.lock bundleless' => [$baseDir.'/composer_bundleless.lock', 'exception', 'translated'],
243
            'composer.lock not found' => [$baseDir.'/composer_not_there.lock', 'exception', 'translated'],
244
        ];
245
    }
246
247
    private function getVersionChecker(ContainerInterface $container, AdapterInterface $cache, $translator)
248
    {
249
        return new VersionChecker($container, $cache, $translator);
250
    }
251
}
252