Completed
Push — do-not-scrutinize-tests ( fcf005 )
by Bart
04:15 queued 02:38
created

ModelMapperTest::provideImportModels()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 34
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 23
nc 1
nop 0
1
<?php
2
3
namespace NerdsAndCompany\Schematic\Mappers;
4
5
use Craft;
6
use craft\base\Model;
7
use Codeception\Test\Unit;
8
use NerdsAndCompany\Schematic\Schematic;
9
use NerdsAndCompany\Schematic\Converters\Models\Base as Converter;
10
11
/**
12
 * Class ModelMapperTest.
13
 *
14
 * @author    Nerds & Company
15
 * @copyright Copyright (c) 2015-2017, Nerds & Company
16
 * @license   MIT
17
 *
18
 * @see      http://www.nerds.company
19
 */
20
class ModelMapperTest extends Unit
21
{
22
    /**
23
     * @var ModelMapper
24
     */
25
    private $mapper;
26
27
    /**
28
     * Set the mapper.
29
     *
30
     * @SuppressWarnings(PHPMD.CamelCaseMethodName)
31
     * phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
32
     */
33
    protected function _before()
34
    {
35
        $this->mapper = new ModelMapper();
36
    }
37
38
    //==============================================================================================================
39
    //=================================================  TESTS  ====================================================
40
    //==============================================================================================================
41
42
    /**
43
     * @dataProvider provideExportModels
44
     *
45
     * @param Model[] $models
46
     * @param array   $expectedResult
47
     */
48
    public function testSuccessfulExport(array $models, array $expectedResult = [])
49
    {
50
        $converter = $this->getMockConverter();
51
        $this->expectConverter($converter, count($models));
52
53
        $actualResult = $this->mapper->export($models);
54
55
        $this->assertSame($expectedResult, $actualResult);
56
    }
57
58
    /**
59
     * @dataProvider provideImportModels
60
     *
61
     * @param Model[] $existingGroups
62
     * @param array   $modelDefinitions
63
     * @param int     $saveCount
64
     */
65
    public function testUnSuccessfulImport(array $existingGroups, array $modelDefinitions, int $saveCount)
66
    {
67
        $converter = $this->getMockConverter();
68
        $this->expectConverter($converter, count($modelDefinitions));
69
        $this->expectSaves($converter, $saveCount, false);
70
        $this->expectDeletes($converter, 0);
71
72
        $this->mapper->import($modelDefinitions, $existingGroups);
73
    }
74
75
    /**
76
     * @dataProvider provideImportModels
77
     *
78
     * @param Model[] $existingGroups
79
     * @param array   $modelDefinitions
80
     * @param int     $saveCount
81
     */
82
    public function testSuccessfulImport(array $existingGroups, array $modelDefinitions, int $saveCount)
83
    {
84
        $converter = $this->getMockConverter();
85
        $this->expectConverter($converter, count($modelDefinitions));
86
        $this->expectSaves($converter, $saveCount);
87
        $this->expectDeletes($converter, 0);
88
89
        $this->mapper->import($modelDefinitions, $existingGroups);
90
    }
91
92
    /**
93
     * @dataProvider provideImportModels
94
     *
95
     * @param Model[] $existingGroups
96
     * @param array   $modelDefinitions
97
     * @param int     $saveCount
98
     * @param int     $deleteCount
99
     */
100
    public function testSuccessfulImportWithForceOption(
101
        array $existingGroups,
102
        array $modelDefinitions,
103
        int $saveCount,
104
        int $deleteCount
105
    ) {
106
        Schematic::$force = true;
107
        $converter = $this->getMockConverter();
108
        $this->expectConverter($converter, count($modelDefinitions) + $deleteCount);
109
        $this->expectSaves($converter, $saveCount);
110
        $this->expectDeletes($converter, $deleteCount);
111
112
        $this->mapper->import($modelDefinitions, $existingGroups);
113
    }
114
115
    /**
116
     * @dataProvider provideImportModels
117
     *
118
     * @param Model[] $existingGroups
119
     * @param array   $modelDefinitions
120
     * @param int     $saveCount
121
     * @param int     $deleteCount
122
     */
123
    public function testUnsuccessfulImportWithForceOption(
124
        array $existingGroups,
125
        array $modelDefinitions,
126
        int $saveCount,
127
        int $deleteCount
128
    ) {
129
        Schematic::$force = true;
130
        $converter = $this->getMockConverter();
131
        $this->expectConverter($converter, count($modelDefinitions) + $deleteCount);
132
        $this->expectSaves($converter, $saveCount, false);
133
        $this->expectDeletes($converter, $deleteCount);
134
135
        $this->mapper->import($modelDefinitions, $existingGroups);
136
    }
137
138
    //==============================================================================================================
139
    //==============================================  PROVIDERS  ===================================================
140
    //==============================================================================================================
141
142
    /**
143
     * @return array
144
     */
145
    public function provideExportModels()
146
    {
147
        $mockModel1 = $this->getMockModel(1);
148
        $mockModel2 = $this->getMockModel(2);
149
150
        return [
151
            'empty array' => [
152
                'models' => [],
153
                'modelDefinitions' => [],
154
            ],
155
            'single model' => [
156
                'models' => [
157
                    $mockModel1,
158
                ],
159
                'modelDefinitions' => [
160
                    'modelHandle1' => $this->getMockModelDefinition($mockModel1),
161
                ],
162
            ],
163
            'multiple models' => [
164
                'models' => [
165
                    $mockModel1,
166
                    $mockModel2,
167
                ],
168
                'modelDefinitions' => [
169
                    'modelHandle1' => $this->getMockModelDefinition($mockModel1),
170
                    'modelHandle2' => $this->getMockModelDefinition($mockModel2),
171
                ],
172
            ],
173
        ];
174
    }
175
176
    /**
177
     * @return array
178
     */
179
    public function provideImportModels()
180
    {
181
        $mockModel1 = $this->getMockModel(1);
182
        $mockModel2 = $this->getMockModel(2);
183
184
        return [
185
            'empty array' => [
186
                'models' => [],
187
                'modelDefinitions' => [],
188
                'saveCount' => 0,
189
                'deleteCount' => 0,
190
            ],
191
            'single old model' => [
192
                'models' => [
193
                    $mockModel1,
194
                ],
195
                'modelDefinitions' => [],
196
                'saveCount' => 0,
197
                'deleteCount' => 1,
198
            ],
199
            'single new model' => [
200
                'models' => [
201
                    $mockModel1,
202
                ],
203
                'modelDefinitions' => [
204
                    'modelHandle1' => $this->getMockModelDefinition($mockModel1),
205
                    'modelHandle2' => $this->getMockModelDefinition($mockModel2),
206
                ],
207
208
                'saveCount' => 1,
209
                'deleteCount' => 0,
210
            ],
211
        ];
212
    }
213
214
    //==============================================================================================================
215
    //================================================  HELPERS  ===================================================
216
    //==============================================================================================================
217
218
    /**
219
     * Get model definition for mock model.
220
     *
221
     * @param Model $mockModel
222
     *
223
     * @return array
224
     */
225
    private function getMockModelDefinition(Model $mockModel): array
226
    {
227
        return [
228
            'class' => get_class($mockModel),
229
            'attributes' => [
230
                'name' => $mockModel->name,
231
                'handle' => $mockModel->handle,
232
                'max' => 100,
233
                'other' => 'stuff',
234
            ],
235
        ];
236
    }
237
238
    /**
239
     * Get a mock model.
240
     *
241
     * @param int $modelId
242
     *
243
     * @return Mock|Model
244
     */
245
    private function getMockModel(int $modelId): Model
246
    {
247
        $mockModel = $this->getMockBuilder(Model::class)->getMock();
248
        $mockModel->expects($this->any())
249
                  ->method('__get')
250
                  ->willReturnMap([
251
                        ['id', $modelId],
252
                        ['handle', 'modelHandle'.$modelId],
253
                        ['name', 'modelName'.$modelId],
254
                  ]);
255
256
        return $mockModel;
257
    }
258
259
    /**
260
     * Get a mock converter.
261
     *
262
     * @return Converter
263
     */
264
    private function getMockConverter(): Converter
265
    {
266
        $mockConverter = $this->getMockBuilder(Converter::class)->getMock();
267
268
        $mockConverter->expects($this->any())
269
                      ->method('getRecordDefinition')
270
                      ->willReturnCallback(function ($model) {
271
                          return $this->getMockModelDefinition($model);
272
                      });
273
274
        return $mockConverter;
275
    }
276
277
    /**
278
     * Mock a converter.
279
     *
280
     * @param Mock|Converter|null $converter
281
     */
282
    private function expectConverter($converter, int $count)
283
    {
284
        Craft::$app->controller->module->expects($this->exactly($count))
285
                                       ->method('getConverter')
286
                                       ->willReturn($converter);
287
    }
288
289
    /**
290
     * Expect a number of model saves.
291
     *
292
     * @param Converter $converter
293
     * @param int       $saveCount
294
     * @param bool      $return
295
     */
296
    private function expectSaves(Converter $converter, int $saveCount, bool $return = true)
297
    {
298
        $converter->expects($this->exactly($saveCount))
299
                  ->method('saveRecord')
300
                  ->willReturn($return);
301
    }
302
303
    /**
304
     * Expect a number of model deletes.
305
     *
306
     * @param Converter $converter
307
     * @param int       $deleteCount
308
     */
309
    private function expectDeletes(Converter $converter, int $deleteCount)
310
    {
311
        $converter->expects($this->exactly($deleteCount))
312
                  ->method('deleteRecord');
313
    }
314
}
315