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

testTranslatorConstructorParameterType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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 Psr\Cache\CacheItemInterface;
14
use Symfony\Component\Cache\Adapter\AdapterInterface;
15
use Symfony\Component\Cache\Adapter\ArrayAdapter;
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\Translation\TranslatorInterface;
23
24
class VersionCheckTest extends TestCase
25
{
26
    /** @var \PHPUnit\Framework\MockObject\MockObject|LegacyTranslatorInterface|TranslatorInterface */
27
    private $translator;
28
    /** @var ContainerInterface (mock) */
29
    private $container;
30
31
    /** @var ArrayAdapter */
32
    private $cache;
33
34
    public function setUp()
35
    {
36
        /* @var ContainerInterface $container */
37
        $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...
38
39
        $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...
40
41
        if (\interface_exists(TranslatorInterface::class)) {
42
            $this->translator = $this->createMock(TranslatorInterface::class);
43
        } else {
44
            $this->translator = $this->createMock(LegacyTranslatorInterface::class);
45
        }
46
    }
47
48
    /**
49
     * @group legacy
50
     * @expectedDeprecation Passing an instance of "Doctrine\Common\Cache\CacheProvider" 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.
51
     */
52
    public function testDeprecatedCacheConstructorParameter()
53
    {
54
        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...
55
    }
56
57
    /**
58
     * @group legacy
59
     */
60
    public function testCacheConstructorParameterType()
61
    {
62
        $this->expectException(\InvalidArgumentException::class);
63
        $this->expectExceptionMessage('The "$cache" parameter should extend from "Doctrine\Common\Cache\CacheProvider" or implement "Symfony\Component\Cache\Adapter\AdapterInterface"');
64
65
        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...
66
    }
67
68
    /**
69
     * @group legacy
70
     */
71
    public function testTranslatorConstructorParameterType()
72
    {
73
        $this->expectException(\InvalidArgumentException::class);
74
        $this->expectExceptionMessage('The "$translator" parameter should be instance of "Symfony\Contracts\Translation\TranslatorInterface" or "Symfony\Component\Translation\TranslatorInterface"');
75
76
        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...
77
    }
78
79
    /**
80
     * @param array|null $methods
81
     *
82
     * @return \PHPUnit\Framework\MockObject\MockObject|VersionChecker
83
     */
84
    public function setUpVersionCheckerMock(?array $methods)
85
    {
86
        $versionCheckerMock = $this->getMockBuilder(VersionChecker::class)
87
            ->setConstructorArgs([$this->container, $this->cache, $this->translator])
88
            ->setMethods($methods)
89
            ->getMock()
90
        ;
91
92
        return $versionCheckerMock;
93
    }
94
95
    public function testIsEnabled()
96
    {
97
        $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...
98
            ->expects($this->exactly(3))
99
            ->method('getParameter')
100
            ->will($this->onConsecutiveCalls('url', 300, true))
101
        ;
102
103
        $versionChecker = $this->getVersionChecker($this->container, new ArrayAdapter(), $this->translator);
104
105
        $this->assertTrue($versionChecker->isEnabled());
106
    }
107
108
    public function testPeriodicallyCheck()
109
    {
110
        $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...
111
            ->expects($this->exactly(3))
112
            ->method('getParameter')
113
            ->will($this->onConsecutiveCalls('url', 300, true))
114
        ;
115
116
        $cacheItem = $this->createMock(CacheItemInterface::class);
117
        $cacheItem->method('isHit')->willReturn(true);
118
        $cacheItem->method('get')->willReturn([]);
119
120
        $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...
121
            ->expects($this->once())
122
            ->method('getItem')
123
            ->willReturn($cacheItem)
124
        ;
125
        $versionCheckerMock = $this->setUpVersionCheckerMock(null);
126
        $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...
127
    }
128
129
    public function testCheckWithInvalidResponse()
130
    {
131
        $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...
132
            ->expects($this->exactly(4))
133
            ->method('getParameter')
134
            ->will($this->onConsecutiveCalls('url', 300, true, 'title'))
135
        ;
136
137
        $requestMock = $this->createMock(Request::class);
138
139
        $stackMock = $this->createMock(RequestStack::class);
140
        $stackMock
141
            ->expects($this->once())
142
            ->method('getCurrentRequest')
143
            ->willReturn($requestMock)
144
        ;
145
        $kernelMock = $this->createMock(Kernel::class);
146
147
        $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...
148
            ->expects($this->exactly(2))
149
            ->method('get')
150
            ->will($this->onConsecutiveCalls($stackMock, $kernelMock))
151
        ;
152
153
        $versionCheckerMock = $this->setUpVersionCheckerMock(['parseComposer']);
154
        $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...
155
            ->expects($this->once())
156
            ->method('parseComposer')
157
            ->willReturn(['name' => 'box/spout'])
158
        ;
159
        $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...
160
    }
161
162
    /**
163
     * @dataProvider provider
164
     */
165
    public function testCheck(string $lockPath, string $expectedType, string $expected)
166
    {
167
        if ('exception' === $expectedType) {
168
            $this->expectException(ParseException::class);
169
            $this->expectExceptionMessage($expected);
170
        }
171
172
        $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...
173
            ->expects($this->any())
174
            ->method('getParameter')
175
            ->will($this->onConsecutiveCalls('url', 300, true, 'title'))
176
        ;
177
178
        $requestStack = new RequestStack();
179
        $requestStack->push(new Request());
180
181
        $translatorMock = $this->createMock(Translator::class);
182
        $translatorMock
183
            ->expects($this->any())
184
            ->method('trans')
185
            ->willReturn('translated')
186
        ;
187
188
        $kernelMock = $this->createMock(Kernel::class);
189
190
        if ('instanceOf' === $expectedType) {
191
            $cacheItem = $this->createMock(CacheItemInterface::class);
192
            $cacheItem->method('isHit')->willReturn(false);
193
            $cacheItem->expects($this->once())->method('expiresAfter')->with(300);
194
            $cacheItem->expects($this->once())->method('set')->with($this->isInstanceOf($expected));
195
196
            $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...
197
                ->expects($this->once())
198
                ->method('getItem')
199
                ->willReturn($cacheItem);
200
        }
201
202
        $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...
203
            ->expects($this->exactly(3))
204
            ->method('get')
205
            ->will($this->onConsecutiveCalls($requestStack, $kernelMock, $translatorMock))
206
        ;
207
208
        $mock = new MockHandler([
209
            new Response(200, ['X-Foo' => 'Bar'], \json_encode(['foo' => 'bar'])),
210
        ]);
211
212
        $handler = HandlerStack::create($mock);
213
        $client = new Client(['handler' => $handler]);
214
215
        $versionCheckerMock = $this->setUpVersionCheckerMock(['getClient', 'getLockPath']);
216
        $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...
217
            ->expects($this->any())
218
            ->method('getClient')
219
            ->willReturn($client)
220
        ;
221
        $versionCheckerMock
222
            ->expects($this->once())
223
            ->method('getLockPath')
224
            ->willReturn($lockPath)
225
        ;
226
227
        if ('instanceOf' === $expectedType) {
228
            $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...
229
        } else {
230
            $versionCheckerMock->check();
231
        }
232
    }
233
234
    public function provider()
235
    {
236
        $baseDir = __DIR__ . '/testdata';
237
238
        return [
239
            'composer.lock ok' => [$baseDir.'/composer_ok.lock', 'instanceOf', \stdClass::class],
240
            'composer.lock broken' => [$baseDir.'/composer_broken.lock', 'exception', 'translated (#4)'],
241
            'composer.lock bundleless' => [$baseDir.'/composer_bundleless.lock', 'exception', 'translated'],
242
            'composer.lock not found' => [$baseDir.'/composer_not_there.lock', 'exception', 'translated'],
243
        ];
244
    }
245
246
    private function getVersionChecker(ContainerInterface $container, AdapterInterface $cache, $translator)
247
    {
248
        return new VersionChecker($container, $cache, $translator);
249
    }
250
}
251