Completed
Push — add/changelog-tooling ( 86359e...64ad4d )
by
unknown
40:44 queued 31:04
created

WordpressVersioningTest::provideNextVersion()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 107

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 107
rs 8
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
/**
3
 * Tests for the WordPress versioning plugin.
4
 *
5
 * @package automattic/jetpack-changelogger
6
 */
7
8
// phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
9
10
namespace Automattic\Jetpack\Changelogger\Tests\Plugins;
11
12
use Automattic\Jetpack\Changelog\ChangeEntry;
13
use Automattic\Jetpack\Changelogger\Plugins\WordpressVersioning;
14
use InvalidArgumentException;
15
use PHPUnit\Framework\TestCase;
16
use Symfony\Component\Console\Input\ArrayInput;
17
use Symfony\Component\Console\Input\InputDefinition;
18
use Symfony\Component\Console\Input\InputOption;
19
use Symfony\Component\Console\Output\BufferedOutput;
20
21
/**
22
 * Tests for the WordPress versioning plugin.
23
 *
24
 * @covers \Automattic\Jetpack\Changelogger\Plugins\WordpressVersioning
25
 */
26
class WordpressVersioningTest extends TestCase {
27
	use \Yoast\PHPUnitPolyfills\Polyfills\AssertIsType;
28
	use \Yoast\PHPUnitPolyfills\Polyfills\ExpectException;
29
30
	/**
31
	 * Test getOptions.
32
	 */
33
	public function testGetOptions() {
34
		$obj  = new WordpressVersioning( array() );
0 ignored issues
show
Unused Code introduced by
The call to WordpressVersioning::__construct() has too many arguments starting with array().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
35
		$opts = $obj->getOptions();
36
		$this->assertIsArray( $opts );
37
		foreach ( $opts as $opt ) {
38
			$this->assertInstanceOf( InputOption::class, $opt );
39
		}
40
	}
41
42
	/**
43
	 * Test normalizeVersion and parseVersion.
44
	 *
45
	 * @dataProvider provideNormalizeVersion
46
	 * @param string                          $version Version.
47
	 * @param string|InvalidArgumentException $expect Expected result.
48
	 */
49 View Code Duplication
	public function testNormalizeVersion( $version, $expect ) {
50
		$obj = new WordpressVersioning( array() );
0 ignored issues
show
Unused Code introduced by
The call to WordpressVersioning::__construct() has too many arguments starting with array().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
51
		if ( $expect instanceof InvalidArgumentException ) {
52
			$this->expectException( InvalidArgumentException::class );
53
			$this->expectExceptionMessage( $expect->getMessage() );
54
			$obj->normalizeVersion( $version );
55
		} else {
56
			$this->assertSame( $expect, $obj->normalizeVersion( $version ) );
57
		}
58
	}
59
60
	/**
61
	 * Data provider for testNormalizeVersion.
62
	 */
63
	public function provideNormalizeVersion() {
64
		return array(
65
			array( '1.2', '1.2' ),
66
			array( '1000.2', '1000.2' ),
67
			array( '1000.2.999', '1000.2.999' ),
68
			array( '1.2.3', '1.2.3' ),
69
			array( '1.2.0', '1.2' ),
70
			array( '0.0.0', '0.0' ),
71
			array( '1.2-dev', '1.2-dev' ),
72
			array( '1.2.3-dev', '1.2.3-dev' ),
73
			array( '1.2.3-alpha', '1.2.3-alpha' ),
74
			array( '1.2-alpha1', '1.2-alpha1' ),
75
			array( '1.2.3-beta', '1.2.3-beta' ),
76
			array( '1.2-beta1', '1.2-beta1' ),
77
			array( '1.2.3-rc', '1.2.3-rc' ),
78
			array( '1.2-rc1', '1.2-rc1' ),
79
			array( '1.2.3-alpha+foobar', '1.2.3-alpha+foobar' ),
80
			array( '1.2.3-alpha1+foobar.2', '1.2.3-alpha1+foobar.2' ),
81
			array( '0001.2.0003-alpha0001+000foobar000....0002', '1.2.3-alpha0001+000foobar000....0002' ),
82
83
			array( '1.22', new InvalidArgumentException( 'Version number "1.22" is not in a recognized format.' ) ),
84
			array( '1.2.x', new InvalidArgumentException( 'Version number "1.2.x" is not in a recognized format.' ) ),
85
			array( '1.x.4', new InvalidArgumentException( 'Version number "1.x.4" is not in a recognized format.' ) ),
86
			array( '1..4', new InvalidArgumentException( 'Version number "1..4" is not in a recognized format.' ) ),
87
			array( '.2.3', new InvalidArgumentException( 'Version number ".2.3" is not in a recognized format.' ) ),
88
			array( '1.2.', new InvalidArgumentException( 'Version number "1.2." is not in a recognized format.' ) ),
89
			array( '1.2.-1', new InvalidArgumentException( 'Version number "1.2.-1" is not in a recognized format.' ) ),
90
			array( 'v1.2.3', new InvalidArgumentException( 'Version number "v1.2.3" is not in a recognized format.' ) ),
91
			array( '1.2.3.4', new InvalidArgumentException( 'Version number "1.2.3.4" is not in a recognized format.' ) ),
92
			array( '1.2-alpha.1', new InvalidArgumentException( 'Version number "1.2-alpha.1" is not in a recognized format.' ) ),
93
			array( '1.2-dev1', new InvalidArgumentException( 'Version number "1.2-dev1" is not in a recognized format.' ) ),
94
			array( '1.2-DEV', new InvalidArgumentException( 'Version number "1.2-DEV" is not in a recognized format.' ) ),
95
			array( '1.2-foo', new InvalidArgumentException( 'Version number "1.2-foo" is not in a recognized format.' ) ),
96
			array( '1.2-foo1', new InvalidArgumentException( 'Version number "1.2-foo1" is not in a recognized format.' ) ),
97
			array( '1.2.3-?', new InvalidArgumentException( 'Version number "1.2.3-?" is not in a recognized format.' ) ),
98
			array( '1.2.3+?', new InvalidArgumentException( 'Version number "1.2.3+?" is not in a recognized format.' ) ),
99
			array( '1.2.3-a..b', new InvalidArgumentException( 'Version number "1.2.3-a..b" is not in a recognized format.' ) ),
100
		);
101
	}
102
103
	/**
104
	 * Test nextVersion.
105
	 *
106
	 * @dataProvider provideNextVersion
107
	 * @param string                          $version Version.
108
	 * @param ChangeEntry[]                   $changes Changes.
109
	 * @param array                           $extra Extra components.
110
	 * @param string|InvalidArgumentException $expect Expected result.
111
	 * @param string                          $expectPoint Expected result for a point release.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $expectPoint not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
112
	 */
113
	public function testNextVersion( $version, array $changes, array $extra, $expect, $expectPoint = null ) {
114
		$obj = new WordpressVersioning( array() );
0 ignored issues
show
Unused Code introduced by
The call to WordpressVersioning::__construct() has too many arguments starting with array().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
115
116
		$out1 = $this->getMockBuilder( BufferedOutput::class )
117
			->setMethods( array( 'getErrorOutput' ) )
118
			->getMock();
119
		$out2 = new BufferedOutput();
120
		$out1->method( 'getErrorOutput' )->willReturn( $out2 );
121
122
		$def = new InputDefinition( $obj->getOptions() );
123
		$obj->setIO( new ArrayInput( array(), $def ), $out1 );
124
125
		if ( $expect instanceof InvalidArgumentException ) {
126
			$this->expectException( InvalidArgumentException::class );
127
			$this->expectExceptionMessage( $expect->getMessage() );
128
			$obj->nextVersion( $version, $changes, $extra );
0 ignored issues
show
Documentation introduced by
$changes is of type array<integer,object<Aut...Changelog\ChangeEntry>>, but the function expects a array<integer,object<Aut...r\Plugins\ChangeEntry>>.

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...
129
		} else {
130
			$this->assertSame( $expect, $obj->nextVersion( $version, $changes, $extra ) );
0 ignored issues
show
Documentation introduced by
$changes is of type array<integer,object<Aut...Changelog\ChangeEntry>>, but the function expects a array<integer,object<Aut...r\Plugins\ChangeEntry>>.

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...
131
			$this->assertSame( '', $out1->fetch() );
132
			$this->assertSame( '', $out2->fetch() );
133
134
			$obj->setIO( new ArrayInput( array( '--point-release' => true ), $def ), $out1 );
135
			$this->assertSame( $expectPoint, $obj->nextVersion( $version, $changes, $extra ) );
0 ignored issues
show
Documentation introduced by
$changes is of type array<integer,object<Aut...Changelog\ChangeEntry>>, but the function expects a array<integer,object<Aut...r\Plugins\ChangeEntry>>.

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...
136
			$this->assertSame( '', $out1->fetch() );
137
			$this->assertSame( '', $out2->fetch() );
138
		}
139
	}
140
141
	/**
142
	 * Data provider for testNextVersion.
143
	 */
144
	public function provideNextVersion() {
145
		return array(
146
			'No changes'                               => array(
147
				'1.2.3',
148
				array(),
149
				array(),
150
				'1.3',
151
				'1.2.4',
152
			),
153
			'Patch changes'                            => array(
154
				'1.2.3',
155
				array(
156
					new ChangeEntry( array( 'significance' => 'patch' ) ),
157
					new ChangeEntry( array( 'significance' => 'patch' ) ),
158
					new ChangeEntry( array( 'significance' => null ) ),
159
					new ChangeEntry( array( 'significance' => 'patch' ) ),
160
				),
161
				array(),
162
				'1.3',
163
				'1.2.4',
164
			),
165
			'Minor change'                             => array(
166
				'1.2.3',
167
				array(
168
					new ChangeEntry( array( 'significance' => 'patch' ) ),
169
					new ChangeEntry( array( 'significance' => 'minor' ) ),
170
					new ChangeEntry( array( 'significance' => null ) ),
171
					new ChangeEntry( array( 'significance' => 'patch' ) ),
172
				),
173
				array(),
174
				'1.3',
175
				'1.2.4',
176
			),
177
			'Major change'                             => array(
178
				'1.2.3',
179
				array(
180
					new ChangeEntry( array( 'significance' => 'patch' ) ),
181
					new ChangeEntry( array( 'significance' => 'minor' ) ),
182
					new ChangeEntry( array( 'significance' => null ) ),
183
					new ChangeEntry( array( 'significance' => 'major' ) ),
184
					new ChangeEntry( array( 'significance' => 'patch' ) ),
185
				),
186
				array(),
187
				'1.3',
188
				'1.2.4',
189
			),
190
			'Version number with extra components'     => array(
191
				'1.2.3-dev',
192
				array(),
193
				array(),
194
				'1.3',
195
				'1.2.4',
196
			),
197
			'Version number with extra components (2)' => array(
198
				'1.2.9+123',
199
				array(),
200
				array(),
201
				'1.3',
202
				'1.2.10',
203
			),
204
			'Version number with extra components (3)' => array(
205
				'1.2.3-dev+bar',
206
				array(),
207
				array(),
208
				'1.3',
209
				'1.2.4',
210
			),
211
			'Roll over major component'                => array(
212
				'99.9.999',
213
				array(),
214
				array(),
215
				'100.0',
216
				'99.9.1000',
217
			),
218
219
			'Including extra components'               => array(
220
				'1.2.3',
221
				array(),
222
				array(
223
					'prerelease' => 'alpha2',
224
					'buildinfo'  => 'g12345678.003',
225
				),
226
				'1.3-alpha2+g12345678.003',
227
				'1.2.4-alpha2+g12345678.003',
228
			),
229
			'Including extra components (2)'           => array(
230
				'1.2.3-dev',
231
				array(),
232
				array( 'buildinfo' => 'g12345678' ),
233
				'1.3+g12345678',
234
				'1.2.4+g12345678',
235
			),
236
237
			'Invalid prerelease component'             => array(
238
				'1.2.3-dev',
239
				array(),
240
				array( 'prerelease' => 'delta' ),
241
				new InvalidArgumentException( 'Invalid prerelease data' ),
242
			),
243
			'Invalid buildinfo component'              => array(
244
				'1.2.3-dev',
245
				array(),
246
				array( 'buildinfo' => 'build?' ),
247
				new InvalidArgumentException( 'Invalid buildinfo data' ),
248
			),
249
		);
250
	}
251
252
	/**
253
	 * Test compareVersions.
254
	 *
255
	 * @dataProvider provideCompareVersions
256
	 * @param string $a Version A.
257
	 * @param string $expect Expected result converted to a string, '>', '==', or '<'.
258
	 * @param string $b Version B.
259
	 */
260 View Code Duplication
	public function testCompareVersions( $a, $expect, $b ) {
261
		$obj = new WordpressVersioning( array() );
0 ignored issues
show
Unused Code introduced by
The call to WordpressVersioning::__construct() has too many arguments starting with array().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
262
		$ret = $obj->compareVersions( $a, $b );
263
		$this->assertIsInt( $ret );
264
		$ret = $ret < 0 ? '<' : ( $ret > 0 ? '>' : '==' );
265
		$this->assertSame( $expect, $ret );
266
	}
267
268
	/**
269
	 * Data provider for testCompareVersions.
270
	 */
271
	public function provideCompareVersions() {
272
		return array(
273
			array( '1.0', '==', '1.0' ),
274
			array( '1.0.0', '==', '1.0' ),
275
			array( '1.0', '<', '2.0' ),
276
			array( '2.0', '>', '1.0' ),
277
			array( '1.1', '>', '1.0' ),
278
			array( '1.0', '<', '1.1' ),
279
			array( '1.9.999', '<', '2.0' ),
280
			array( '1.1', '<', '1.1.1' ),
281
			array( '1.0.999', '<', '1.1' ),
282
			array( '1.1.2', '>', '1.1.1' ),
283
			array( '1.1.1', '>', '1.1.1-dev' ),
284
			array( '1.1.0', '<', '1.1.1-dev' ),
285
			array( '1.1.1-alpha', '<', '1.1.1-beta' ),
286
			array( '1.1.1-dev', '<', '1.1.1-alpha' ),
287
			array( '1.1.1-alpha9', '<', '1.1.1-beta1' ),
288
			array( '1.1.1-beta9', '>', '1.1.1-beta1' ),
289
			array( '1.1.1-beta9', '==', '1.1.1-beta9' ),
290
			array( '1.1.1-alpha2', '<', '1.1.1-alpha10' ),
291
			array( '1.1.1+beta.9.1', '==', '1.1.1+beta.9' ),
292
		);
293
	}
294
295
}
296