QuantityFormatterTest   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 8
dl 0
loc 219
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 5 2
A getInstance() 0 3 1
A getQuantityFormatter() 0 18 2
B validProvider() 0 163 1
A testFormatWithFormatString() 0 6 1
1
<?php
2
3
namespace ValueFormatters\Test;
4
5
use DataValues\QuantityValue;
6
use DataValues\UnboundedQuantityValue;
7
use PHPUnit\Framework\TestCase;
8
use ValueFormatters\DecimalFormatter;
9
use ValueFormatters\FormatterOptions;
10
use ValueFormatters\QuantityFormatter;
11
use ValueFormatters\ValueFormatter;
12
13
/**
14
 * @covers \ValueFormatters\QuantityFormatter
15
 *
16
 * @group ValueFormatters
17
 * @group DataValueExtensions
18
 *
19
 * @license GPL-2.0-or-later
20
 * @author Daniel Kinzler
21
 */
22
class QuantityFormatterTest extends TestCase {
23
24
	public function setUp() : void {
25
		if ( !\extension_loaded( 'bcmath' ) ) {
26
			$this->markTestSkipped( 'bcmath extension not loaded' );
27
		}
28
	}
29
30
	/**
31
	 * @see ValueFormatterTestBase::getInstance
32
	 *
33
	 * @param FormatterOptions|null $options
34
	 *
35
	 * @return QuantityFormatter
36
	 */
37
	protected function getInstance( FormatterOptions $options = null ) {
38
		return $this->getQuantityFormatter( $options );
39
	}
40
41
	/**
42
	 * @param FormatterOptions|null $options
43
	 * @param string|null $quantityWithUnitFormat
44
	 *
45
	 * @return QuantityFormatter
46
	 */
47
	private function getQuantityFormatter(
48
		FormatterOptions $options = null,
49
		$quantityWithUnitFormat = null
50
	) {
51
		$vocabularyUriFormatter = $this->createMock( ValueFormatter::class );
52
		$vocabularyUriFormatter->expects( $this->any() )
53
			->method( 'format' )
54
			->will( $this->returnCallback( function ( $unit ) {
55
				return $unit === '1' ? null : $unit;
56
			} ) );
57
58
		return new QuantityFormatter(
59
			$options,
60
			new DecimalFormatter( $options ),
61
			$vocabularyUriFormatter,
0 ignored issues
show
Documentation introduced by
$vocabularyUriFormatter is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<ValueFormatters\ValueFormatter>.

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...
62
			$quantityWithUnitFormat
63
		);
64
	}
65
66
	/**
67
	 * @see ValueFormatterTestBase::validProvider
68
	 */
69
	public function validProvider() {
70
		$noMargin = new FormatterOptions( [
71
			QuantityFormatter::OPT_SHOW_UNCERTAINTY_MARGIN => false
72
		] );
73
74
		$withMargin = new FormatterOptions( [
75
			QuantityFormatter::OPT_SHOW_UNCERTAINTY_MARGIN => true
76
		] );
77
78
		$noRounding = new FormatterOptions( [
79
			QuantityFormatter::OPT_SHOW_UNCERTAINTY_MARGIN => true,
80
			QuantityFormatter::OPT_APPLY_ROUNDING => false
81
		] );
82
83
		$exactRounding = new FormatterOptions( [
84
			QuantityFormatter::OPT_SHOW_UNCERTAINTY_MARGIN => false,
85
			QuantityFormatter::OPT_APPLY_ROUNDING => -2
86
		] );
87
88
		$forceSign = new FormatterOptions( [
89
			QuantityFormatter::OPT_SHOW_UNCERTAINTY_MARGIN => false,
90
			DecimalFormatter::OPT_FORCE_SIGN => true,
91
		] );
92
93
		$noUnit = new FormatterOptions( [
94
			QuantityFormatter::OPT_APPLY_UNIT => false,
95
		] );
96
97
		return [
98
			'+0/nm' => [ QuantityValue::newFromNumber( '+0', '1', '+0', '+0' ), '0', $noMargin ],
99
			'+0/wm' => [ QuantityValue::newFromNumber( '+0', '1', '+0', '+0' ), '0±0', $withMargin ],
100
101
			'+0.0/nm' => [ QuantityValue::newFromNumber( '+0.0', '°', '+0.1', '-0.1' ), '0.0 °', $noMargin ],
102
			'+0.0/wm' => [ QuantityValue::newFromNumber( '+0.0', '°', '+0.1', '-0.1' ), '0±0.1 °', $withMargin ],
103
			'+0.0/xr' => [ QuantityValue::newFromNumber( '+0.0', '°', '+0.1', '-0.1' ), '0.0 °', $exactRounding ],
104
105
			'-1205/nm' => [ QuantityValue::newFromNumber( '-1205', 'm', '-1105', '-1305' ), '-1200 m', $noMargin ],
106
			'-1205/wm' => [
107
				QuantityValue::newFromNumber( '-1205', 'm', '-1105', '-1305' ),
108
				'-1205±100 m',
109
				$withMargin
110
			],
111
			'-1205/nr' => [
112
				QuantityValue::newFromNumber( '-1205', 'm', '-1105', '-1305' ),
113
				'-1205±100 m',
114
				$noRounding
115
			],
116
			'-1205/xr' => [
117
				QuantityValue::newFromNumber( '-1205', 'm', '-1105', '-1305' ),
118
				'-1205 m',
119
				$exactRounding
120
			],
121
			'-1205/nu' => [ QuantityValue::newFromNumber( '-1205', 'm', '-1105', '-1305' ), '-1205±100', $noUnit ],
122
123
			'+3.025/nm' => [ QuantityValue::newFromNumber( '+3.025', '1', '+3.02744', '+3.0211' ), '3.025', $noMargin ],
124
			'+3.025/wm' => [
125
				QuantityValue::newFromNumber( '+3.025', '1', '+3.02744', '+3.0211' ),
126
				'3.025±0.0039',
127
				$withMargin
128
			],
129
			'+3.025/xr' => [
130
				QuantityValue::newFromNumber( '+3.025', '1', '+3.02744', '+3.0211' ),
131
				'3.03',
132
				$exactRounding
133
			],
134
			'+3.125/nr' => [
135
				QuantityValue::newFromNumber( '+3.125', '1', '+3.2', '+3.0' ),
136
				'3.125±0.125',
137
				$noRounding
138
			],
139
			'+3.125/xr' => [ QuantityValue::newFromNumber( '+3.125', '1', '+3.2', '+3.0' ), '3.13', $exactRounding ],
140
141
			'+3.125/fs' => [ QuantityValue::newFromNumber( '+3.125', '1', '+3.2', '+3.0' ), '+3.13', $forceSign ],
142
143
			// Unbounded quantities with different options
144
			'UB: +0.0/nm' => [ UnboundedQuantityValue::newFromNumber( '+0.0', '°' ), '0.0 °', $noMargin ],
145
			'UB: +0.0/wm' => [ UnboundedQuantityValue::newFromNumber( '+0.0', '°' ), '0.0 °', $withMargin ],
146
			'UB: +0.0/xr' => [ UnboundedQuantityValue::newFromNumber( '+0.0', '°' ), '0.0 °', $exactRounding ],
147
			'UB: +5.021/nm' => [ UnboundedQuantityValue::newFromNumber( '+5.021', '°' ), '5.021 °', $noMargin ],
148
			'UB: +5.021/wm' => [ UnboundedQuantityValue::newFromNumber( '+5.021', '°' ), '5.021 °', $withMargin ],
149
			'UB: +5.021/xr' => [ UnboundedQuantityValue::newFromNumber( '+5.021', '°' ), '5.02 °', $exactRounding ],
150
			'UB: +3.125/fs' => [ UnboundedQuantityValue::newFromNumber( '+3.125', '1' ), '+3.125', $forceSign ],
151
152
			// Unbounded quantities with enforced, exact rounding
153
			[ UnboundedQuantityValue::newFromNumber( '+0.00155', '1' ), '0.00', $exactRounding ],
154
			[ UnboundedQuantityValue::newFromNumber( '+0.0155', '1' ), '0.02', $exactRounding ],
155
			[ UnboundedQuantityValue::newFromNumber( '+0.155', '1' ), '0.16', $exactRounding ],
156
			[ UnboundedQuantityValue::newFromNumber( '+1.55', '1' ), '1.55', $exactRounding ],
157
			[ UnboundedQuantityValue::newFromNumber( '+15.5', '1' ), '15.5', $exactRounding ],
158
			[ UnboundedQuantityValue::newFromNumber( '+155', '1' ), '155', $exactRounding ],
159
160
			// Default options with different margins
161
			'24+-000.01' => [ QuantityValue::newFromNumber( '+24', '1', '+24.01', '+23.99' ), '24±0.01' ],
162
			'24+-000.10' => [ QuantityValue::newFromNumber( '+24', '1', '+24.1', '+23.9' ), '24±0.1' ],
163
			'24+-001.00' => [ QuantityValue::newFromNumber( '+24', '1', '+25', '+23' ), '24±1' ],
164
			'24+-010.00' => [ QuantityValue::newFromNumber( '+24', '1', '+34', '+14' ), '24±10' ],
165
			'24+-100.00' => [ QuantityValue::newFromNumber( '+24', '1', '+124', '-76' ), '24±100' ],
166
167
			// Rounding with a fixed +/-1 margin
168
			[ QuantityValue::newFromNumber( '+1.44', '1', '+2.44', '+0.44' ), '1', $noMargin ],
169
			[ QuantityValue::newFromNumber( '+1.45', '1', '+2.45', '+0.45' ), '1', $noMargin ],
170
			[ QuantityValue::newFromNumber( '+1.49', '1', '+2.49', '+0.49' ), '1', $noMargin ],
171
			[ QuantityValue::newFromNumber( '+1.50', '1', '+2.50', '+0.50' ), '2', $noMargin ],
172
			[ QuantityValue::newFromNumber( '+2.50', '1', '+3.50', '+1.50' ), '3', $noMargin ],
173
174
			// Rounding with different margins
175
			'1.55+/-0.09' => [ QuantityValue::newFromNumber( '+1.55', '1', '+1.64', '+1.46' ), '1.55', $noMargin ],
176
			'1.55+/-0.1' => [ QuantityValue::newFromNumber( '+1.55', '1', '+1.65', '+1.45' ), '1.6', $noMargin ],
177
			'1.55+/-0.49' => [ QuantityValue::newFromNumber( '+1.55', '1', '+2.04', '+1.06' ), '1.6', $noMargin ],
178
			'1.55+/-0.5' => [ QuantityValue::newFromNumber( '+1.55', '1', '+2.05', '+1.05' ), '1.6', $noMargin ],
179
			'1.55+/-0.99' => [ QuantityValue::newFromNumber( '+1.55', '1', '+2.54', '+0.56' ), '1.6', $noMargin ],
180
			'1.55+/-1' => [ QuantityValue::newFromNumber( '+1.55', '1', '+2.55', '+0.55' ), '2', $noMargin ],
181
			// FIXME: We should probably never round to zero as it is confusing.
182
			'1.55+/-10' => [ QuantityValue::newFromNumber( '+1.55', '1', '+11.55', '-8.45' ), '0', $noMargin ],
183
184
			// Do not mess with the value when the margin is rendered
185
			[ QuantityValue::newFromNumber( '+1500', '1', '+2500', '+500' ), '1500±1000' ],
186
			[ QuantityValue::newFromNumber( '+2', '1', '+2.005', '+1.995' ), '2±0.005' ],
187
			[ QuantityValue::newFromNumber( '+1.5', '1', '+2.5', '+0.5' ), '1.5±1' ],
188
			[ QuantityValue::newFromNumber( '+1.0005', '1', '+1.0015', '+0.9995' ), '1.0005±0.001' ],
189
			[ QuantityValue::newFromNumber( '+0.0015', '1', '+0.0025', '+0.0005' ), '0.0015±0.001' ],
190
191
			/**
192
			 * Never mess with the margin
193
			 * @see https://phabricator.wikimedia.org/T58892
194
			 */
195
			[ QuantityValue::newFromNumber( '+2', '1', '+3.5', '+0.5' ), '2±1.5' ],
196
			[ QuantityValue::newFromNumber( '+2', '1', '+2.016', '+1.984' ), '2±0.016' ],
197
			[ QuantityValue::newFromNumber( '+2', '1', '+2.0015', '+1.9985' ), '2±0.0015' ],
198
			[ QuantityValue::newFromNumber( '+0.0015', '1', '+0.003', '+0' ), '0.0015±0.0015' ],
199
			[ QuantityValue::newFromNumber( '+2.0011', '1', '+2.0022', '+2' ), '2.0011±0.0011' ],
200
			[ QuantityValue::newFromNumber( '+2.0099', '1', '+2.0198', '+2' ), '2.0099±0.0099' ],
201
202
			// IEEE edge cases
203
			[
204
				QuantityValue::newFromNumber(
205
					'+1.00000000000000015',
206
					'1',
207
					'+1.00000000000000025',
208
					'+1.00000000000000005'
209
				),
210
				'1.00000000000000015±0.0000000000000001'
211
			],
212
			'0.2 / 3 * 3' => [
213
				QuantityValue::newFromNumber(
214
					'+0.2000000000000000111',
215
					'1',
216
					'+0.2000000000000000111',
217
					'+0.2000000000000000111'
218
				),
219
				'0.2000000000000000111±0'
220
			],
221
			'8 - 6.4' => [
222
				QuantityValue::newFromNumber(
223
					'+1.59999999999999964473',
224
					'1',
225
					'+1.59999999999999964473',
226
					'+1.59999999999999964473'
227
				),
228
				'1.59999999999999964473±0'
229
			],
230
		];
231
	}
232
233
	public function testFormatWithFormatString() {
234
		$formatter = $this->getQuantityFormatter( null, '<$2>$1' );
235
		$value = UnboundedQuantityValue::newFromNumber( '+5', 'USD' );
236
		$formatted = $formatter->format( $value );
237
		$this->assertSame( '<USD>5', $formatted );
238
	}
239
240
}
241