Passed
Push — master ( 26bdab...a3b78d )
by adam
02:09
created

testRoundingWithDefaultPrecisionWhenFormattingAsFloat()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace Tests\DataValues\Geo\Formatters;
6
7
use DataValues\Geo\Formatters\LatLongFormatter;
8
use DataValues\Geo\Parsers\LatLongParser;
9
use DataValues\Geo\Values\LatLongValue;
10
use DataValues\StringValue;
11
use InvalidArgumentException;
12
use PHPUnit\Framework\TestCase;
13
use ValueFormatters\FormatterOptions;
14
15
/**
16
 * @covers \DataValues\Geo\Formatters\LatLongFormatter
17
 *
18
 * @group ValueFormatters
19
 * @group DataValueExtensions
20
 *
21
 * @license GPL-2.0-or-later
22
 * @author Jeroen De Dauw < [email protected] >
23
 * @author Addshore
24
 * @author Daniel Kinzler
25
 */
26
class LatLongFormatterTest extends TestCase {
27
28
	public function floatNotationProvider() {
29
		return [
30
			'0, degree' => [
31
				new LatLongValue( 0, 0 ),
32
				1,
33
				'0, 0'
34
			],
35
			'negative zero' => [
36
				new LatLongValue( -0.25, 0.25 ),
37
				1,
38
				'0, 0'
39
			],
40
			'signed, minute' => [
41
				new LatLongValue( -55.755786, 37.25633 ),
42
				1 / 60,
43
				'-55.75, 37.25'
44
			],
45
			'signed, degree' => [
46
				new LatLongValue( -55.755786, 37.25633 ),
47
				1,
48
				'-56, 37'
49
			],
50
			'three degrees' => [
51
				new LatLongValue( -55.755786, 37.25633 ),
52
				3,
53
				'-57, 36'
54
			],
55
			'seven degrees' => [
56
				new LatLongValue( -55.755786, 37.25633 ),
57
				7,
58
				'-56, 35'
59
			],
60
			'ten degrees' => [
61
				new LatLongValue( -55.755786, 37.25633 ),
62
				10,
63
				'-60, 40'
64
			],
65
			'rounding degrees down' => [
66
				new LatLongValue( -14.9, 14.9 ),
67
				10,
68
				'-10, 10'
69
			],
70
			'rounding degrees up' => [
71
				new LatLongValue( -15, 15 ),
72
				10,
73
				'-20, 20'
74
			],
75
			'rounding fractions down' => [
76
				new LatLongValue( -0.049, 0.049 ),
77
				0.1,
78
				'0, 0'
79
			],
80
			'rounding fractions up' => [
81
				new LatLongValue( -0.05, 0.05 ),
82
				0.1,
83
				'-0.1, 0.1'
84
			],
85
			'precision option must support strings' => [
86
				new LatLongValue( -0.05, 0.05 ),
87
				'0.1',
88
				'-0.1, 0.1'
89
			],
90
		];
91
	}
92
93
	/**
94
	 * @param string $format One of the LatLongFormatter::TYPE_… constants
95
	 * @param float|int $precision
96
	 *
97
	 * @return FormatterOptions
98
	 */
99
	private function makeOptions( $format, $precision ) {
100
		$options = new FormatterOptions();
101
		$options->setOption( LatLongFormatter::OPT_FORMAT, $format );
102
		$options->setOption( LatLongFormatter::OPT_DIRECTIONAL, false );
103
		$options->setOption( LatLongFormatter::OPT_PRECISION, $precision );
104
105
		return $options;
106
	}
107
108
	/**
109
	 * @dataProvider floatNotationProvider
110
	 */
111
	public function testFloatNotationFormatting( LatLongValue $latLong, $precision, $expected ) {
112
		$options = $this->makeOptions( LatLongFormatter::TYPE_FLOAT, $precision );
113
		$this->assertFormatsCorrectly( $latLong, $options, $expected );
114
	}
115
116
	/**
117
	 * @dataProvider floatNotationProvider
118
	 */
119
	public function testFloatNotationRoundTrip( LatLongValue $value, $precision, $expected ) {
0 ignored issues
show
Unused Code introduced by
The parameter $expected is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
120
		$options = $this->makeOptions( LatLongFormatter::TYPE_FLOAT, $precision );
121
		$this->assertRoundTrip( $value, $options );
122
	}
123
124
	public function decimalDegreeNotationProvider() {
125
		return [
126
			'0, degree' => [
127
				new LatLongValue( 0, 0 ),
128
				1,
129
				'0°, 0°'
130
			],
131
			'negative zero' => [
132
				new LatLongValue( -0.25, 0.25 ),
133
				1,
134
				'0°, 0°'
135
			],
136
			'signed, minute' => [
137
				new LatLongValue( -55.755786, 37.25633 ),
138
				1 / 60,
139
				'-55.75°, 37.25°'
140
			],
141
			'signed, degree' => [
142
				new LatLongValue( -55.755786, 37.25633 ),
143
				1,
144
				'-56°, 37°'
145
			],
146
			'three degrees' => [
147
				new LatLongValue( -55.755786, 37.25633 ),
148
				3,
149
				'-57°, 36°'
150
			],
151
			'seven degrees' => [
152
				new LatLongValue( -55.755786, 37.25633 ),
153
				7,
154
				'-56°, 35°'
155
			],
156
			'ten degrees' => [
157
				new LatLongValue( -55.755786, 37.25633 ),
158
				10,
159
				'-60°, 40°'
160
			],
161
			'rounding degrees down' => [
162
				new LatLongValue( -14.9, 14.9 ),
163
				10,
164
				'-10°, 10°'
165
			],
166
			'rounding degrees up' => [
167
				new LatLongValue( -15, 15 ),
168
				10,
169
				'-20°, 20°'
170
			],
171
			'rounding fractions down' => [
172
				new LatLongValue( -0.049, 0.049 ),
173
				0.1,
174
				'0.0°, 0.0°'
175
			],
176
			'rounding fractions up' => [
177
				new LatLongValue( -0.05, 0.05 ),
178
				0.1,
179
				'-0.1°, 0.1°'
180
			],
181
			'precision option must support strings' => [
182
				new LatLongValue( -0.05, 0.05 ),
183
				'0.1',
184
				'-0.1°, 0.1°'
185
			],
186
		];
187
	}
188
189
	/**
190
	 * @dataProvider decimalDegreeNotationProvider
191
	 */
192
	public function testDecimalDegreeNotationFormatting( LatLongValue $latLong, $precision, $expected ) {
193
		$options = $this->makeOptions( LatLongFormatter::TYPE_DD, $precision );
194
		$this->assertFormatsCorrectly( $latLong, $options, $expected );
195
	}
196
197
	/**
198
	 * @dataProvider decimalDegreeNotationProvider
199
	 */
200
	public function testDecimalDegreeNotationRoundTrip( LatLongValue $latLong, $precision, $expected ) {
0 ignored issues
show
Unused Code introduced by
The parameter $expected is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
201
		$options = $this->makeOptions( LatLongFormatter::TYPE_DD, $precision );
202
		$this->assertRoundTrip( $latLong, $options );
203
	}
204
205
	public function decimalMinuteNotationProvider() {
206
		return [
207
			'0, degree' => [
208
				new LatLongValue( 0, 0 ),
209
				1,
210
				'0°, 0°'
211
			],
212
			'0, minute' => [
213
				new LatLongValue( 0, 0 ),
214
				1 / 60,
215
				'0° 0\', 0° 0\''
216
			],
217
			'0, second' => [
218
				new LatLongValue( 0, 0 ),
219
				1 / 3600,
220
				'0° 0.00\', 0° 0.00\''
221
			],
222
			'negative zero' => [
223
				new LatLongValue( -1 / 128, 1 / 128 ),
224
				1 / 60,
225
				'0° 0\', 0° 0\''
226
			],
227
			'negative, not zero' => [
228
				new LatLongValue( -0.25, 0.25 ),
229
				1 / 60,
230
				'-0° 15\', 0° 15\''
231
			],
232
			'second' => [
233
				new LatLongValue( -55.755786, 37.25633 ),
234
				1 / 3600,
235
				'-55° 45.35\', 37° 15.38\''
236
			],
237
			'minute' => [
238
				new LatLongValue( -55.755786, 37.25633 ),
239
				1 / 60,
240
				'-55° 45\', 37° 15\''
241
			],
242
			'ten minutes' => [
243
				new LatLongValue( -55.755786, 37.25633 ),
244
				10 / 60,
245
				'-55° 50\', 37° 20\''
246
			],
247
			'fifty minutes' => [
248
				new LatLongValue( -55.755786, 37.25633 ),
249
				50 / 60,
250
				'-55° 50\', 37° 30\''
251
			],
252
			'degree' => [
253
				new LatLongValue( -55.755786, 37.25633 ),
254
				1,
255
				'-56°, 37°'
256
			],
257
			'ten degrees' => [
258
				new LatLongValue( -55.755786, 37.25633 ),
259
				10,
260
				'-60°, 40°'
261
			],
262
			'rounding minutes down' => [
263
				new LatLongValue( -14.9 / 60, 14.9 / 60 ),
264
				10 / 60,
265
				'-0° 10\', 0° 10\''
266
			],
267
			'rounding minutes up' => [
268
				new LatLongValue( -15 / 60, 15 / 60 ),
269
				10 / 60,
270
				'-0° 20\', 0° 20\''
271
			],
272
			'rounding fractions down' => [
273
				new LatLongValue( -0.049 / 60, 0.049 / 60 ),
274
				0.1 / 60,
275
				'0° 0.0\', 0° 0.0\''
276
			],
277
			'rounding fractions up' => [
278
				new LatLongValue( -0.05 / 60, 0.05 / 60 ),
279
				0.1 / 60,
280
				'-0° 0.1\', 0° 0.1\''
281
			],
282
			'round to degree when it does not make a difference' => [
283
				new LatLongValue( 1.5, 2.5 ),
284
				1 - 1 / 60,
285
				'2°, 3°'
286
			],
287
			'round to minutes when it starts making a difference' => [
288
				new LatLongValue( 1.5, 2.5 ),
289
				1 - 2 / 60,
290
				'1° 56\', 2° 54\''
291
			],
292
			'precision option must support strings' => [
293
				new LatLongValue( -0.05, 0.05 ),
294
				'0.1',
295
				'-0° 6\', 0° 6\''
296
			],
297
		];
298
	}
299
300
	/**
301
	 * @dataProvider decimalMinuteNotationProvider
302
	 */
303
	public function testDecimalMinuteNotationFormatting( LatLongValue $latLong, $precision, $expected ) {
304
		$options = $this->makeOptions( LatLongFormatter::TYPE_DM, $precision );
305
		$this->assertFormatsCorrectly( $latLong, $options, $expected );
306
	}
307
308
	/**
309
	 * @dataProvider decimalMinuteNotationProvider
310
	 */
311
	public function testDecimalMinuteNotationRoundTrip( LatLongValue $latLong, $precision, $expected ) {
0 ignored issues
show
Unused Code introduced by
The parameter $expected is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
312
		$options = $this->makeOptions( LatLongFormatter::TYPE_DM, $precision );
313
		$this->assertRoundTrip( $latLong, $options );
314
	}
315
316
	public function decimalMinuteSecondNotationProvider() {
317
		return [
318
			'0, degree' => [
319
				new LatLongValue( 0, 0 ),
320
				1,
321
				'0°, 0°'
322
			],
323
			'0, minute' => [
324
				new LatLongValue( 0, 0 ),
325
				1 / 60,
326
				'0° 0\', 0° 0\''
327
			],
328
			'0, second' => [
329
				new LatLongValue( 0, 0 ),
330
				1 / 3600,
331
				'0° 0\' 0", 0° 0\' 0"'
332
			],
333
			'negative zero' => [
334
				new LatLongValue( -1 / 8192, 1 / 8192 ),
335
				1 / 3600,
336
				'0° 0\' 0", 0° 0\' 0"'
337
			],
338
			'negative, not zero' => [
339
				new LatLongValue( -1 / 4096, 1 / 4096 ),
340
				1 / 7200,
341
				'-0° 0\' 1.0", 0° 0\' 1.0"'
342
			],
343
			'second' => [
344
				new LatLongValue( -55.755786, 37.25 ),
345
				1 / 3600,
346
				'-55° 45\' 21", 37° 15\' 0"'
347
			],
348
			'second/100' => [
349
				new LatLongValue( -55.755786, 37.25633 ),
350
				1 / 360000,
351
				'-55° 45\' 20.83", 37° 15\' 22.79"'
352
			],
353
			'ten seconds' => [
354
				new LatLongValue( -55.755786, 37.25633 ),
355
				10 / 3600,
356
				'-55° 45\' 20", 37° 15\' 20"'
357
			],
358
			'fifty seconds' => [
359
				new LatLongValue( -55.755786, 37.25633 ),
360
				50 / 3600,
361
				'-55° 45\' 0", 37° 15\' 0"'
362
			],
363
			'minute' => [
364
				new LatLongValue( -55.755786, 37.25633 ),
365
				1 / 60,
366
				'-55° 45\', 37° 15\''
367
			],
368
			'degree' => [
369
				new LatLongValue( -55.755786, 37.25633 ),
370
				1,
371
				'-56°, 37°'
372
			],
373
			'degree/100, case A' => [
374
				new LatLongValue( 52.01, 10.01 ),
375
				0.01,
376
				'52° 0\' 36", 10° 0\' 36"'
377
			],
378
			'degree/100, case B' => [
379
				new LatLongValue( 52.02, 10.02 ),
380
				0.01,
381
				'52° 1\' 12", 10° 1\' 12"'
382
			],
383
			'degree/1000' => [
384
				new LatLongValue( 52.4, 6.7667 ),
385
				0.001,
386
				'52° 24\' 0", 6° 46\' 1"'
387
			],
388
			'ten degrees' => [
389
				new LatLongValue( -55.755786, 37.25633 ),
390
				10,
391
				'-60°, 40°'
392
			],
393
			'rounding seconds down' => [
394
				new LatLongValue( -14.9 / 3600, 14.9 / 3600 ),
395
				10 / 3600,
396
				'-0° 0\' 10", 0° 0\' 10"'
397
			],
398
			'rounding seconds up' => [
399
				new LatLongValue( -15 / 3600, 15 / 3600 ),
400
				10 / 3600,
401
				'-0° 0\' 20", 0° 0\' 20"'
402
			],
403
			'rounding fractions down' => [
404
				new LatLongValue( -0.049 / 3600, 0.049 / 3600 ),
405
				0.1 / 3600,
406
				'0° 0\' 0.0", 0° 0\' 0.0"'
407
			],
408
			'rounding fractions up' => [
409
				new LatLongValue( -0.05 / 3600, 0.05 / 3600 ),
410
				0.1 / 3600,
411
				'-0° 0\' 0.1", 0° 0\' 0.1"'
412
			],
413
			'round to degree when it does not make a difference' => [
414
				new LatLongValue( 1.5, 2.5 ),
415
				1 - 1 / 60,
416
				'2°, 3°'
417
			],
418
			'round to minutes when it starts making a difference' => [
419
				new LatLongValue( 1.5, 2.5 ),
420
				1 - 2 / 60,
421
				'1° 56\', 2° 54\''
422
			],
423
			'round to minutes when it does not make a difference' => [
424
				new LatLongValue( 1.926, 2.926 ),
425
				1 / 60 - 1 / 3600,
426
				'1° 56\', 2° 56\''
427
			],
428
			'round to seconds when it starts making a difference' => [
429
				new LatLongValue( 1.926, 2.926 ),
430
				1 / 60 - 2 / 3600,
431
				'1° 56\' 0", 2° 55\' 56"'
432
			],
433
			'unexpected rounding to 36°, 36°' => [
434
				new LatLongValue( 36.5867, 37.0458 ),
435
				1.1187604885913,
436
				'37°, 37°'
437
			],
438
			'precision option must support strings' => [
439
				new LatLongValue( -0.05, 0.05 ),
440
				'0.1',
441
				'-0° 6\', 0° 6\''
442
			],
443
			'Bug T150085 with 1 second precision' => [
444
				new LatLongValue( 42.1206, 2.76944 ),
445
				1 / 3600,
446
				'42° 7\' 14", 2° 46\' 10"'
447
			],
448
			'Bug T150085 with 1 minute precision' => [
449
				new LatLongValue( 42.1206, 2.76944 ),
450
				1 / 60,
451
				'42° 7\', 2° 46\''
452
			],
453
			'Bug T150085 with ~0.7 minute precision' => [
454
				new LatLongValue( 42.1206, 2.76944 ),
455
				0.012111004438894,
456
				'42° 7\' 19", 2° 46\' 24"'
457
			],
458
		];
459
	}
460
461
	/**
462
	 * @dataProvider decimalMinuteSecondNotationProvider
463
	 */
464
	public function testDecimalMinuteSecondNotationFormatting( LatLongValue $latLong, $precision, $expected ) {
465
		$options = $this->makeOptions( LatLongFormatter::TYPE_DMS, $precision );
466
		$this->assertFormatsCorrectly( $latLong, $options, $expected );
467
	}
468
469
	/**
470
	 * @dataProvider decimalMinuteSecondNotationProvider
471
	 */
472
	public function testDecimalMinuteSecondNotationRoundTrip( LatLongValue $latLong, $precision, $expected ) {
0 ignored issues
show
Unused Code introduced by
The parameter $expected is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
473
		$options = $this->makeOptions( LatLongFormatter::TYPE_DMS, $precision );
474
		$this->assertRoundTrip( $latLong, $options );
475
	}
476
477
	/**
478
	 * @param LatLongValue $latLong
479
	 * @param FormatterOptions $options
480
	 * @param string $expected
481
	 */
482
	private function assertFormatsCorrectly( LatLongValue $latLong, FormatterOptions $options, $expected ) {
483
		$formatter = new LatLongFormatter( $options );
484
485
		$this->assertSame(
486
			$expected,
487
			$formatter->format( $latLong ),
488
			'format()'
489
		);
490
491
		$precision = (float)$options->getOption( LatLongFormatter::OPT_PRECISION );
492
		$this->assertSame(
493
			$expected,
494
			$formatter->formatLatLongValue( $latLong, $precision ),
495
			'formatLatLongValue()'
496
		);
497
	}
498
499
	private function assertRoundTrip( LatLongValue $value, FormatterOptions $options ) {
500
		$formatter = new LatLongFormatter( $options );
501
		$parser = new LatLongParser();
502
503
		$formatted = $formatter->format( $value );
504
		$parsed = $parser->parse( $formatted );
505
506
		// NOTE: $parsed may be != $coord, because of rounding, so we can't compare directly.
507
		$formattedParsed = $formatter->format( $parsed );
508
509
		$this->assertSame( $formatted, $formattedParsed );
510
	}
511
512
	public function testDirectionalOptionGetsAppliedForDecimalMinutes() {
513
		$coordinates = [
514
			'55° 0\' N, 37° 0\' E' => [ 55, 37 ],
515
			'55° 30\' N, 37° 30\' W' => [ 55.5, -37.5 ],
516
			'55° 30\' S, 37° 30\' E' => [ -55.5, 37.5 ],
517
			'55° 30\' S, 37° 30\' W' => [ -55.5, -37.5 ],
518
			'0° 0\' N, 0° 0\' E' => [ 0, 0 ],
519
		];
520
521
		$this->assertIsDirectionalFormatMap( $coordinates, LatLongFormatter::TYPE_DM );
522
	}
523
524
	/**
525
	 * @param array[] $coordinates
526
	 * @param string $format One of the LatLongFormatter::TYPE_… constants
527
	 */
528
	private function assertIsDirectionalFormatMap( array $coordinates, $format ) {
529
		foreach ( $coordinates as $expected => $arguments ) {
530
			$options = new FormatterOptions();
531
			$options->setOption( LatLongFormatter::OPT_FORMAT, $format );
532
			$options->setOption( LatLongFormatter::OPT_DIRECTIONAL, true );
533
			$options->setOption( LatLongFormatter::OPT_PRECISION, 1 / 60 );
534
535
			$this->assertFormatsCorrectly(
536
				new LatLongValue( $arguments[0], $arguments[1] ),
537
				$options,
538
				$expected
539
			);
540
		}
541
	}
542
543
	public function testDirectionalOptionGetsAppliedForFloats() {
544
		$coordinates = [
545
			'55.75 N, 37.25 W' => [ 55.755786, -37.25633 ],
546
			'55.75 S, 37.25 E' => [ -55.755786, 37.25633 ],
547
			'55 S, 37.25 W' => [ -55, -37.25633 ],
548
			'5.5 N, 37 E' => [ 5.5, 37 ],
549
			'0 N, 0 E' => [ 0, 0 ],
550
		];
551
552
		$this->assertIsDirectionalFormatMap( $coordinates, LatLongFormatter::TYPE_FLOAT );
553
	}
554
555
	private function provideSpacingLevelOptions() {
556
		return [
557
			'none' => [],
558
			'latlong' => [ LatLongFormatter::OPT_SPACE_LATLONG ],
559
			'direction' => [ LatLongFormatter::OPT_SPACE_DIRECTION ],
560
			'coordparts' => [ LatLongFormatter::OPT_SPACE_COORDPARTS ],
561
			'latlong_direction' => [
562
				LatLongFormatter::OPT_SPACE_LATLONG,
563
				LatLongFormatter::OPT_SPACE_DIRECTION
564
			],
565
			'all' => [
566
				LatLongFormatter::OPT_SPACE_LATLONG,
567
				LatLongFormatter::OPT_SPACE_DIRECTION,
568
				LatLongFormatter::OPT_SPACE_COORDPARTS,
569
			],
570
		];
571
	}
572
573
	public function testSpacingOptionGetsAppliedForDecimalMinutes() {
574
		$coordinates = [
575
			'none' => [
576
				'55°0\'N,37°0\'E' => [ 55, 37 ],
577
				'55°30\'N,37°30\'W' => [ 55.5, -37.5 ],
578
				'0°0\'N,0°0\'E' => [ 0, 0 ],
579
			],
580
			'latlong' => [
581
				'55°0\'N, 37°0\'E' => [ 55, 37 ],
582
				'55°30\'N, 37°30\'W' => [ 55.5, -37.5 ],
583
				'0°0\'N, 0°0\'E' => [ 0, 0 ],
584
			],
585
			'direction' => [
586
				'55°0\' N,37°0\' E' => [ 55, 37 ],
587
				'55°30\' N,37°30\' W' => [ 55.5, -37.5 ],
588
				'0°0\' N,0°0\' E' => [ 0, 0 ],
589
			],
590
			'coordparts' => [
591
				'55° 0\'N,37° 0\'E' => [ 55, 37 ],
592
				'55° 30\'N,37° 30\'W' => [ 55.5, -37.5 ],
593
				'0° 0\'N,0° 0\'E' => [ 0, 0 ],
594
			],
595
			'latlong_direction' => [
596
				'55°0\' N, 37°0\' E' => [ 55, 37 ],
597
				'55°30\' N, 37°30\' W' => [ 55.5, -37.5 ],
598
				'0°0\' N, 0°0\' E' => [ 0, 0 ],
599
			],
600
		];
601
602
		$this->assertSpacingCorrect( $coordinates, LatLongFormatter::TYPE_DM );
603
	}
604
605
	/**
606
	 * @param array[] $coordSets
607
	 * @param string $format One of the LatLongFormatter::TYPE_… constants
608
	 */
609
	private function assertSpacingCorrect( array $coordSets, $format ) {
610
		$spacingLevelOptions = $this->provideSpacingLevelOptions();
611
		foreach ( $coordSets as $spacingKey => $coordinates ) {
612
			foreach ( $coordinates as $expected => $arguments ) {
613
				$options = new FormatterOptions();
614
				$options->setOption( LatLongFormatter::OPT_FORMAT, $format );
615
				$options->setOption( LatLongFormatter::OPT_DIRECTIONAL, true );
616
				$options->setOption( LatLongFormatter::OPT_PRECISION, 1 / 60 );
617
				$options->setOption( LatLongFormatter::OPT_SPACING_LEVEL, $spacingLevelOptions[$spacingKey] );
618
619
				$this->assertFormatsCorrectly(
620
					new LatLongValue( $arguments[0], $arguments[1] ),
621
					$options,
622
					$expected
623
				);
624
			}
625
		}
626
	}
627
628
	public function testSpacingOptionGetsAppliedForFloats() {
629
		$coordinates = [
630
			'none' => [
631
				'55.75N,37.25W' => [ 55.755786, -37.25633 ],
632
				'0N,0E' => [ 0, 0 ],
633
			],
634
			'latlong' => [
635
				'55.75N, 37.25W' => [ 55.755786, -37.25633 ],
636
				'0N, 0E' => [ 0, 0 ],
637
			],
638
			'direction' => [
639
				'55.75 N,37.25 W' => [ 55.755786, -37.25633 ],
640
				'0 N,0 E' => [ 0, 0 ],
641
			],
642
			'coordparts' => [
643
				'55.75N,37.25W' => [ 55.755786, -37.25633 ],
644
				'0N,0E' => [ 0, 0 ],
645
			],
646
			'latlong_direction' => [
647
				'55.75 N, 37.25 W' => [ 55.755786, -37.25633 ],
648
				'0 N, 0 E' => [ 0, 0 ],
649
			],
650
			'all' => [
651
				'55.75 N, 37.25 W' => [ 55.755786, -37.25633 ],
652
				'0 N, 0 E' => [ 0, 0 ],
653
			],
654
		];
655
656
		$this->assertSpacingCorrect( $coordinates, LatLongFormatter::TYPE_FLOAT );
657
	}
658
659
	public function testWrongType() {
660
		$formatter = new LatLongFormatter( new FormatterOptions() );
661
662
		$this->expectException( InvalidArgumentException::class );
663
		$formatter->format( new StringValue( 'Evil' ) );
0 ignored issues
show
Documentation introduced by
new \DataValues\StringValue('Evil') is of type object<DataValues\StringValue>, but the function expects a object<DataValues\Geo\Values\LatLongValue>.

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...
664
	}
665
666
	public function testGivenInvalidFormattingOption_formatThrowsException() {
667
		$options = new FormatterOptions();
668
		$options->setOption( LatLongFormatter::OPT_FORMAT, 'not a format' );
669
		$formatter = new LatLongFormatter( $options );
670
671
		$this->expectException( InvalidArgumentException::class );
672
		$formatter->format( new LatLongValue( 0, 0 ) );
673
	}
674
675
	/**
676
	 * @dataProvider invalidPrecisionProvider
677
	 */
678
	public function testFormatWithInvalidPrecision_fallsBackToDefaultPrecision( $precision ) {
679
		$options = new FormatterOptions();
680
		$options->setOption( LatLongFormatter::OPT_PRECISION, $precision );
681
		$formatter = new LatLongFormatter( $options );
682
683
		$formatted = $formatter->format( new LatLongValue( 1.2, 3.4 ) );
684
		$this->assertSame( '1.2, 3.4', $formatted );
685
	}
686
687
	/**
688
	 * @dataProvider invalidPrecisionProvider
689
	 */
690
	public function testFormatLatLongValueWithInvalidPrecision_fallsBackToDefaultPrecision( $precision ) {
691
		$formatter = new LatLongFormatter( new FormatterOptions() );
692
693
		$formatted = $formatter->formatLatLongValue( new LatLongValue( 1.2, 3.4 ), $precision );
694
		$this->assertSame( '1.2, 3.4', $formatted );
695
	}
696
697
	public function invalidPrecisionProvider() {
698
		return [
699
			[ 0 ],
700
			[ -1 ],
701
			[ NAN ],
702
			[ INF ],
703
		];
704
	}
705
706
	public function testRoundingWithDefaultPrecisionWhenFormattingAsFloat() {
707
		$this->assertSame(
708
			'52.144444444444, -0.46666666666667',
709
			( new LatLongFormatter() )->format( new LatLongValue( 52.1445,-0.466722 ) )
710
		);
711
	}
712
713
	public function testRoundingWithDefaultPrecisionWhenFormattingAsDecimalDegrees() {
714
		$this->assertSame(
715
			'52.1361°, -0.4219°',
716
			$this->newDecimalDegreeFormatter()->format( new LatLongValue( 52.136,-0.422 ) )
717
		);
718
	}
719
720
	private function newDecimalDegreeFormatter() {
721
		return ( new LatLongFormatter( new FormatterOptions( [
722
			LatLongFormatter::OPT_FORMAT => LatLongFormatter::TYPE_DD
723
		] ) ) );
724
	}
725
726
}
727