Completed
Push — master ( c8702c...a22429 )
by Tobias
09:12
created

SetupTest   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 498
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 33
c 2
b 1
f 0
lcom 2
cbo 1
dl 0
loc 498
rs 9.3999

21 Methods

Rating   Name   Duplication   Size   Complexity  
A testCanConstruct() 0 7 1
A testOnExtensionLoad() 0 5 1
A testCanBuildHookCallbackListFor() 0 15 3
A testCanClear() 0 20 3
B testCanCompileRequestedHooksListFor() 0 31 1
B testCanGetCompleteHookDefinitionList() 0 27 2
A testCanInitializeApplications() 0 20 1
B testHookRegistrationProcess() 0 25 3
A testCanRun() 0 9 1
A testHookGalleryGetModes() 0 19 1
A testHookImageBeforeProduceHTML() 0 8 1
B testHookInternalParseBeforeLinks() 0 36 1
B testHookParserBeforeTidy() 0 29 1
A testHookScribuntoExternalLibraries() 0 23 1
A testHookSetupAfterCache() 0 6 1
A buildHookCallbackListForProvider() 0 10 1
B hookRegistryProvider() 0 24 1
B buildHookListsForCanBuildHookListCheck() 0 15 5
A doTestHookIsRegistered() 0 15 2
A doTestHookIsNotRegistered() 0 7 1
A getCallBackForHook() 0 14 1
1
<?php
2
3
namespace BootstrapComponents\Tests\Unit;
4
5
use BootstrapComponents\Setup as Setup;
6
use \PHPUnit_Framework_TestCase;
7
8
/**
9
 * @covers  \BootstrapComponents\Setup
10
 *
11
 * @ingroup Test
12
 *
13
 * @group   extension-bootstrap-components
14
 * @group   mediawiki-databaseless
15
 *
16
 * @license GNU GPL v3+
17
 *
18
 * @since   1.0
19
 * @author  Tobias Oetterer
20
 */
21
class SetupTest extends PHPUnit_Framework_TestCase {
22
	/**
23
	 * @throws \ConfigException
24
	 * @throws \MWException
25
	 */
26
	public function testCanConstruct() {
27
28
		$this->assertInstanceOf(
29
			'BootstrapComponents\\Setup',
30
			new Setup( [] )
31
		);
32
	}
33
34
	/**
35
	 * @throws \ConfigException cascading {@see \BootstrapComponents\Setup::onExtensionLoad}
36
	 * @throws \MWException
37
	 */
38
	public function testOnExtensionLoad() {
39
		$this->assertTrue(
40
			Setup::onExtensionLoad( [ 'version' => 'test' ] )
41
		);
42
	}
43
44
	/**
45
	 * @param string[] $hookList
46
	 *
47
	 * @throws \ConfigException
48
	 * @throws \MWException
49
	 *
50
	 * @dataProvider buildHookCallbackListForProvider
51
	 */
52
	public function testCanBuildHookCallbackListFor( $hookList ) {
53
54
		$instance = new Setup( [] );
55
56
		/** @noinspection PhpParamsInspection */
57
		$hookCallbackList = $instance->buildHookCallbackListFor( $hookList );
58
		list ( $expectedHookList, $invertedHookList ) = $this->buildHookListsForCanBuildHookListCheck( $hookList );
59
60
		foreach ( $expectedHookList as $hook ) {
61
			$this->doTestHookIsRegistered( $instance, $hookCallbackList, $hook, false );
62
		}
63
		foreach ( $invertedHookList as $hook ) {
64
			$this->doTestHookIsNotRegistered( $hookCallbackList, $hook );
65
		}
66
	}
67
68
	/**
69
	 * @throws \ConfigException
70
	 * @throws \MWException
71
	 */
72
	public function testCanClear() {
73
74
		$instance = new Setup( [] );
75
		$instance->register(
76
			$instance->buildHookCallbackListFor( Setup::AVAILABLE_HOOKS )
77
		);
78
		foreach ( Setup::AVAILABLE_HOOKS as $hook ) {
79
			$this->assertTrue(
80
				$instance->isRegistered( $hook ),
81
				'Hook ' . $hook . ' is not registered!'
82
			);
83
		}
84
		$instance->clear();
85
		foreach ( [ 'GalleryGetModes', 'ImageBeforeProduceHTML' ] as $hook ) {
86
			$this->assertTrue(
87
				!$instance->isRegistered( $hook ),
88
				'Hook ' . $hook . ' is still registered!'
89
			);
90
		}
91
	}
92
93
	/**
94
	 * @param string[] $listOfConfigSettingsSet
95
	 * @param string[] $expectedHookList
96
	 *
97
	 * @throws \ConfigException
98
	 * @throws \MWException
99
	 *
100
	 * @dataProvider hookRegistryProvider
101
	 */
102
	public function testCanCompileRequestedHooksListFor( $listOfConfigSettingsSet, $expectedHookList ) {
103
		$myConfig = $this->getMockBuilder( 'Config' )
104
			->disableOriginalConstructor()
105
			->getMock();
106
		$myConfig->expects( $this->any() )
107
			->method( 'has' )
108
			->will( $this->returnCallback(
109
				function( $configSetting ) use ( $listOfConfigSettingsSet )
110
				{
111
					return in_array( $configSetting, $listOfConfigSettingsSet );
112
				}
113
			) );
114
		$myConfig->expects( $this->any() )
115
			->method( 'get' )
116
			->will( $this->returnCallback(
117
				function( $configSetting ) use ( $listOfConfigSettingsSet )
118
				{
119
					return in_array( $configSetting, $listOfConfigSettingsSet );
120
				}
121
			) );
122
123
		$instance = new Setup( [] );
124
125
		/** @noinspection PhpParamsInspection */
126
		$compiledHookList = $instance->compileRequestedHooksListFor( $myConfig );
127
128
		$this->assertEquals(
129
			$expectedHookList,
130
			$compiledHookList
131
		);
132
	}
133
134
	/**
135
	 * @throws \ConfigException
136
	 * @throws \MWException
137
	 */
138
	public function testCanGetCompleteHookDefinitionList() {
139
140
		$myConfig = $this->getMockBuilder( 'Config' )
141
			->disableOriginalConstructor()
142
			->getMock();
143
		$componentLibrary = $this->getMockBuilder( 'BootstrapComponents\\ComponentLibrary' )
144
			->disableOriginalConstructor()
145
			->getMock();
146
		$nestingController = $this->getMockBuilder( 'BootstrapComponents\\NestingController' )
147
			->disableOriginalConstructor()
148
			->getMock();
149
150
		$instance = new Setup( [] );
151
152
		/** @noinspection PhpParamsInspection */
153
		$completeHookDefinitionList = $instance->getCompleteHookDefinitionList( $myConfig, $componentLibrary, $nestingController );
154
		$this->assertEquals(
155
			Setup::AVAILABLE_HOOKS,
156
			array_keys( $completeHookDefinitionList )
157
		);
158
159
		foreach ( $completeHookDefinitionList as $callback ) {
160
			$this->assertTrue(
161
				is_callable( $callback )
162
			);
163
		}
164
	}
165
166
	/**
167
	 * @throws \ConfigException
168
	 * @throws \MWException
169
	 */
170
	public function testCanInitializeApplications() {
171
172
		$myConfig = $this->getMockBuilder( 'Config' )
173
			->disableOriginalConstructor()
174
			->getMock();
175
176
		$instance = new Setup( [] );
177
178
		/** @noinspection PhpParamsInspection */
179
		list( $componentLibrary, $nestingController ) = $instance->initializeApplications( $myConfig );
180
181
		$this->assertInstanceOf(
182
			'BootstrapComponents\\ComponentLibrary',
183
			$componentLibrary
184
		);
185
		$this->assertInstanceOf(
186
			'BootstrapComponents\\NestingController',
187
			$nestingController
188
		);
189
	}
190
191
	/**
192
	 * @param array $listOfConfigSettingsSet
193
	 * @param array $expectedRegisteredHooks
194
	 * @param array $expectedNotRegisteredHooks
195
	 *
196
	 * @throws \ConfigException cascading {@see \Config::get}
197
	 * @throws \MWException
198
	 *
199
	 * @dataProvider hookRegistryProvider
200
	 */
201
	public function testHookRegistrationProcess( $listOfConfigSettingsSet, $expectedRegisteredHooks, $expectedNotRegisteredHooks ) {
202
203
		$instance = new Setup( [] );
204
205
		$hookCallbackList = $instance->buildHookCallbackListFor(
206
			$expectedRegisteredHooks
207
		);
208
209
		$this->assertTrue(
210
			is_array( $listOfConfigSettingsSet )
211
		);
212
213
		$this->assertEquals(
214
			count( $expectedRegisteredHooks ),
215
			$instance->register( $hookCallbackList )
216
		);
217
218
		foreach ( $expectedRegisteredHooks as $expectedHook ) {
219
			$this->doTestHookIsRegistered( $instance, $hookCallbackList, $expectedHook );
220
		}
221
222
		foreach ( $expectedNotRegisteredHooks as $notExpectedHook ) {
223
			$this->doTestHookIsNotRegistered( $hookCallbackList, $notExpectedHook );
224
		}
225
	}
226
227
	/**
228
	 * @throws \ConfigException cascading {@see \Config::get}
229
	 * @throws \MWException
230
	 */
231
	public function testCanRun() {
232
233
		$instance = new Setup( [] );
234
235
		$this->assertInternalType(
236
			'integer',
237
			$instance->run()
238
		);
239
	}
240
241
	/*
242
	 * Here end the tests for all the public methods.
243
	 * Following one test per hook function and one test for all the parser hook registrations.
244
	 */
245
246
	/**
247
	 * @throws \ConfigException
248
	 * @throws \MWException
249
	 */
250
	public function testHookGalleryGetModes() {
251
252
		$callback = $this->getCallBackForHook( 'GalleryGetModes' );
253
		$modesForTest = [ 'default' => 'TestGallery' ];
254
255
		$callback( $modesForTest );
256
		$this->assertEquals(
257
			2,
258
			count( $modesForTest )
259
		);
260
		$this->assertArrayHasKey(
261
			'carousel',
262
			$modesForTest
263
		);
264
		$this->assertEquals(
265
			'BootstrapComponents\\CarouselGallery',
266
			$modesForTest['carousel']
267
		);
268
	}
269
270
	/**
271
	 * @throws \ConfigException
272
	 * @throws \MWException
273
	 */
274
	public function testHookImageBeforeProduceHTML() {
275
		$callback = $this->getCallBackForHook( 'ImageBeforeProduceHTML' );
276
		$linker = $title = $file = $frameParams = $handlerParams = $time = $res = false;
277
278
		$this->assertTrue(
279
			$callback( $linker, $title, $file, $frameParams, $handlerParams, $time, $res )
280
		);
281
	}
282
283
	/**
284
	 * @throws \ConfigException
285
	 * @throws \MWException
286
	 */
287
	public function testHookInternalParseBeforeLinks() {
288
		$parserOutput = $this->getMockBuilder( 'ParserOutput' )
289
			->disableOriginalConstructor()
290
			->getMock();
291
		$parserOutput->expects( $this->exactly( 2 ) )
292
			->method( 'setExtensionData' )
293
			->with(
294
				$this->stringContains( 'bsc_no_image_modal' ),
295
				$this->isType( 'boolean' )
296
			);
297
		$parser = $this->getMockBuilder( 'Parser' )
298
			->disableOriginalConstructor()
299
			->getMock();
300
		$parser->expects( $this->exactly( 2 ) )
301
			->method( 'getOutput' )
302
			->willReturn( $parserOutput );
303
304
		$callback = $this->getCallBackForHook( 'InternalParseBeforeLinks' );
305
306
		$text = '';
307
		$this->assertTrue(
308
			$callback( $parser, $text )
309
		);
310
		$this->assertEquals(
311
			'',
312
			$text
313
		);
314
		$text = '__NOIMAGEMODAL__';
315
		$this->assertTrue(
316
			$callback( $parser, $text )
317
		);
318
		$this->assertEquals(
319
			'',
320
			$text
321
		);
322
	}
323
324
	/**
325
	 * @throws \ConfigException
326
	 * @throws \MWException
327
	 */
328
	public function testHookParserBeforeTidy() {
329
		$parser = $this->getMockBuilder( 'Parser' )
330
			->disableOriginalConstructor()
331
			->getMock();
332
		$parserOutputHelper = $this->getMockBuilder( 'BootstrapComponents\\ParserOutputHelper' )
333
			->disableOriginalConstructor()
334
			->getMock();
335
		$parserOutputHelper->expects( $this->exactly( 2 ) )
336
			->method( 'getContentForLaterInjection' )
337
			->willReturnOnConsecutiveCalls( '', 'call2' );
338
339
		$callback = $this->getCallBackForHook( 'ParserBeforeTidy' );
340
341
		$text = '';
342
		$this->assertTrue(
343
			$callback( $parser, $text, $parserOutputHelper )
344
		);
345
		$this->assertEquals(
346
			'',
347
			$text
348
		);
349
		$this->assertTrue(
350
			$callback( $parser, $text, $parserOutputHelper )
351
		);
352
		$this->assertEquals(
353
			'call2',
354
			$text
355
		);
356
	}
357
358
	// Note: Hook ParserFirstCallInit is tested in \BootstrapComponents\Tests\Unit\Hooks\ParserFirstCallInitTest
359
360
	/**
361
	 * @throws \ConfigException
362
	 * @throws \MWException
363
	 */
364
	public function testHookScribuntoExternalLibraries() {
365
		$callback = $this->getCallBackForHook( 'ScribuntoExternalLibraries' );
366
367
		$libraries = [];
368
		$this->assertTrue(
369
			$callback( '', $libraries )
370
		);
371
		$this->assertEquals(
372
			[],
373
			$libraries
374
		);
375
		$this->assertTrue(
376
			$callback( 'lua', $libraries )
377
		);
378
		$this->assertArrayHasKey(
379
			'mw.bootstrap',
380
			$libraries
381
		);
382
		$this->assertEquals(
383
			'BootstrapComponents\\LuaLibrary',
384
			$libraries['mw.bootstrap']
385
		);
386
	}
387
388
	/**
389
	 * @throws \ConfigException
390
	 * @throws \MWException
391
	 */
392
	public function testHookSetupAfterCache() {
393
		$callback = $this->getCallBackForHook( 'SetupAfterCache' );
394
		$this->assertTrue(
395
			$callback()
396
		);
397
	}
398
399
	/**
400
	 * @return array
401
	 */
402
	public function buildHookCallbackListForProvider() {
403
		return [
404
			'empty'               => [ [] ],
405
			'default'             => [ [ 'ParserBeforeTidy', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries' ] ],
406
			'alsoImageModal'      => [ [ 'ImageBeforeProduceHTML', 'InternalParseBeforeLinks', 'ParserBeforeTidy', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries' ] ],
407
			'alsoCarouselGallery' => [ [ 'GalleryGetModes', 'ParserBeforeTidy', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries' ] ],
408
			'all'                 => [ [ 'GalleryGetModes', 'ImageBeforeProduceHTML', 'InternalParseBeforeLinks', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries' ] ],
409
			'invalid'             => [ [ 'nonExistingHook', 'PageContentSave' ] ],
410
		];
411
	}
412
413
	/**
414
	 * @return string[]
415
	 */
416
	public function hookRegistryProvider() {
417
		return [
418
			'onlydefault' => [
419
				[],
420
				[ 'ParserBeforeTidy', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries', ],
421
				[ 'GalleryGetModes', 'ImageBeforeProduceHTML', 'InternalParseBeforeLinks', ],
422
			],
423
			'gallery activated' => [
424
				[ 'BootstrapComponentsEnableCarouselGalleryMode' ],
425
				[ 'ParserBeforeTidy', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries', 'GalleryGetModes', ],
426
				[ 'ImageBeforeProduceHTML', 'InternalParseBeforeLinks', ],
427
			],
428
			'image replacement activated' => [
429
				[ 'BootstrapComponentsModalReplaceImageTag' ],
430
				[ 'ParserBeforeTidy', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries', 'ImageBeforeProduceHTML', 'InternalParseBeforeLinks', ],
431
				[ 'GalleryGetModes', ],
432
			],
433
			'both activated' => [
434
				[ 'BootstrapComponentsEnableCarouselGalleryMode', 'BootstrapComponentsModalReplaceImageTag' ],
435
				[ 'ParserBeforeTidy', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries', 'GalleryGetModes', 'ImageBeforeProduceHTML', 'InternalParseBeforeLinks', ],
436
				[],
437
			],
438
		];
439
	}
440
441
	/**
442
	 * @param $hookList
443
	 *
444
	 * @return array $expectedHookList, $invertedHookList
445
	 */
446
	private function buildHookListsForCanBuildHookListCheck( $hookList ) {
447
		$expectedHookList = [];
448
		$invertedHookList = [];
449
		foreach ( $hookList as $hook ) {
450
			if ( in_array( $hook, Setup::AVAILABLE_HOOKS ) ) {
451
				$expectedHookList[] = $hook;
452
			}
453
		}
454
		foreach ( Setup::AVAILABLE_HOOKS as $availableHook ) {
455
			if ( !in_array( $availableHook, $hookList ) ) {
456
				$invertedHookList[] = $availableHook;
457
			}
458
		}
459
		return [ $expectedHookList, $invertedHookList ];
460
	}
461
462
	/**
463
	 * @param Setup  $instance
464
	 * @param array  $registeredHooks
465
	 * @param string $expectedHook
466
	 * @param bool   $hardRegisterTest
467
	 */
468
	private function doTestHookIsRegistered( Setup $instance, $registeredHooks, $expectedHook, $hardRegisterTest = true ) {
469
		if ( $hardRegisterTest ) {
470
			$this->assertTrue(
471
				$instance->isRegistered( $expectedHook )
472
			);
473
		}
474
		$this->assertArrayHasKey(
475
			$expectedHook,
476
			$registeredHooks,
477
			'Expected hook "' . $expectedHook . '" to be registered but was not! '
478
		);
479
		$this->assertTrue(
480
			is_callable( $registeredHooks[$expectedHook] )
481
		);
482
	}
483
484
	/**
485
	 * @param array  $registeredHooks
486
	 * @param string $notExpectedHook
487
	 */
488
	private function doTestHookIsNotRegistered( $registeredHooks, $notExpectedHook ) {
489
		$this->assertArrayNotHasKey(
490
			$notExpectedHook,
491
			$registeredHooks,
492
			'Expected hook "' . $notExpectedHook . '" to not be registered but was! '
493
		);
494
	}
495
496
	/**
497
	 * @param string $hook
498
	 *
499
	 * @throws \ConfigException
500
	 * @throws \MWException
501
	 *
502
	 * @return \Closure
503
	 */
504
	private function getCallBackForHook( $hook ) {
505
		$instance = new Setup( [] );
506
		$hookCallbackList = $instance->buildHookCallbackListFor(
507
			[ $hook ]
508
		);
509
		$this->assertArrayHasKey(
510
			$hook,
511
			$hookCallbackList
512
		);
513
		$this->assertTrue(
514
			is_callable( $hookCallbackList[$hook] )
515
		);
516
		return $hookCallbackList[$hook];
517
	}
518
}
519