Completed
Pull Request — master (#114)
by Bart
07:38
created

GlobalSetsTest::testGetRecordDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace NerdsAndCompany\Schematic\Converters\Elements;
4
5
use Craft;
6
use craft\elements\GlobalSet as GlobalSetElement;
7
use craft\base\Field;
8
use craft\models\FieldLayout;
9
use craft\models\Site;
10
use craft\services\Fields;
11
use Codeception\Test\Unit;
12
13
/**
14
 * Class GlobalSetsTest.
15
 *
16
 * @author    Nerds & Company
17
 * @copyright Copyright (c) 2015-2017, Nerds & Company
18
 * @license   MIT
19
 *
20
 * @see      http://www.nerds.company
21
 */
22
class GlobalSetsTest extends Unit
23
{
24
    /**
25
     * @var GlobalSets
26
     */
27
    private $converter;
28
29
    /**
30
     * Set the converter.
31
     *
32
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
33
     */
34
    protected function _before()
35
    {
36
        $this->converter = new GlobalSet();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \NerdsAndCompany\Sch...rs\Elements\GlobalSet() of type object<NerdsAndCompany\S...ers\Elements\GlobalSet> is incompatible with the declared type object<NerdsAndCompany\S...rs\Elements\GlobalSets> of property $converter.

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...
37
    }
38
39
    //==============================================================================================================
40
    //=================================================  TESTS  ====================================================
41
    //==============================================================================================================
42
43
    /**
44
     * @dataProvider provideGlobalSets
45
     *
46
     * @param GlobalSetModel $set
47
     * @param array          $definition
48
     */
49
    public function testGetRecordDefinition(GlobalSetElement $set, array $definition)
50
    {
51
        $result = $this->converter->getRecordDefinition($set);
52
53
        $this->assertSame($definition, $result);
54
    }
55
56
    /**
57
     * @dataProvider provideGlobalSets
58
     *
59
     * @param GlobalSetModel $set
60
     * @param array          $definition
61
     * @param bool           $valid
62
     */
63
    public function testSaveRecord(GlobalSetElement $set, array $definition, bool $valid)
64
    {
65
        Craft::$app->sites->expects($this->any())
66
                ->method('getSiteByHandle')
67
                ->willReturnMap([
68
                  ['default', $this->getMockSite()],
69
                  ['invalid', null],
70
                ]);
71
72
        Craft::$app->globals->expects($this->exactly($valid ? 1 : 0))
73
                            ->method('saveSet')
74
                            ->with($set)
75
                            ->willReturn(true);
76
77
        $result = $this->converter->saveRecord($set, $definition);
78
79
        $this->assertSame($valid, $result);
80
    }
81
82
    /**
83
     * @dataProvider provideGlobalSets
84
     *
85
     * @param GlobalSetModel $set
86
     */
87
    public function testDeleteRecord(GlobalSetElement $set)
88
    {
89
        Craft::$app->elements->expects($this->exactly(1))->method('deleteElementById')->with($set->id);
90
        $this->converter->deleteRecord($set);
91
    }
92
93
    //==============================================================================================================
94
    //==============================================  PROVIDERS  ===================================================
95
    //==============================================================================================================
96
97
    /**
98
     * @return array
99
     */
100
    public function provideGlobalSets()
101
    {
102
        $mockGlobalSet1 = $this->getMockGlobalSet(1);
103
        $mockGlobalSet2 = $this->getMockGlobalSet(1, 'invalid');
104
105
        return [
106
            'Valid set' => [
107
                'set' => $mockGlobalSet1,
108
                'definition' => $this->getMockGlobalSetDefinition($mockGlobalSet1),
0 ignored issues
show
Documentation introduced by
$mockGlobalSet1 is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<craft\elements\GlobalSet>.

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...
109
                'validSave' => true,
110
            ],
111
            'Invalid set' => [
112
                'set' => $mockGlobalSet2,
113
                'definition' => $this->getMockGlobalSetDefinition($mockGlobalSet2),
0 ignored issues
show
Documentation introduced by
$mockGlobalSet2 is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<craft\elements\GlobalSet>.

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...
114
                'validSave' => false,
115
            ],
116
        ];
117
    }
118
119
    //==============================================================================================================
120
    //================================================  HELPERS  ===================================================
121
    //==============================================================================================================
122
123
    /**
124
     * @param GlobalSet $mockGlobalSet
125
     *
126
     * @return array
127
     */
128
    private function getMockGlobalSetDefinition(GlobalSetElement $mockGlobalSet)
129
    {
130
        $fieldDefs = [];
131
        foreach ($mockGlobalSet->getFieldLayout()->getFields() as $field) {
132
            $fieldDefs[$field->handle] = $field->required;
133
        }
134
135
        return [
136
            'class' => get_class($mockGlobalSet),
137
            'attributes' => [
138
                'name' => $mockGlobalSet->name,
139
                'handle' => $mockGlobalSet->handle,
140
                'enabled' => true,
141
                'archived' => false,
142
                'enabledForSite' => true,
143
                'title' => null,
144
                'slug' => null,
145
                'uri' => null,
146
            ],
147
            'fieldLayout' => [
148
                'fields' => $fieldDefs,
149
            ],
150
            'site' => $mockGlobalSet->getSite()->handle,
151
        ];
152
    }
153
154
    /**
155
     * @param int    $setId
156
     * @param string $siteHandle
157
     *
158
     * @return Mock|GlobalSet
159
     */
160
    private function getMockGlobalSet(int $setId, string $siteHandle = 'default')
161
    {
162
        $mockSet = $this->getMockBuilder(GlobalSetElement::class)
163
                                    ->setMethods(['__isset', 'getSite', 'getFieldLayout', 'fieldByHandle'])
164
                                    ->disableOriginalConstructor()
165
                                    ->getMock();
166
167
        $mockSet->id = $setId;
0 ignored issues
show
Bug introduced by
Accessing id on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
168
        $mockSet->fieldLayoutId = $setId;
0 ignored issues
show
Bug introduced by
Accessing fieldLayoutId on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
169
        $mockSet->handle = 'setHandle'.$setId;
0 ignored issues
show
Bug introduced by
Accessing handle on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
170
        $mockSet->name = 'setName'.$setId;
0 ignored issues
show
Bug introduced by
Accessing name on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
171
172
        $mockSet->expects($this->any())
173
                ->method('getSite')
174
                ->willReturn($this->getMockSite($siteHandle));
175
176
        $mockField = $this->getMockbuilder(Field::class)->getMock();
177
        $mockField->id = $setId;
0 ignored issues
show
Bug introduced by
Accessing id on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
178
        $mockField->handle = 'field'.$setId;
0 ignored issues
show
Bug introduced by
Accessing handle on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
179
        $mockField->required = false;
0 ignored issues
show
Bug introduced by
Accessing required on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
180
181
        $mockFieldLayout = $this->getMockBuilder(FieldLayout::class)->getMock();
182
183
        $mockFieldLayout->expects($this->any())
184
                        ->method('getFields')
185
                        ->willReturn([$mockField]);
186
187
        $mockSet->expects($this->any())
188
                  ->method('getFieldLayout')
189
                  ->willReturn($mockFieldLayout);
190
191
        return $mockSet;
192
    }
193
194
    /**
195
     * Get a mock site.
196
     *
197
     * @param string $handle
198
     *
199
     * @return Mock|Site
200
     */
201
    private function getMockSite(string $handle = 'default')
202
    {
203
        $mockSite = new Site([
204
            'id' => 99,
205
            'handle' => $handle,
206
        ]);
207
208
        return $mockSite;
209
    }
210
}
211