Completed
Push — master ( ae47f3...33ec04 )
by Bob Olde
11s
created

GlobalSetsTest   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 8
dl 0
loc 210
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A _before() 0 4 1
A testGetRecordDefinition() 0 6 1
A testSaveRecord() 0 18 2
A testDeleteRecord() 0 8 1
A provideGlobalSets() 0 18 1
B getMockGlobalSetDefinition() 0 25 2
A getMockGlobalSet() 0 51 1
A getMockSite() 0 9 1
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 yii\base\Behavior;
9
use craft\models\FieldLayout;
10
use craft\models\Site;
11
use craft\services\Fields;
12
use Codeception\Test\Unit;
13
14
/**
15
 * Class GlobalSetTest.
16
 *
17
 * @author    Nerds & Company
18
 * @copyright Copyright (c) 2015-2017, Nerds & Company
19
 * @license   MIT
20
 *
21
 * @see      http://www.nerds.company
22
 */
23
class GlobalSetsTest extends Unit
24
{
25
    /**
26
     * @var GlobalSets
27
     */
28
    private $converter;
29
30
    /**
31
     * Set the converter.
32
     *
33
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
34
     */
35
    protected function _before()
36
    {
37
        $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...
38
    }
39
40
    //==============================================================================================================
41
    //=================================================  TESTS  ====================================================
42
    //==============================================================================================================
43
44
    /**
45
     * @dataProvider provideGlobalSets
46
     *
47
     * @param GlobalSetElement $set
48
     * @param array            $definition
49
     */
50
    public function testGetRecordDefinition(GlobalSetElement $set, array $definition)
51
    {
52
        $result = $this->converter->getRecordDefinition($set);
53
54
        $this->assertSame($definition, $result);
55
    }
56
57
    /**
58
     * @dataProvider provideGlobalSets
59
     *
60
     * @param GlobalSetElement $set
61
     * @param array            $definition
62
     * @param bool             $valid
63
     */
64
    public function testSaveRecord(GlobalSetElement $set, array $definition, bool $valid)
65
    {
66
        Craft::$app->sites->expects($this->any())
67
                ->method('getSiteByHandle')
68
                ->willReturnMap([
69
                  ['default', $this->getMockSite()],
70
                  ['invalid', null],
71
                ]);
72
73
        Craft::$app->globals->expects($this->exactly($valid ? 1 : 0))
74
                            ->method('saveSet')
75
                            ->with($set)
76
                            ->willReturn(true);
77
78
        $result = $this->converter->saveRecord($set, $definition);
79
80
        $this->assertSame($valid, $result);
81
    }
82
83
    /**
84
     * @dataProvider provideGlobalSets
85
     *
86
     * @param GlobalSetElement $set
87
     */
88
    public function testDeleteRecord(GlobalSetElement $set)
89
    {
90
        Craft::$app->elements->expects($this->exactly(1))
91
                             ->method('deleteElementById')
92
                             ->with($set->id);
93
94
        $this->converter->deleteRecord($set);
95
    }
96
97
    //==============================================================================================================
98
    //==============================================  PROVIDERS  ===================================================
99
    //==============================================================================================================
100
101
    /**
102
     * @return array
103
     */
104
    public function provideGlobalSets()
105
    {
106
        $mockGlobalSet1 = $this->getMockGlobalSet(1);
107
        $mockGlobalSet2 = $this->getMockGlobalSet(1, 'invalid');
108
109
        return [
110
            'Valid set' => [
111
                'set' => $mockGlobalSet1,
112
                '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...
113
                'validSave' => true,
114
            ],
115
            'Invalid set' => [
116
                'set' => $mockGlobalSet2,
117
                '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...
118
                'validSave' => false,
119
            ],
120
        ];
121
    }
122
123
    //==============================================================================================================
124
    //================================================  HELPERS  ===================================================
125
    //==============================================================================================================
126
127
    /**
128
     * @param GlobalSet $mockGlobalSet
129
     *
130
     * @return array
131
     */
132
    private function getMockGlobalSetDefinition(GlobalSetElement $mockGlobalSet)
133
    {
134
        $fieldDefs = [];
135
        foreach ($mockGlobalSet->getFieldLayout()->getFields() as $field) {
136
            $fieldDefs[$field->handle] = $field->required;
137
        }
138
139
        return [
140
            'class' => get_class($mockGlobalSet),
141
            'attributes' => [
142
                'name' => $mockGlobalSet->name,
143
                'handle' => $mockGlobalSet->handle,
144
                'enabled' => true,
145
                'archived' => false,
146
                'enabledForSite' => true,
147
                'title' => null,
148
                'slug' => null,
149
                'uri' => null,
150
            ],
151
            'fieldLayout' => [
152
                'fields' => $fieldDefs,
153
            ],
154
            'site' => $mockGlobalSet->getSite()->handle,
155
        ];
156
    }
157
158
    /**
159
     * @param int    $setId
160
     * @param string $siteHandle
161
     *
162
     * @return Mock|GlobalSet
163
     */
164
    private function getMockGlobalSet(int $setId, string $siteHandle = 'default')
165
    {
166
        $mockSet = $this->getMockBuilder(GlobalSetElement::class)
167
                                    ->setMethods(['__isset', 'getSite', 'getFieldLayout', 'fieldByHandle', 'getBehavior', 'behaviors'])
168
                                    ->disableOriginalConstructor()
169
                                    ->getMock();
170
171
        $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...
172
        $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...
173
        $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...
174
        $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...
175
176
        $mockBehavior = $this->getMockbuilder(Behavior::class)->getMock();
177
178
        $mockBehavior->expects($this->any())
179
                     ->method('canGetProperty')
180
                     ->willReturn(true);
181
182
        $mockSet->expects($this->any())
183
                ->method('behaviors')
184
                ->willReturn([$mockBehavior]);
185
186
        $mockSet->expects($this->any())
187
                ->method('getBehavior')
188
                ->willReturn($mockBehavior);
189
190
        $mockSet->expects($this->any())
191
                ->method('getSite')
192
                ->willReturn($this->getMockSite($siteHandle));
193
194
        $mockField = $this->getMockbuilder(Field::class)->getMock();
195
        $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...
196
        $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...
197
        $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...
198
199
        $mockSet->expects($this->any())
200
                ->method('fieldByHandle')
201
                ->willReturn($mockField);
202
203
        $mockFieldLayout = $this->getMockBuilder(FieldLayout::class)->getMock();
204
205
        $mockFieldLayout->expects($this->any())
206
                        ->method('getFields')
207
                        ->willReturn([$mockField]);
208
209
        $mockSet->expects($this->any())
210
                  ->method('getFieldLayout')
211
                  ->willReturn($mockFieldLayout);
212
213
        return $mockSet;
214
    }
215
216
    /**
217
     * Get a mock site.
218
     *
219
     * @param string $handle
220
     *
221
     * @return Mock|Site
222
     */
223
    private function getMockSite(string $handle = 'default')
224
    {
225
        $mockSite = new Site([
226
            'id' => 99,
227
            'handle' => $handle,
228
        ]);
229
230
        return $mockSite;
231
    }
232
}
233