Completed
Pull Request — master (#114)
by Bart
09:10
created

GlobalSetsTest::provideValidGlobalSetDefinitions()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 18
nc 1
nop 0
1
<?php
2
3
namespace NerdsAndCompany\Schematic\Services;
4
5
use Craft;
6
use craft\elements\GlobalSet;
7
use craft\models\FieldLayout;
8
use craft\models\Site;
9
use craft\services\Fields;
10
use Codeception\Test\Unit;
11
use NerdsAndCompany\Schematic\Schematic;
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 $service;
28
29
    /**
30
     * Set the service.
31
     *
32
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
33
     */
34
    protected function _before()
35
    {
36
        Craft::$app->sites->expects($this->any())
37
                  ->method('getSiteByHandle')
38
                  ->willReturn($this->getMockSite());
39
40
        $this->service = new ModelProcessor();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \NerdsAndCompany\Sch...rvices\ModelProcessor() of type object<NerdsAndCompany\S...ervices\ModelProcessor> is incompatible with the declared type object<NerdsAndCompany\S...ic\Services\GlobalSets> of property $service.

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
43
    //==============================================================================================================
44
    //=================================================  TESTS  ====================================================
45
    //==============================================================================================================
46
47
    /**
48
     * @dataProvider provideValidGlobalSets
49
     *
50
     * @param GlobalSetModel[] $sets
51
     * @param array            $expectedResult
52
     */
53
    public function testSuccessfulExport(array $sets, array $expectedResult = [])
54
    {
55
        $actualResult = $this->service->export($sets);
56
57
        $this->assertSame($expectedResult, $actualResult);
58
    }
59
60
    /**
61
     * @dataProvider provideValidGlobalSetDefinitions
62
     *
63
     * @param array $setDefinitions
64
     */
65
    public function testSuccessfulImport(array $setDefinitions, array $existingSets, int $saveCount)
66
    {
67
        $this->expectSaves($saveCount);
68
        $this->expectDeletes(0);
69
70
        $this->service->import($setDefinitions, $existingSets);
71
    }
72
73
    /**
74
     * @dataProvider provideValidGlobalSetDefinitions
75
     *
76
     * @param array $setDefinitions
77
     */
78
    public function testImportWithForceOption(array $setDefinitions, array $existingSets, int $saveCount, int $deleteCount)
79
    {
80
        Schematic::$force = true;
81
        $this->expectSaves($saveCount);
82
        $this->expectDeletes($deleteCount);
83
84
        $this->service->import($setDefinitions, $existingSets);
85
    }
86
87
    //==============================================================================================================
88
    //==============================================  PROVIDERS  ===================================================
89
    //==============================================================================================================
90
91
    /**
92
     * @return array
93
     */
94
    public function provideValidGlobalSets()
95
    {
96
        $mockGlobalSet1 = $this->getMockGlobalSet(1);
97
        $mockGlobalSet2 = $this->getMockGlobalSet(2);
98
99
        return [
100
            'emptyArray' => [
101
                'GlobalSets' => [],
102
                'expectedResult' => [],
103
            ],
104
            'single set' => [
105
                'GlobalSets' => [
106
                    'set1' => $mockGlobalSet1,
107
                ],
108
                'expectedResult' => [
109
                    'setHandle1' => $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...
110
                ],
111
            ],
112
            'multiple sets' => [
113
                'GlobalSets' => [
114
                    'set1' => $mockGlobalSet1,
115
                    'set2' => $mockGlobalSet2,
116
                ],
117
                'expectedResult' => [
118
                    'setHandle1' => $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...
119
                    'setHandle2' => $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...
120
                ],
121
            ],
122
        ];
123
    }
124
125
    /**
126
     * @return array
127
     */
128
    public function provideValidGlobalSetDefinitions()
129
    {
130
        $mockGlobalSet1 = $this->getMockGlobalSet(1);
131
        $mockGlobalSet2 = $this->getMockGlobalSet(2);
132
133
        return [
134
            'emptyArray' => [
135
                'setDefinitions' => [],
136
                'existingSets' => [
137
                    $mockGlobalSet1,
138
                ],
139
                'saveCount' => 0,
140
                'deleteCount' => 1,
141
            ],
142
            'single set' => [
143
                'setDefinitions' => [
144
                    'setHandle1' => $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...
145
                    'setHandle2' => $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...
146
                ],
147
                'existingSets' => [
148
                    $mockGlobalSet1,
149
                ],
150
                'saveCount' => 1,
151
                'deleteCount' => 0,
152
            ],
153
        ];
154
    }
155
156
    //==============================================================================================================
157
    //================================================  HELPERS  ===================================================
158
    //==============================================================================================================
159
160
    /**
161
     * @param GlobalSet $mockGlobalSet
162
     *
163
     * @return array
164
     */
165
    private function getMockGlobalSetDefinition(GlobalSet $mockGlobalSet)
166
    {
167
        return [
168
            'class' => get_class($mockGlobalSet),
169
            'attributes' => [
170
                'name' => $mockGlobalSet->name,
171
                'handle' => $mockGlobalSet->handle,
172
                'enabled' => true,
173
                'archived' => false,
174
                'enabledForSite' => true,
175
                'title' => null,
176
                'slug' => null,
177
                'uri' => null,
178
            ],
179
            'fieldLayout' => [
180
                'fields' => [],
181
            ],
182
            'site' => 'default',
183
        ];
184
    }
185
186
    /**
187
     * @param int $setId
188
     *
189
     * @return Mock|GlobalSet
190
     */
191
    private function getMockGlobalSet(int $setId)
192
    {
193
        $mockSet = $this->getMockBuilder(GlobalSet::class)
194
                                    ->setMethods(array_diff(
195
                                        get_class_methods(GlobalSet::class),
196
                                        ['setAttributes', 'safeAttributes', 'getAttributes', 'getFields']
197
                                    ))
198
                                    ->disableOriginalConstructor()
199
                                    ->getMock();
200
201
        $mockSet->expects($this->any())
202
          ->method('attributes')
203
          ->willReturn([
204
              'id',
205
              'fieldLayoutId',
206
              'siteId',
207
              'structureId',
208
              'tempId',
209
              'uid',
210
              'contentId',
211
              'name',
212
              'handle',
213
              'enabled',
214
              'archived',
215
              'enabledForSite',
216
              'title',
217
              'slug',
218
              'uri',
219
              'hasDescendants',
220
              'ref',
221
              'status',
222
              'structureId',
223
              'totalDescendants',
224
              'url',
225
          ]);
226
227
        $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...
228
        $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...
229
        $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...
230
        $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...
231
232
        $mockSet->expects($this->any())
233
                ->method('getSite')
234
                ->willReturn($this->getMockSite());
235
236
        $mockSet->expects($this->any())
237
                ->method('getScenario')
238
                ->willReturn([]);
239
240
        $mockFieldLayout = $this->getMockBuilder(FieldLayout::class)->getMock();
241
242
        $mockFieldLayout->expects($this->any())
243
                        ->method('getFields')
244
                        ->willReturn([]);
245
246
        $mockSet->expects($this->any())
247
                  ->method('getFieldLayout')
248
                  ->willReturn($mockFieldLayout);
249
250
        return $mockSet;
251
    }
252
253
    /**
254
     * Get a mock site.
255
     *
256
     * @return Mock|Site
257
     */
258
    private function getMockSite()
259
    {
260
        $mockSite = new Site([
261
            'id' => 99,
262
            'handle' => 'default',
263
        ]);
264
265
        return $mockSite;
266
    }
267
268
    /**
269
     * Expect a number of set saves.
270
     *
271
     * @param int $saveCount
272
     */
273
    private function expectSaves(int $saveCount)
274
    {
275
        Craft::$app->globals
276
                   ->expects($this->exactly($saveCount))
277
                   ->method('saveSet')
278
                   ->willReturn(true);
279
    }
280
281
    /**
282
     * Expect a number of set deletes.
283
     *
284
     * @param int $deleteCount
285
     */
286
    private function expectDeletes(int $deleteCount)
287
    {
288
        Craft::$app->elements
289
                    ->expects($this->exactly($deleteCount))
290
                    ->method('deleteElementById');
291
    }
292
}
293