getQuantityHtmlFormatter()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 2
nc 1
nop 3
1
<?php
2
3
namespace ValueFormatters\Test;
4
5
use DataValues\DecimalValue;
6
use DataValues\QuantityValue;
7
use DataValues\UnboundedQuantityValue;
8
use PHPUnit\Framework\TestCase;
9
use ValueFormatters\DecimalFormatter;
10
use ValueFormatters\FormatterOptions;
11
use ValueFormatters\QuantityHtmlFormatter;
12
use ValueFormatters\ValueFormatter;
13
14
/**
15
 * @covers ValueFormatters\QuantityHtmlFormatter
16
 *
17
 * @license GPL-2.0-or-later
18
 * @author Thiemo Kreuz
19
 */
20
class QuantityHtmlFormatterTest extends TestCase {
21
22
	/**
23
	 * @see ValueFormatterTestBase::getInstance
24
	 *
25
	 * @param FormatterOptions|null $options
26
	 *
27
	 * @return QuantityHtmlFormatter
28
	 */
29
	protected function getInstance( FormatterOptions $options = null ) {
30
		return $this->getQuantityHtmlFormatter( $options );
31
	}
32
33
	/**
34
	 * @param FormatterOptions|null $options
35
	 * @param DecimalFormatter|null $decimalFormatter
36
	 * @param string|null $quantityWithUnitFormat
37
	 *
38
	 * @return QuantityHtmlFormatter
39
	 */
40
	private function getQuantityHtmlFormatter(
41
		FormatterOptions $options = null,
42
		DecimalFormatter $decimalFormatter = null,
43
		$quantityWithUnitFormat = null
44
	) {
45
		$vocabularyUriFormatter = $this->createMock( ValueFormatter::class );
46
		$vocabularyUriFormatter->expects( $this->any() )
47
			->method( 'format' )
48
			->will( $this->returnCallback( function ( $unit ) {
49
				return $unit === '1' ? null : $unit;
50
			} ) );
51
52
		return new QuantityHtmlFormatter(
53
			$options,
54
			$decimalFormatter,
55
			$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...
56
			$quantityWithUnitFormat
57
		);
58
	}
59
60
	/**
61
	 * @param string $className
62
	 * @param int $uncertaintyMargin
63
	 *
64
	 * @return QuantityValue
65
	 */
66
	private function newQuantityValue( $className, $uncertaintyMargin = 0 ) {
67
		$quantity = $this->getMockBuilder( $className )
68
			->disableOriginalConstructor()
69
			->getMock();
70
71
		$quantity->expects( $this->any() )
72
			->method( 'getAmount' )
73
			->will( $this->returnValue( new DecimalValue( 2 ) ) );
74
		if ( $className === QuantityValue::class ) {
75
			$quantity->expects( $this->any() )
76
				->method( 'getUncertaintyMargin' )
77
				->will( $this->returnValue( new DecimalValue( $uncertaintyMargin ) ) );
78
		}
79
80
		return $quantity;
81
	}
82
83
	/**
84
	 * @see ValueFormatterTestBase::validProvider
85
	 */
86
	public function validProvider() {
87
		return [
88
			'Unbounded, Unit 1' => [
89
				UnboundedQuantityValue::newFromNumber( '+2', '1' ),
90
				'2'
91
			],
92
			'Unbounded, String unit' => [
93
				UnboundedQuantityValue::newFromNumber( '+2', 'Ultrameter' ),
94
				'2 <span class="wb-unit">Ultrameter</span>'
95
			],
96
			'Unit 1' => [
97
				QuantityValue::newFromNumber( '+2', '1', '+3', '+1' ),
98
				'2±1'
99
			],
100
			'String unit' => [
101
				QuantityValue::newFromNumber( '+2', 'Ultrameter', '+3', '+1' ),
102
				'2±1 <span class="wb-unit">Ultrameter</span>'
103
			],
104
			'HTML injection' => [
105
				QuantityValue::newFromNumber( '+2', '<b>injection</b>', '+2', '+2' ),
106
				'2±0 <span class="wb-unit">&lt;b&gt;injection&lt;/b&gt;</span>'
107
			],
108
		];
109
	}
110
111
	public function testFormatWithFormatString() {
112
		$formatter = $this->getQuantityHtmlFormatter( null, null, '$2&thinsp;$1' );
113
		$value = UnboundedQuantityValue::newFromNumber( '+5', 'USD' );
114
		$formatted = $formatter->format( $value );
115
		$this->assertSame( '<span class="wb-unit">USD</span>&thinsp;5', $formatted );
116
	}
117
118
	/**
119
	 * @dataProvider applyUnitOptionProvider
120
	 */
121
	public function testGivenHtmlCharacters_formatEscapesHtmlCharacters(
122
		?FormatterOptions $options,
123
		UnboundedQuantityValue $value,
124
		$expected
125
	) {
126
		$decimalFormatter = $this->createMock( DecimalFormatter::class );
127
		$decimalFormatter->expects( $this->any() )
128
			->method( 'format' )
129
			->will( $this->returnValue( '<b>+2</b>' ) );
130
131
		$formatter = $this->getQuantityHtmlFormatter( $options, $decimalFormatter );
0 ignored issues
show
Documentation introduced by
$decimalFormatter is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a null|object<ValueFormatters\DecimalFormatter>.

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...
132
		$formatted = $formatter->format( $value );
133
		$this->assertSame( $expected, $formatted );
134
	}
135
136
	public function applyUnitOptionProvider() {
137
		$noUnit = new FormatterOptions();
138
		$noUnit->setOption( QuantityHtmlFormatter::OPT_APPLY_UNIT, false );
139
140
		return [
141
			'Disabled without unit' => [
142
				$noUnit,
143
				UnboundedQuantityValue::newFromNumber( 2, '1' ),
144
				'&lt;b&gt;+2&lt;/b&gt;'
145
			],
146
			'Disabled with unit' => [
147
				$noUnit,
148
				UnboundedQuantityValue::newFromNumber( 2, '<b>m</b>' ),
149
				'&lt;b&gt;+2&lt;/b&gt;'
150
			],
151
			'Default without unit' => [
152
				null,
153
				UnboundedQuantityValue::newFromNumber( 2, '1' ),
154
				'&lt;b&gt;+2&lt;/b&gt;'
155
			],
156
			'Default with unit' => [
157
				null,
158
				UnboundedQuantityValue::newFromNumber( 2, '<b>m</b>' ),
159
				'&lt;b&gt;+2&lt;/b&gt; <span class="wb-unit">&lt;b&gt;m&lt;/b&gt;</span>'
160
			],
161
			'HTML escaping bounded' => [
162
				null,
163
				$this->newQuantityValue( QuantityValue::class ),
164
				'&lt;b&gt;+2&lt;/b&gt;±&lt;b&gt;+2&lt;/b&gt;'
165
			],
166
			'HTML escaping bounded with uncertainty' => [
167
				null,
168
				$this->newQuantityValue( QuantityValue::class, 1 ),
169
				'&lt;b&gt;+2&lt;/b&gt;±&lt;b&gt;+2&lt;/b&gt;'
170
			],
171
			'HTML escaping unbounded' => [
172
				null,
173
				$this->newQuantityValue( UnboundedQuantityValue::class ),
174
				'&lt;b&gt;+2&lt;/b&gt;'
175
			],
176
		];
177
	}
178
179
}
180