Completed
Push — master ( 84cc78...40cd21 )
by Jeroen De
01:50
created

ProcessorTest::testNewFromOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace ParamProcessor\Tests;
4
5
use ParamProcessor\ProcessedParam;
6
use ParamProcessor\ProcessingError;
7
use ParamProcessor\ProcessingResult;
8
use ParamProcessor\Processor;
9
use ParamProcessor\Options;
10
use PHPUnit\Framework\TestCase;
11
12
/**
13
 * @covers \ParamProcessor\Processor
14
 *
15
 * @licence GNU GPL v2+
16
 * @author Jeroen De Dauw < [email protected] >
17
 */
18
class ProcessorTest extends TestCase {
19
20
	public function newFromOptionsProvider() {
21
		$options = [];
22
23
		$option = new Options();
24
25
		$options[] = clone $option;
26
27
		$option->setName( 'foobar' );
28
		$option->setLowercaseNames( false );
29
30
		$options[] = clone $option;
31
32
		return $this->arrayWrap( $options );
33
	}
34
35
	private function arrayWrap( array $elements ) {
36
		return array_map(
37
			function( $element ) {
38
				return [ $element ];
39
			},
40
			$elements
41
		);
42
	}
43
44
	public function testNewFromOptions() {
45
		$this->assertEquals( new Options(), Processor::newFromOptions( new Options() )->getOptions() );
46
	}
47
48
	/**
49
	 * Simple parameter definitions and values that should all pass.
50
	 *
51
	 * @return array
52
	 */
53
	private function getSimpleParams() {
54
		$params = [
55
			'awesome' => 'yes',
56
			'Howmuch ' => '9001',
57
			'FLOAT' => '4.2',
58
			' page' => 'Ohi there!',
59
			' text     ' => 'foo bar baz o_O',
60
		];
61
62
		$definitions = [
63
			'awesome' => [
64
				'type' => 'boolean',
65
			],
66
			'howmuch' => [
67
				'type' => 'integer',
68
			],
69
			'float' => [
70
				'type' => 'float',
71
			],
72
			'page' => [
73
				'type' => 'string',
74
				'hastoexist' => false,
75
			],
76
			'text' => [],
77
		];
78
79
		$options = new Options();
80
81
		$expected = [
82
			'awesome' => true,
83
			'howmuch' => 9001,
84
			'float' => 4.2,
85
			'page' => 'Ohi there!',
86
			'text' => 'foo bar baz o_O',
87
		];
88
89
		return [ $params, $definitions, $options, $expected ];
90
	}
91
92
	/**
93
	 * Simple parameter definitions with defaults and values
94
	 * that are invalid or missing and therefore default.
95
	 *
96
	 * @return array
97
	 */
98
	private function getDefaultingParams() {
99
		$params = [
100
			'awesome' => 'omg!',
101
			'howmuch' => 'omg!',
102
			'float' => 'omg!',
103
			'page' => 42,
104
			'whot?' => 'O_o',
105
			'integerr' => ' 9001 ',
106
		];
107
108
		$definitions = [
109
			'awesome' => [
110
				'type' => 'boolean',
111
				'default' => true,
112
			],
113
			'howmuch' => [
114
				'type' => 'integer',
115
				'default' => 9001,
116
			],
117
			'float' => [
118
				'type' => 'float',
119
				'default' => 4.2,
120
			],
121
			'page' => [
122
				'type' => 'string',
123
				'hastoexist' => false,
124
				'default' => 'Ohi there!',
125
			],
126
			'text' => [
127
				'default' => 'foo bar baz o_O',
128
			],
129
			'integerr' => [
130
				'type' => 'integer',
131
				'default' => 42,
132
			],
133
		];
134
135
		$options = new Options();
136
		$options->setTrimValues( false );
137
138
		$expected = [
139
			'awesome' => true,
140
			'howmuch' => 9001,
141
			'float' => 4.2,
142
			'page' => 'Ohi there!',
143
			'text' => 'foo bar baz o_O',
144
			'integerr' => 42,
145
		];
146
147
		return [ $params, $definitions, $options, $expected ];
148
	}
149
150
	/**
151
	 * Values and definitions in-system parameter handling.
152
	 * Options set to expect non-raw values.
153
	 *
154
	 * @return array
155
	 */
156
	private function getTypedParams() {
157
		$params = [
158
			'awesome' => true,
159
			'howmuch' => '42',
160
			'float' => 4.2,
161
			'page' => 'Ohi there!',
162
			'Text' => 'foo bar baz o_O',
163
			'text1 ' => 'foo bar baz o_O',
164
			' text2' => 'foo bar baz o_O',
165
		];
166
167
		$definitions = [
168
			'awesome' => [
169
				'type' => 'boolean',
170
			],
171
			'howmuch' => [
172
				'type' => 'integer',
173
				'default' => 9001,
174
			],
175
			'float' => [
176
				'type' => 'float',
177
				'lowerbound' => 9001,
178
				'default' => 9000.1
179
			],
180
			'page' => [
181
				'type' => 'string',
182
				'hastoexist' => false,
183
			],
184
			'text' => [
185
				'default' => 'some text',
186
			],
187
			'text1' => [
188
				'default' => 'some text',
189
			],
190
			'text2' => [
191
				'default' => 'some text',
192
			],
193
		];
194
195
		$options = new Options();
196
		$options->setRawStringInputs( false );
197
		$options->setLowercaseNames( false );
198
		$options->setTrimNames( false );
199
200
		$expected = [
201
			'awesome' => true,
202
			'howmuch' => 9001,
203
			'float' => 9000.1,
204
			'page' => 'Ohi there!',
205
			'text' => 'some text',
206
			'text1' => 'some text',
207
			'text2' => 'some text',
208
		];
209
210
		return [ $params, $definitions, $options, $expected ];
211
	}
212
213
	/**
214
	 * Values with capitalization and preceding/tailing spaces to test
215
	 * of the clean options work.
216
	 *
217
	 * @return array
218
	 */
219
	private function getUncleanParams() {
220
		$params = [
221
			'awesome' => ' yes ',
222
			'text' => ' FOO  bar  ',
223
			'integerr' => ' 9001 ',
224
		];
225
226
		$definitions = [
227
			'awesome' => [
228
				'type' => 'boolean',
229
			],
230
			'text' => [
231
				'default' => 'bar',
232
			],
233
			'integerr' => [
234
				'type' => 'integer',
235
				'default' => 42,
236
			],
237
		];
238
239
		$options = new Options();
240
		$options->setLowercaseValues( true );
241
		$options->setTrimValues( true );
242
243
		$expected = [
244
			'awesome' => true,
245
			'text' => 'foo  bar',
246
			'integerr' => 9001,
247
		];
248
249
		return [ $params, $definitions, $options, $expected ];
250
	}
251
252
	/**
253
	 * List parameters to test if list handling works correctly.
254
	 *
255
	 * @return array
256
	 */
257
	private function getListParams() {
258
		$params = [
259
			'awesome' => ' yes, no, on, off ',
260
			'float' => ' 9001 ; 42 ; 4.2;0',
261
		];
262
263
		$definitions = [
264
			'awesome' => [
265
				'type' => 'boolean',
266
				'islist' => true,
267
			],
268
			'text' => [
269
				'default' => [ 'bar' ],
270
				'islist' => true,
271
			],
272
			'float' => [
273
				'type' => 'float',
274
				'islist' => true,
275
				'delimiter' => ';'
276
			],
277
		];
278
279
		$options = new Options();
280
		$options->setLowercaseValues( true );
281
		$options->setTrimValues( true );
282
283
		$expected = [
284
			'awesome' => [ true, false, true, false ],
285
			'text' => [ 'bar' ],
286
			'float' => [ 9001.0, 42.0, 4.2, 0.0 ],
287
		];
288
289
		return [ $params, $definitions, $options, $expected ];
290
	}
291
292
	public function parameterProvider() {
293
		// $params, $definitions [, $options]
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
294
		$argLists = [];
295
296
		$argLists[] = $this->getSimpleParams();
297
298
		$argLists[] = $this->getDefaultingParams();
299
300
		$argLists[] = $this->getTypedParams();
301
302
		$argLists[] = $this->getUncleanParams();
303
304
		$argLists[] = $this->getListParams();
305
306
		foreach ( $argLists as &$argList ) {
307
			foreach ( $argList[1] as $key => &$definition ) {
308
				$definition['message'] = 'test-' . $key;
309
			}
310
311
			if ( !array_key_exists( 2, $argList ) ) {
312
				$argList[2] = new Options();
313
			}
314
		}
315
316
		return $argLists;
317
	}
318
319
	/**
320
	 * @dataProvider parameterProvider
321
	 */
322
	public function testSetParameters( array $params, array $definitions, Options $options ) {
323
		$validator = Processor::newFromOptions( $options );
324
325
		$validator->setParameters( $params, $definitions );
326
327
		$this->assertTrue( true ); // TODO
328
	}
329
330
	/**
331
	 * @dataProvider parameterProvider
332
	 */
333
	public function testValidateParameters( array $params, array $definitions, Options $options, array $expected = [] ) {
334
		$validator = Processor::newFromOptions( $options );
335
336
		$validator->setParameters( $params, $definitions );
337
338
		$processingResult = $validator->processParameters();
339
340
		$actualValues = [];
341
342
		foreach ( $processingResult->getParameters() as $param ) {
343
			$actualValues[$param->getName()] = $param->getValue();
344
		}
345
346
		$this->assertEquals( $expected, $actualValues );
347
348
349
	}
350
351
	public function testProcessParametersOnEmptyOptions() {
352
		$processor = Processor::newDefault();
353
354
		$this->assertInstanceOf(
355
			ProcessingResult::class,
356
			$processor->processParameters()
357
		);
358
	}
359
360
	public function testErrorsCanBeRetrievedAfterProcessing() {
361
		$processor = Processor::newDefault();
362
363
		$this->processWithOneError( $processor );
364
365
		$this->assertCount( 1, $processor->getErrors() );
366
	}
367
368
	private function processWithOneError( Processor $processor ) {
369
		$processor->setParameters(
370
			[],
371
			[
0 ignored issues
show
Documentation introduced by
array('awesome' => array...ge' => 'test-awesome')) is of type array<string,array<strin...ssage\":\"string\"}>"}>, but the function expects a array<integer,object<Par...ssor\IParamDefinition>>.

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...
372
				'awesome' => [
373
					'type' => 'boolean',
374
					'message' => 'test-awesome'
375
				],
376
			]
377
		);
378
379
		// There should be a single "missing required parameter" error.
380
		$processor->processParameters();
381
	}
382
383
	public function testErrorsAreClearedBetweenProcessingRuns() {
384
		$processor = Processor::newDefault();
385
386
		$this->processWithOneError( $processor );
387
		$processor->setParameters( [], [] );
388
		$processor->processParameters();
389
390
		$this->assertEmpty( $processor->getErrors() );
391
	}
392
393
	public function testInvalidListElementsAreOmitted() {
394
		$processor = Processor::newDefault();
395
396
		$processor->setFunctionParams(
397
			[
398
				'some-list=1,2,3, ,4,'
399
			],
400
			[
401
				'some-list' => [
402
					'type' => 'integer',
403
					'message' => 'test',
404
					'islist' => true
405
				],
406
			]
407
		);
408
409
		$this->assertSame(
410
			[ 1, 2, 3, 4 ],
411
			$processor->processParameters()->getParameters()['some-list']->getValue()
412
		);
413
	}
414
415
	public function testListParametersAreNotDefaultedWhenSomeElementsAreInvalid() {
416
		$processor = Processor::newDefault();
417
418
		$processor->setFunctionParams(
419
			[
420
				'some-list=1,nan'
421
			],
422
			[
423
				'some-list' => [
424
					'type' => 'integer',
425
					'message' => 'test',
426
					'islist' => true,
427
					'default' => []
428
				],
429
			]
430
		);
431
432
		$this->assertSame(
433
			[ 1 ],
434
			$processor->processParameters()->getParameters()['some-list']->getValue()
435
		);
436
	}
437
438
	public function testListParametersAreDefaultedWhenAllElementsAreInvalid() {
439
		$processor = Processor::newDefault();
440
441
		$processor->setFunctionParams(
442
			[
443
				'some-list=such,nan'
444
			],
445
			[
446
				'some-list' => [
447
					'type' => 'integer',
448
					'message' => 'test',
449
					'islist' => true,
450
					'default' => [ 42 ]
451
				],
452
			]
453
		);
454
455
		$this->assertSame(
456
			[ 42 ],
457
			$processor->processParameters()->getParameters()['some-list']->getValue()
458
		);
459
	}
460
461
}
462