Passed
Push — master ( 4855a9...e58eff )
by Jeroen De
55s queued 10s
created

testCanParseSuccessiveValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
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\Parsers;
6
7
use DataValues\DataValue;
8
use DataValues\Geo\Parsers\GlobeCoordinateParser;
9
use DataValues\Geo\Values\GlobeCoordinateValue;
10
use DataValues\Geo\Values\LatLongValue;
11
use PHPUnit\Framework\TestCase;
12
use ValueParsers\ParseException;
13
use ValueParsers\ParserOptions;
14
15
/**
16
 * @covers \DataValues\Geo\Parsers\GlobeCoordinateParser
17
 * @covers \DataValues\Geo\PackagePrivate\LatLongPrecisionParser
18
 * @covers \DataValues\Geo\PackagePrivate\PreciseLatLong
19
 * @covers \DataValues\Geo\PackagePrivate\PrecisionParser
20
 *
21
 * @group ValueParsers
22
 * @group DataValueExtensions
23
 *
24
 * @license GPL-2.0-or-later
25
 * @author Jeroen De Dauw < [email protected] >
26
 * @author Thiemo Kreuz
27
 */
28
class GlobeCoordinateParserTest extends TestCase {
29
30
	/**
31
	 * @dataProvider invalidInputProvider
32
	 */
33
	public function testParseWithInvalidInputs( $value ) {
34
		$this->expectException( ParseException::class );
35
		( new GlobeCoordinateParser() )->parse( $value );
36
	}
37
38
	public function invalidInputProvider() {
39
		return [
40
			[ '~=[,,_,,]:3' ],
41
			[ 'ohi there' ],
42
		];
43
	}
44
45
	/**
46
	 * @dataProvider validInputProvider
47
	 */
48
	public function testParseWithValidInputs( $value, DataValue $expected ) {
49
		$actual = ( new GlobeCoordinateParser() )->parse( $value );
50
		$msg = json_encode( $actual->toArray() ) . " should equal\n"
51
			. json_encode( $expected->toArray() );
52
		$this->assertTrue( $expected->equals( $actual ), $msg );
53
	}
54
55
	public function validInputProvider() {
56
		$argLists = [];
57
58
		$valid = [
59
			// Whitespace
60
			"1N 1E\n" => [ 1, 1, 1 ],
61
			' 1N 1E ' => [ 1, 1, 1 ],
62
63
			// Float
64
			'55.7557860 N, 37.6176330 W' => [ 55.7557860, -37.6176330, 0.000001 ],
65
			'55.7557860N,37.6176330W' => [ 55.7557860, -37.6176330, 0.000001 ],
66
			'55.7557860, -37.6176330' => [ 55.7557860, -37.6176330, 0.000001 ],
67
			'55.7557860, -37.6176330    ' => [ 55.7557860, -37.6176330, 0.000001 ],
68
			'55 S, 37.6176330 W' => [ -55, -37.6176330, 0.000001 ],
69
			'55 S,37.6176330W' => [ -55, -37.6176330, 0.000001 ],
70
			'-55, -37.6176330' => [ -55, -37.6176330, 0.000001 ],
71
			'5.5S,37W ' => [ -5.5, -37, 0.1 ],
72
			'-5.5,-37 ' => [ -5.5, -37, 0.1 ],
73
			'-5.5 -37 ' => [ -5.5, -37, 0.1 ],
74
			'4,2' => [ 4, 2, 1 ],
75
			'5.5S 37W ' => [ -5.5, -37, 0.1 ],
76
			'5.5 S 37 W ' => [ -5.5, -37, 0.1 ],
77
			'4 2' => [ 4, 2, 1 ],
78
			'S5.5 W37 ' => [ -5.5, -37, 0.1 ],
79
80
			// DD
81
			'55.7557860° N, 37.6176330° W' => [ 55.7557860, -37.6176330, 0.000001 ],
82
			'55.7557860°, -37.6176330°' => [ 55.7557860, -37.6176330, 0.000001 ],
83
			'55.7557860°,-37.6176330°' => [ 55.7557860, -37.6176330, 0.000001 ],
84
			'55.7557860°,-37.6176330°  ' => [ 55.7557860, -37.6176330, 0.000001 ],
85
			'55° S, 37.6176330 ° W' => [ -55, -37.6176330, 0.000001 ],
86
			'-55°, -37.6176330 °' => [ -55, -37.6176330, 0.000001 ],
87
			'5.5°S,37°W ' => [ -5.5, -37, 0.1 ],
88
			'5.5° S,37° W ' => [ -5.5, -37, 0.1 ],
89
			'-5.5°,-37° ' => [ -5.5, -37, 0.1 ],
90
			'-55° -37.6176330 °' => [ -55, -37.6176330, 0.000001 ],
91
			'5.5°S 37°W ' => [ -5.5, -37, 0.1 ],
92
			'-5.5 ° -37 ° ' => [ -5.5, -37, 0.1 ],
93
			'S5.5° W37°' => [ -5.5, -37, 0.1 ],
94
			' S 5.5° W 37°' => [ -5.5, -37, 0.1 ],
95
96
			// DMS
97
			'55° 45\' 20.8296", 37° 37\' 3.4788"' => [ 55.755786, 37.617633, 0.0001 / 3600 ],
98
			'55° 45\' 20.8296", -37° 37\' 3.4788"' => [ 55.755786, -37.617633, 0.0001 / 3600 ],
99
			'-55° 45\' 20.8296", -37° 37\' 3.4788"' => [ -55.755786, -37.617633, 0.0001 / 3600 ],
100
			'-55° 45\' 20.8296", 37° 37\' 3.4788"' => [ -55.755786, 37.617633, 0.0001 / 3600 ],
101
			'-55° 45\' 20.8296", 37° 37\' 3.4788"  ' => [ -55.755786, 37.617633, 0.0001 / 3600 ],
102
			'55° 0\' 0", 37° 0\' 0"' => [ 55, 37, 1 / 3600 ],
103
			'55° 30\' 0", 37° 30\' 0"' => [ 55.5, 37.5, 1 / 3600 ],
104
			'55° 0\' 18", 37° 0\' 18"' => [ 55.005, 37.005, 1 / 3600 ],
105
			'  55° 0\' 18", 37° 0\' 18"' => [ 55.005, 37.005, 1 / 3600 ],
106
			'0° 0\' 0", 0° 0\' 0"' => [ 0, 0, 1 / 3600 ],
107
			'0° 0\' 18" N, 0° 0\' 18" E' => [ 0.005, 0.005, 1 / 3600 ],
108
			' 0° 0\' 18" S  , 0°  0\' 18"  W ' => [ -0.005, -0.005, 1 / 3600 ],
109
			'0° 0′ 18″ N, 0° 0′ 18″ E' => [ 0.005, 0.005, 1 / 3600 ],
110
			'0° 0\' 18" N  0° 0\' 18" E' => [ 0.005, 0.005, 1 / 3600 ],
111
			' 0 ° 0 \' 18 " S   0 °  0 \' 18 "  W ' => [ -0.005, -0.005, 1 / 3600 ],
112
			'0° 0′ 18″ N 0° 0′ 18″ E' => [ 0.005, 0.005, 1 / 3600 ],
113
			'N 0° 0\' 18" E 0° 0\' 18"' => [ 0.005, 0.005, 1 / 3600 ],
114
			'N0°0\'18"E0°0\'18"' => [ 0.005, 0.005, 1 / 3600 ],
115
			'N0°0\'18" E0°0\'18"' => [ 0.005, 0.005, 1 / 3600 ],
116
117
			// DM
118
			'55° 0\', 37° 0\'' => [ 55, 37, 1 / 60 ],
119
			'55° 30\', 37° 30\'' => [ 55.5, 37.5, 1 / 60 ],
120
			'0° 0\', 0° 0\'' => [ 0, 0, 1 / 60 ],
121
			'   0° 0\', 0° 0\'' => [ 0, 0, 1 / 60 ],
122
			'   0° 0\', 0° 0\'  ' => [ 0, 0, 1 / 60 ],
123
			'-55° 30\', -37° 30\'' => [ -55.5, -37.5, 1 / 60 ],
124
			'0° 0.3\' S, 0° 0.3\' W' => [ -0.005, -0.005, 1 / 3600 ],
125
			'-55° 30′, -37° 30′' => [ -55.5, -37.5, 1 / 60 ],
126
			'-55 ° 30 \' -37 ° 30 \'' => [ -55.5, -37.5, 1 / 60 ],
127
			'0° 0.3\' S 0° 0.3\' W' => [ -0.005, -0.005, 1 / 3600 ],
128
			'-55° 30′ -37° 30′' => [ -55.5, -37.5, 1 / 60 ],
129
			'S 0° 0.3\' W 0° 0.3\'' => [ -0.005, -0.005, 1 / 3600 ],
130
			'S0°0.3\'W0°0.3\'' => [ -0.005, -0.005, 1 / 3600 ],
131
			'S0°0.3\' W0°0.3\'' => [ -0.005, -0.005, 1 / 3600 ],
132
		];
133
134
		foreach ( $valid as $value => $expected ) {
135
			$expected = new GlobeCoordinateValue( new LatLongValue( $expected[0], $expected[1] ), $expected[2] );
136
			$argLists[] = [ (string)$value, $expected ];
137
		}
138
139
		return $argLists;
140
	}
141
142
	public function testWithGlobeOptionMatchingTheDefault() {
143
		$parser = new GlobeCoordinateParser( new ParserOptions( [
144
			'globe' => 'http://www.wikidata.org/entity/Q2'
145
		] ) );
146
147
		$this->assertEquals(
148
			new GlobeCoordinateValue(
149
				new LatLongValue( 55.7557860, -37.6176330 ),
150
				0.000001,
151
				'http://www.wikidata.org/entity/Q2'
152
			),
153
			$parser->parse( '55.7557860° N, 37.6176330° W' )
154
		);
155
	}
156
157
	public function testWithGlobeOptionDifferingFromTheDefault() {
158
		$parser = new GlobeCoordinateParser( new ParserOptions( [
159
			'globe' => 'http://www.wikidata.org/entity/Q111'
160
		] ) );
161
162
		$this->assertEquals(
163
			new GlobeCoordinateValue(
164
				new LatLongValue( 60.5, 260 ),
165
				0.1,
166
				'http://www.wikidata.org/entity/Q111'
167
			),
168
			$parser->parse( '60.5, 260' )
169
		);
170
	}
171
172
	public function testWithoutGlobeOption() {
173
		$parser = new GlobeCoordinateParser();
174
175
		$this->assertEquals(
176
			new GlobeCoordinateValue(
177
				new LatLongValue( 40.2, 22.5 ),
178
				0.1,
179
				'http://www.wikidata.org/entity/Q2'
180
			),
181
			$parser->parse( '40.2, 22.5' )
182
		);
183
	}
184
185
	/**
186
	 * @dataProvider precisionDetectionProvider
187
	 */
188
	public function testPrecisionDetection( $value, $expected ) {
189
		$parser = new GlobeCoordinateParser();
190
		$globeCoordinateValue = $parser->parse( $value );
191
192
		$this->assertSame( (float)$expected, $globeCoordinateValue->getPrecision() );
193
	}
194
195
	public function precisionDetectionProvider() {
196
		return [
197
			// Float
198
			[ '10 20', 1 ],
199
			[ '1 2', 1 ],
200
			[ '1.3 2.4', 0.1 ],
201
			[ '1.3 20', 0.1 ],
202
			[ '10 2.4', 0.1 ],
203
			[ '1.35 2.46', 0.01 ],
204
			[ '1.357 2.468', 0.001 ],
205
			[ '1.3579 2.468', 0.0001 ],
206
			[ '1.00001 2.00001', 0.00001 ],
207
			[ '1.000001 2.000001', 0.000001 ],
208
			[ '1.0000001 2.0000001', 0.0000001 ],
209
			[ '1.00000001 2.00000001', 0.00000001 ],
210
			[ '1.000000001 2.000000001', 1 ],
211
			[ '1.555555555 2.555555555', 0.00000001 ],
212
213
			// Dd
214
			[ '10° 20°', 1 ],
215
			[ '1° 2°', 1 ],
216
			[ '1.3° 2.4°', 0.1 ],
217
			[ '1.3° 20°', 0.1 ],
218
			[ '10° 2.4°', 0.1 ],
219
			[ '1.35° 2.46°', 0.01 ],
220
			[ '1.357° 2.468°', 0.001 ],
221
			[ '1.3579° 2.468°', 0.0001 ],
222
			[ '1.00001° 2.00001°', 0.00001 ],
223
			[ '1.000001° 2.000001°', 0.000001 ],
224
			[ '1.0000001° 2.0000001°', 0.0000001 ],
225
			[ '1.00000001° 2.00000001°', 0.00000001 ],
226
			[ '1.000000001° 2.000000001°', 1 ],
227
			[ '1.555555555° 2.555555555°', 0.00000001 ],
228
229
			// Dm
230
			[ '1°3\' 2°4\'', 1 / 60 ],
231
			[ '1°3\' 2°0\'', 1 / 60 ],
232
			[ '1°0\' 2°4\'', 1 / 60 ],
233
			[ '1°3.5\' 2°4.6\'', 1 / 3600 ],
234
			[ '1°3.57\' 2°4.68\'', 1 / 36000 ],
235
			[ '1°3.579\' 2°4.68\'', 1 / 360000 ],
236
			[ '1°3.0001\' 2°4.0001\'', 1 / 3600000 ],
237
			[ '1°3.00001\' 2°4.00001\'', 1 / 36000000 ],
238
			[ '1°3.000001\' 2°4.000001\'', 1 / 36000000 ],
239
			[ '1°3.0000001\' 2°4.0000001\'', 1 / 60 ],
240
			[ '1°3.5555555\' 2°4.5555555\'', 1 / 36000000 ],
241
242
			// Dms
243
			[ '1°3\'5" 2°4\'6"', 1 / 3600 ],
244
			[ '1°3\'5" 2°0\'0"', 1 / 3600 ],
245
			[ '1°0\'0" 2°4\'6"', 1 / 3600 ],
246
			[ '1°3\'0" 2°4\'0"', 1 / 3600 ],
247
			[ '1°3\'5.7" 2°4\'6.8"', 1 / 36000 ],
248
			[ '1°3\'5.79" 2°4\'6.8"', 1 / 360000 ],
249
			[ '1°3\'5.001" 2°4\'6.001"', 1 / 3600000 ],
250
			[ '1°3\'5.0001" 2°4\'6.0001"', 1 / 36000000 ],
251
			[ '1°3\'5.00001" 2°4\'6.00001"', 1 / 3600 ],
252
			[ '1°3\'5.55555" 2°4\'6.55555"', 1 / 36000000 ],
253
254
			/**
255
			 * @fixme What do the users expect in this case, 1/3600 or 1/360000?
256
			 * @see https://bugzilla.wikimedia.org/show_bug.cgi?id=64820
257
			 */
258
			[ '47°42\'0.00"N, 15°27\'0.00"E', 1 / 3600 ],
259
		];
260
	}
261
262
	public function testCanParseSuccessiveValues() {
263
		$parser = new GlobeCoordinateParser();
264
265
		$this->assertEquals(
266
			$parser->parse( 'S5.5 W37' ),
267
			$parser->parse( 'S5.5 W37' )
268
		);
269
270
		$this->assertEquals(
271
			$parser->parse( '55° 0\' 0", 37° 0\' 0"' ),
272
			$parser->parse( '55° 0\' 0", 37° 0\' 0"' )
273
		);
274
	}
275
276
}
277