|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Drupal\Tests\Driver; |
|
4
|
|
|
|
|
5
|
|
|
use Drupal\Driver\Wrapper\Field\DriverFieldDrupal8; |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* Tests the Driver's plugin managers. |
|
9
|
|
|
*/ |
|
10
|
|
|
class DriverPluginManagersTest extends \PHPUnit_Framework_TestCase |
|
11
|
|
|
{ |
|
12
|
|
|
|
|
13
|
|
|
/** |
|
14
|
|
|
* {@inheritdoc} |
|
15
|
|
|
*/ |
|
16
|
|
|
public function tearDown() |
|
17
|
|
|
{ |
|
18
|
|
|
\Mockery::close(); |
|
19
|
|
|
} |
|
20
|
|
|
|
|
21
|
|
|
/** |
|
22
|
|
|
* Factory method to build and returned a mocked field handler. |
|
23
|
|
|
* |
|
24
|
|
|
* @param array $target |
|
25
|
|
|
* The properties to find a matching plugin for. |
|
26
|
|
|
* @param array $mockFilters |
|
27
|
|
|
* The possible filters for the mocked plugin manager. |
|
28
|
|
|
* @param array $mockCriteria |
|
29
|
|
|
* The specificity criteria for the mocked plugin manager. |
|
30
|
|
|
* @param array $mockDefinitions |
|
31
|
|
|
* The plugins to be discovered by the mocked plugin manager. |
|
32
|
|
|
* |
|
33
|
|
|
* @return array |
|
34
|
|
|
* The ids of the matching mock definitions. |
|
35
|
|
|
*/ |
|
36
|
|
View Code Duplication |
public function getMatchedPluginIds($target, $mockFilters, $mockCriteria, $mockDefinitions) |
|
|
|
|
|
|
37
|
|
|
{ |
|
38
|
|
|
|
|
39
|
|
|
|
|
40
|
|
|
$mock = \Mockery::mock('Drupal\Driver\Plugin\DriverPluginManagerBase'); |
|
41
|
|
|
$mock->makePartial(); |
|
42
|
|
|
$mock->shouldAllowMockingProtectedMethods(); |
|
43
|
|
|
$mock->shouldReceive('getFilters')->andReturn($mockFilters); |
|
44
|
|
|
$mock->shouldReceive('getSpecificityCriteria')->andReturn($mockCriteria); |
|
45
|
|
|
$mock->shouldReceive('getDefinitions')->andReturn($mockDefinitions); |
|
46
|
|
|
|
|
47
|
|
|
$matchedDefinitions = $mock->getMatchedDefinitions($target); |
|
|
|
|
|
|
48
|
|
|
$matchedIds = array_column($matchedDefinitions, 'id'); |
|
49
|
|
|
return $matchedIds; |
|
50
|
|
|
} |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* Tests the plugin manager base's definition matching. |
|
54
|
|
|
* |
|
55
|
|
|
* @param array $target |
|
56
|
|
|
* The properties to find a matching plugin for. |
|
57
|
|
|
* @param array $mockFilters |
|
58
|
|
|
* The possible filters for the mocked plugin manager. |
|
59
|
|
|
* @param array $mockCriteria |
|
60
|
|
|
* The specificity criteria for the mocked plugin manager. |
|
61
|
|
|
* @param array $mockDefinitions |
|
62
|
|
|
* The plugins to be discovered by the mocked plugin manager. |
|
63
|
|
|
* @param array $expectedIds |
|
64
|
|
|
* The ids of the mock definitions that match the target. |
|
65
|
|
|
* |
|
66
|
|
|
* @dataProvider managerBaseMatchedDefinitionsData |
|
67
|
|
|
*/ |
|
68
|
|
View Code Duplication |
public function testManagerBaseMatchedDefinitions($target, $mockFilters, $mockCriteria, $mockDefinitions, $expectedIds) |
|
|
|
|
|
|
69
|
|
|
{ |
|
70
|
|
|
$mock = \Mockery::mock('Drupal\Driver\Plugin\DriverPluginManagerBase'); |
|
71
|
|
|
$mock->makePartial(); |
|
72
|
|
|
$mock->shouldAllowMockingProtectedMethods(); |
|
73
|
|
|
$mock->shouldReceive('getFilters')->andReturn($mockFilters); |
|
74
|
|
|
$mock->shouldReceive('getSpecificityCriteria')->andReturn($mockCriteria); |
|
75
|
|
|
$mock->shouldReceive('getDefinitions')->andReturn($mockDefinitions); |
|
76
|
|
|
|
|
77
|
|
|
$matchedDefinitions = $mock->getMatchedDefinitions($target); |
|
|
|
|
|
|
78
|
|
|
$ids = array_column($matchedDefinitions, 'id'); |
|
79
|
|
|
$this->assertEquals($expectedIds, $ids); |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* Data provider for testManagerBaseMatchedDefinitions(). |
|
84
|
|
|
* |
|
85
|
|
|
* @return array |
|
86
|
|
|
* An array of test data. |
|
87
|
|
|
*/ |
|
88
|
|
|
public function managerBaseMatchedDefinitionsData() |
|
89
|
|
|
{ |
|
90
|
|
|
$mockFilters = ['a','b']; |
|
91
|
|
|
|
|
92
|
|
|
$mockCriteria = [ |
|
93
|
|
|
['a', 'b'], |
|
94
|
|
|
['a'], |
|
95
|
|
|
['b'], |
|
96
|
|
|
]; |
|
97
|
|
|
|
|
98
|
|
|
$mockDefinitions = [ |
|
99
|
|
|
['id' => 'A', 'weight' => 0, 'a' => [1], 'b' => [1],], |
|
100
|
|
|
['id' => 'B', 'weight' => 0, 'a' => [1],], |
|
101
|
|
|
['id' => 'C', 'weight' => 0, 'b' => [1],], |
|
102
|
|
|
['id' => 'D', 'weight' => 0, 'a' => [2], 'b' => [1],], |
|
103
|
|
|
['id' => 'E', 'weight' => 0, 'a' => [1], 'b' => [2],], |
|
104
|
|
|
]; |
|
105
|
|
|
|
|
106
|
|
|
$multivalueDefinitions = $mockDefinitions; |
|
107
|
|
|
$multivalueDefinitions[0]['a'] = [1,3]; |
|
108
|
|
|
$multivalueDefinitions[2]['b'] = [1,2]; |
|
109
|
|
|
|
|
110
|
|
|
$alphaAdjustedDefinitions = $mockDefinitions; |
|
111
|
|
|
$alphaAdjustedDefinitions[] = $alphaAdjustedDefinitions[0]; |
|
112
|
|
|
$alphaAdjustedDefinitions[0]['id'] = 'F'; |
|
113
|
|
|
|
|
114
|
|
|
|
|
115
|
|
|
return array( |
|
116
|
|
|
// Test non-matching values are rejected over multiple filters. |
|
117
|
|
|
[ |
|
118
|
|
|
['a' => 2, 'b' => 2], |
|
119
|
|
|
$mockFilters, |
|
120
|
|
|
$mockCriteria, |
|
121
|
|
|
$mockDefinitions, |
|
122
|
|
|
[], |
|
123
|
|
|
], |
|
124
|
|
|
|
|
125
|
|
|
// Test all matching values are accepted. |
|
126
|
|
|
[ |
|
127
|
|
|
['a' => 1, 'b' => 1], |
|
128
|
|
|
$mockFilters, |
|
129
|
|
|
$mockCriteria, |
|
130
|
|
|
$mockDefinitions, |
|
131
|
|
|
['A', 'B', 'C'], |
|
132
|
|
|
], |
|
133
|
|
|
|
|
134
|
|
|
// Test specific comes before general regardless of definition order. |
|
135
|
|
|
[ |
|
136
|
|
|
['a' => 1, 'b' => 2], |
|
137
|
|
|
$mockFilters, |
|
138
|
|
|
$mockCriteria, |
|
139
|
|
|
$mockDefinitions, |
|
140
|
|
|
['E', 'B'], |
|
141
|
|
|
], |
|
142
|
|
|
|
|
143
|
|
|
// Test specific comes before general regardless of definition order. |
|
144
|
|
|
[ |
|
145
|
|
|
['a' => 2, 'b' => 1], |
|
146
|
|
|
$mockFilters, |
|
147
|
|
|
$mockCriteria, |
|
148
|
|
|
$mockDefinitions, |
|
149
|
|
|
['D', 'C'], |
|
150
|
|
|
], |
|
151
|
|
|
|
|
152
|
|
|
// Test weight overrules specificity. |
|
153
|
|
|
[ |
|
154
|
|
|
['a' => 1, 'b' => 1], |
|
155
|
|
|
$mockFilters, |
|
156
|
|
|
$mockCriteria, |
|
157
|
|
|
[ |
|
158
|
|
|
['id' => 'A', 'weight' => 0, 'a' => [1], 'b' => [1],], |
|
159
|
|
|
['id' => 'B', 'weight' => 10, 'a' => [1],], |
|
160
|
|
|
['id' => 'C', 'weight' => 0, 'b' => [1],], |
|
161
|
|
|
['id' => 'D', 'weight' => 0, 'a' => [2], 'b' => [1],], |
|
162
|
|
|
['id' => 'E', 'weight' => 0, 'a' => [1], 'b' => [2],], |
|
163
|
|
|
], |
|
164
|
|
|
['B', 'A', 'C'], |
|
165
|
|
|
], |
|
166
|
|
|
|
|
167
|
|
|
// Test value in multivalue definitions. |
|
168
|
|
|
[ |
|
169
|
|
|
['a' => 1, 'b' => 1], |
|
170
|
|
|
$mockFilters, |
|
171
|
|
|
$mockCriteria, |
|
172
|
|
|
$multivalueDefinitions, |
|
173
|
|
|
['A', 'B', 'C'], |
|
174
|
|
|
], |
|
175
|
|
|
|
|
176
|
|
|
// Test plugins are sorted by id if weight and specificity are equal. |
|
177
|
|
|
[ |
|
178
|
|
|
['a' => 1, 'b' => 1], |
|
179
|
|
|
$mockFilters, |
|
180
|
|
|
$mockCriteria, |
|
181
|
|
|
$alphaAdjustedDefinitions, |
|
182
|
|
|
['A', 'F', 'B', 'C'], |
|
183
|
|
|
], |
|
184
|
|
|
|
|
185
|
|
|
); |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
/** |
|
189
|
|
|
* Tests the plugin manager base's definition matching. |
|
190
|
|
|
* |
|
191
|
|
|
* @param array $target |
|
192
|
|
|
* The properties to find a matching plugin for. |
|
193
|
|
|
* @param array $mockFilters |
|
|
|
|
|
|
194
|
|
|
* The possible filters for the mocked plugin manager. |
|
195
|
|
|
* @param array $mockCriteria |
|
|
|
|
|
|
196
|
|
|
* The specificity criteria for the mocked plugin manager. |
|
197
|
|
|
* @param array $mockDefinitions |
|
198
|
|
|
* The plugins to be discovered by the mocked plugin manager. |
|
199
|
|
|
* @param array $expectedIds |
|
200
|
|
|
* The ids of the mock definitions that match the target. |
|
201
|
|
|
* |
|
202
|
|
|
* @dataProvider fieldManagerMatchedDefinitionsData |
|
203
|
|
|
*/ |
|
204
|
|
View Code Duplication |
public function testFieldManagerMatchedDefinitions($target, $mockDefinitions, $expectedIds) |
|
|
|
|
|
|
205
|
|
|
{ |
|
206
|
|
|
$mock = \Mockery::mock('Drupal\Driver\Plugin\DriverFieldPluginManager'); |
|
207
|
|
|
$mock->makePartial(); |
|
208
|
|
|
$mock->shouldReceive('getDefinitions')->andReturn($mockDefinitions); |
|
209
|
|
|
$mock->shouldAllowMockingProtectedMethods(); |
|
210
|
|
|
$mock->shouldReceive('getFilterableTarget')->andReturn($target); |
|
211
|
|
|
|
|
212
|
|
|
$matchedDefinitions = $mock->getMatchedDefinitions($target); |
|
|
|
|
|
|
213
|
|
|
$ids = array_column($matchedDefinitions, 'id'); |
|
214
|
|
|
$this->assertEquals($expectedIds, $ids); |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
/** |
|
218
|
|
|
* Data provider for testManagerBaseMatchedDefinitions(). |
|
219
|
|
|
* |
|
220
|
|
|
* @return array |
|
221
|
|
|
* An array of test data. |
|
222
|
|
|
*/ |
|
223
|
|
|
public function fieldManagerMatchedDefinitionsData() |
|
224
|
|
|
{ |
|
225
|
|
|
$mockDefinitions = [ |
|
226
|
|
|
[ |
|
227
|
|
|
'id' => 'A', |
|
228
|
|
|
'weight' => 0, |
|
229
|
|
|
'entityTypes' => ['node'], |
|
230
|
|
|
'fieldTypes' => ['datetime'], |
|
231
|
|
|
'fieldNames' => ['datefield'], |
|
232
|
|
|
], |
|
233
|
|
|
[ |
|
234
|
|
|
'id' => 'B', |
|
235
|
|
|
'weight' => 0, |
|
236
|
|
|
'fieldTypes' => ['datetime'], |
|
237
|
|
|
], |
|
238
|
|
|
[ |
|
239
|
|
|
'id' => 'C', |
|
240
|
|
|
'weight' => 0, |
|
241
|
|
|
'entityTypes' => ['node'], |
|
242
|
|
|
'fieldNames' => ['datefield'], |
|
243
|
|
|
], |
|
244
|
|
|
[ |
|
245
|
|
|
'id' => 'D', |
|
246
|
|
|
'weight' => 0, |
|
247
|
|
|
'entityTypes' => ['node'], |
|
248
|
|
|
], |
|
249
|
|
|
[ |
|
250
|
|
|
'id' => 'E', |
|
251
|
|
|
'weight' => 0, |
|
252
|
|
|
'entityTypes' => ['node'], |
|
253
|
|
|
'entityBundles' => ['article'], |
|
254
|
|
|
'fieldTypes' => ['datetime'], |
|
255
|
|
|
'fieldNames' => ['datefield'], |
|
256
|
|
|
], |
|
257
|
|
|
[ |
|
258
|
|
|
'id' => 'F', |
|
259
|
|
|
'weight' => 0, |
|
260
|
|
|
], |
|
261
|
|
|
]; |
|
262
|
|
|
|
|
263
|
|
|
$reweightedDefinitions = $mockDefinitions; |
|
264
|
|
|
$reweightedDefinitions[0]['weight'] = 10; |
|
265
|
|
|
|
|
266
|
|
|
$capitalisedDefinitions = $mockDefinitions; |
|
267
|
|
|
$capitalisedDefinitions[0]['entityTypes'][0] = 'Node'; |
|
268
|
|
|
$capitalisedDefinitions[0]['fieldTypes'][0] = 'Datetime'; |
|
269
|
|
|
$capitalisedDefinitions[0]['fieldNames'][0] = 'DATEFIELD'; |
|
270
|
|
|
|
|
271
|
|
|
return array( |
|
272
|
|
|
// Test specificity order. |
|
273
|
|
|
[ |
|
274
|
|
|
[ |
|
275
|
|
|
'entityTypes' => 'node', |
|
276
|
|
|
'entityBundles' => 'article', |
|
277
|
|
|
'fieldTypes' => 'datetime', |
|
278
|
|
|
'fieldNames' => 'datefield' |
|
279
|
|
|
], |
|
280
|
|
|
$mockDefinitions, |
|
281
|
|
|
['E','A','C','B','D','F'], |
|
282
|
|
|
], |
|
283
|
|
|
|
|
284
|
|
|
// Test entity type must not conflict. |
|
285
|
|
|
[ |
|
286
|
|
|
[ |
|
287
|
|
|
'entityTypes' => 'user', |
|
288
|
|
|
'entityBundles' => 'article', |
|
289
|
|
|
'fieldTypes' => 'datetime', |
|
290
|
|
|
'fieldNames' => 'datefield' |
|
291
|
|
|
], |
|
292
|
|
|
$mockDefinitions, |
|
293
|
|
|
['B','F'], |
|
294
|
|
|
], |
|
295
|
|
|
|
|
296
|
|
|
// Test entity bundle must not conflict. |
|
297
|
|
|
[ |
|
298
|
|
|
[ |
|
299
|
|
|
'entityTypes' => 'node', |
|
300
|
|
|
'entityBundles' => 'page', |
|
301
|
|
|
'fieldTypes' => 'datetime', |
|
302
|
|
|
'fieldNames' => 'datefield' |
|
303
|
|
|
], |
|
304
|
|
|
$mockDefinitions, |
|
305
|
|
|
['A','C','B','D','F'], |
|
306
|
|
|
], |
|
307
|
|
|
|
|
308
|
|
|
// Test field type must not conflict. |
|
309
|
|
|
[ |
|
310
|
|
|
[ |
|
311
|
|
|
'entityTypes' => 'node', |
|
312
|
|
|
'entityBundles' => 'article', |
|
313
|
|
|
'fieldTypes' => 'string', |
|
314
|
|
|
'fieldNames' => 'datefield' |
|
315
|
|
|
], |
|
316
|
|
|
$mockDefinitions, |
|
317
|
|
|
['C','D','F'], |
|
318
|
|
|
], |
|
319
|
|
|
|
|
320
|
|
|
// Test field name must not conflict. |
|
321
|
|
|
[ |
|
322
|
|
|
[ |
|
323
|
|
|
'entityTypes' => 'node', |
|
324
|
|
|
'entityBundles' => 'page', |
|
325
|
|
|
'fieldTypes' => 'datetime', |
|
326
|
|
|
'fieldNames' => 'otherdatefield' |
|
327
|
|
|
], |
|
328
|
|
|
$mockDefinitions, |
|
329
|
|
|
['B','D','F'], |
|
330
|
|
|
], |
|
331
|
|
|
|
|
332
|
|
|
// Weight trumps specificity. |
|
333
|
|
|
[ |
|
334
|
|
|
[ |
|
335
|
|
|
'entityTypes' => 'node', |
|
336
|
|
|
'entityBundles' => 'article', |
|
337
|
|
|
'fieldTypes' => 'datetime', |
|
338
|
|
|
'fieldNames' => 'datefield' |
|
339
|
|
|
], |
|
340
|
|
|
$reweightedDefinitions, |
|
341
|
|
|
['A','E','C','B','D','F'], |
|
342
|
|
|
], |
|
343
|
|
|
|
|
344
|
|
|
// Test case insensitivity. |
|
345
|
|
|
[ |
|
346
|
|
|
[ |
|
347
|
|
|
'entityTypes' => 'node', |
|
348
|
|
|
'entityBundles' => 'article', |
|
349
|
|
|
'fieldTypes' => 'datetime', |
|
350
|
|
|
'fieldNames' => 'datefield' |
|
351
|
|
|
], |
|
352
|
|
|
$capitalisedDefinitions, |
|
353
|
|
|
['E','A','C','B','D','F'], |
|
354
|
|
|
], |
|
355
|
|
|
|
|
356
|
|
|
); |
|
357
|
|
|
} |
|
358
|
|
|
} |
|
359
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.