Completed
Pull Request — master (#114)
by Bart
16:03 queued 06:02
created

GlobalSetsTest::testImportWithForceOption()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 4
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
                'hasDescendants' => null,
179
                'ref' => null,
180
                'status' => null,
181
                'totalDescendants' => null,
182
                'url' => null,
183
                'text' => null,
184
            ],
185
            'fieldLayout' => [
186
                'fields' => [],
187
            ],
188
            'site' => 'default',
189
        ];
190
    }
191
192
    /**
193
     * @param int $setId
194
     *
195
     * @return Mock|GlobalSet
196
     */
197
    private function getMockGlobalSet(int $setId)
198
    {
199
        $mockSet = $this->getMockBuilder(GlobalSet::class)
200
                                    ->setMethods(array_diff(
201
                                        get_class_methods(GlobalSet::class),
202
                                        ['setAttributes', 'safeAttributes', 'getAttributes', 'getFields']
203
                                    ))
204
                                    ->disableOriginalConstructor()
205
                                    ->getMock();
206
207
        $mockSet->expects($this->any())
208
          ->method('attributes')
209
          ->willReturn([
210
              'id',
211
              'fieldLayoutId',
212
              'siteId',
213
              'structureId',
214
              'tempId',
215
              'uid',
216
              'contentId',
217
              'name',
218
              'handle',
219
              'enabled',
220
              'archived',
221
              'enabledForSite',
222
              'title',
223
              'slug',
224
              'uri',
225
              'hasDescendants',
226
              'ref',
227
              'status',
228
              'structureId',
229
              'totalDescendants',
230
              'url',
231
              'text',
232
          ]);
233
234
        $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...
235
        $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...
236
        $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...
237
        $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...
238
239
        $mockSet->expects($this->any())
240
                ->method('getSite')
241
                ->willReturn($this->getMockSite());
242
243
        $mockFieldLayout = $this->getMockBuilder(FieldLayout::class)->getMock();
244
245
        $mockFieldLayout->expects($this->any())
246
                        ->method('getFields')
247
                        ->willReturn([]);
248
249
        $mockSet->expects($this->any())
250
                  ->method('getFieldLayout')
251
                  ->willReturn($mockFieldLayout);
252
253
        return $mockSet;
254
    }
255
256
    /**
257
     * Get a mock site.
258
     *
259
     * @return Mock|Site
260
     */
261
    private function getMockSite()
262
    {
263
        $mockSite = new Site([
264
            'id' => 99,
265
            'handle' => 'default',
266
        ]);
267
268
        return $mockSite;
269
    }
270
271
    /**
272
     * Expect a number of set saves.
273
     *
274
     * @param int $saveCount
275
     */
276
    private function expectSaves(int $saveCount)
277
    {
278
        Craft::$app->globals
279
                   ->expects($this->exactly($saveCount))
280
                   ->method('saveSet')
281
                   ->willReturn(true);
282
    }
283
284
    /**
285
     * Expect a number of set deletes.
286
     *
287
     * @param int $deleteCount
288
     */
289
    private function expectDeletes(int $deleteCount)
290
    {
291
        Craft::$app->elements
292
                    ->expects($this->exactly($deleteCount))
293
                    ->method('deleteElementById');
294
    }
295
}
296