Completed
Push — add/changelog-tooling ( b2784f...e205c1 )
by
unknown
109:57 queued 100:19
created

WriteCommandTest   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 214
Duplicated Lines 1.87 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
dl 4
loc 214
rs 10
c 0
b 0
f 0
wmc 14
lcom 0
cbo 1

3 Methods

Rating   Name   Duplication   Size   Complexity  
A set_up() 0 6 1
F testExecute() 4 44 12
B provideExecute() 0 137 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
/**
3
 * Tests for the changelogger write command.
4
 *
5
 * @package automattic/jetpack-changelogger
6
 */
7
8
// phpcs:disable WordPress.WP.AlternativeFunctions, WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
9
10
namespace Automattic\Jetpack\Changelogger\Tests;
11
12
use Automattic\Jetpack\Changelogger\WriteCommand;
13
use Symfony\Component\Console\Output\OutputInterface;
14
15
/**
16
 * Tests for the changelogger write command.
17
 *
18
 * @covers \Automattic\Jetpack\Changelogger\WriteCommand
19
 */
20
class WriteCommandTest extends CommandTestCase {
21
	use \Yoast\PHPUnitPolyfills\Polyfills\AssertionRenames;
22
23
	/**
24
	 * Set up.
25
	 *
26
	 * @before
27
	 */
28
	public function set_up() {
29
		parent::set_up();
30
		$this->useTempDir();
31
		mkdir( 'changelog' );
32
		file_put_contents( 'changelog/.gitkeep', '' );
33
	}
34
35
	/**
36
	 * Test the command.
37
	 *
38
	 * @dataProvider provideExecute
39
	 * @param string[]    $args Command line arguments.
40
	 * @param array       $options Options for the test and CommandTester.
41
	 * @param string[]    $inputs User inputs.
42
	 * @param int         $expectExitCode Expected exit code.
43
	 * @param string[]    $expectOutputRegexes Regexes to run against the output.
44
	 * @param bool        $expectChangesDeleted Whether change files should have been deleted.
45
	 * @param string|null $expectChangelog Expected changelog file contents, or null if it should be the same as $options['changelog'].
46
	 */
47
	public function testExecute( array $args, array $options, array $inputs, $expectExitCode, $expectOutputRegexes = array(), $expectChangesDeleted = false, $expectChangelog = null ) {
48 View Code Duplication
		if ( isset( $options['composer.json'] ) ) {
49
			file_put_contents( 'composer.json', json_encode( array( 'extra' => array( 'changelogger' => $options['composer.json'] ) ), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) );
50
			unset( $options['composer.json'] );
51
		}
52
		$changelog = isset( $options['changelog'] ) ? $options['changelog'] : null;
53
		$changes   = isset( $options['changes'] ) ? $options['changes'] : array();
54
		unset( $options['changelog'], $options['changes'] );
55
		if ( null !== $changelog ) {
56
			file_put_contents( 'CHANGELOG.md', $changelog );
57
		}
58
		foreach ( $changes as $name => $change ) {
59
			file_put_contents( "changelog/$name", $change );
60
		}
61
62
		$tester = $this->getTester( 'write' );
63
		$tester->setInputs( $inputs );
64
		$code = $tester->execute( $args, $options );
65
		foreach ( $expectOutputRegexes as $re ) {
66
			$this->assertMatchesRegularExpression( $re, $tester->getDisplay() );
67
		}
68
		$this->assertSame( $expectExitCode, $code );
69
70
		$this->assertFileExists( 'changelog/.gitkeep' );
71
		if ( $expectChangesDeleted ) {
72
			foreach ( $changes as $name => $change ) {
73
				$this->assertFileDoesNotExist( "changelog/$name" );
74
			}
75
		} else {
76
			foreach ( $changes as $name => $change ) {
77
				$this->assertFileExists( "changelog/$name" );
78
			}
79
		}
80
81
		if ( null === $expectChangelog ) {
82
			$expectChangelog = $changelog;
83
		}
84
		if ( null === $expectChangelog ) {
85
			$this->assertFileDoesNotExist( 'CHANGELOG.md' );
86
		} else {
87
			$this->assertFileExists( 'CHANGELOG.md' );
88
			$this->assertSame( $expectChangelog, file_get_contents( 'CHANGELOG.md' ) );
89
		}
90
	}
91
92
	/**
93
	 * Data provider for testExecute.
94
	 */
95
	public function provideExecute() {
96
		$date           = gmdate( 'Y-m-d' );
97
		$defaultOptions = array(
98
			'changelog' => "# Changelog\n\n## 1.0.1 - 2021-02-23\n\nPrologue for v1.0.1\n\n### Added\n- Stuff.\n\n### Removed\n- Other stuff.\n\nEpilogue for v1.0.1\n\n## 1.0.0 - 2021-02-23\n\n- Initial release.\n",
99
			'changes'   => array(
100
				'a-change' => "Significance: patch\nType: fixed\n\nFixed a thing.\n",
101
			),
102
		);
103
104
		return array(
105
			'Normal run'                                => array(
106
				array(),
107
				$defaultOptions,
108
				array(),
109
				0,
110
				array( '/^$/' ),
111
				true,
112
				"# Changelog\n\n## 1.0.2 - $date\n### Fixed\n- Fixed a thing.\n\n## 1.0.1 - 2021-02-23\n\nPrologue for v1.0.1\n\n### Added\n- Stuff.\n\n### Removed\n- Other stuff.\n\nEpilogue for v1.0.1\n\n## 1.0.0 - 2021-02-23\n\n- Initial release.\n",
113
			),
114
			'Debug run'                                 => array(
115
				array(),
116
				array( 'verbosity' => OutputInterface::VERBOSITY_DEBUG ) + $defaultOptions,
117
				array(),
118
				0,
119
				array(
120
					'{^Reading changelog from /.*/CHANGELOG.md\\.\\.\\.$}m',
121
					'{^Reading changes from /.*/changelog\\.\\.\\.$}m',
122
					'{^Deduplicating changes from the last 1 version\\(s\\)\\.\\.\\.$}m',
123
					'{^Checking if any changes have content\\.\\.\\.$}m',
124
					'{^Yes, a-change has content\\.$}m',
125
					'{^Latest version from changelog is 1\\.0\\.1\\.$}m',
126
					'{^Next version is 1\\.0\\.2\\.$}m',
127
					'{^Creating new changelog entry\\.$}m',
128
					'{^Writing changelog to /.*/CHANGELOG.md\\.\\.\\.$}m',
129
					'{^Deleted change file a-change\\.$}m',
130
				),
131
				true,
132
				"# Changelog\n\n## 1.0.2 - $date\n### Fixed\n- Fixed a thing.\n\n## 1.0.1 - 2021-02-23\n\nPrologue for v1.0.1\n\n### Added\n- Stuff.\n\n### Removed\n- Other stuff.\n\nEpilogue for v1.0.1\n\n## 1.0.0 - 2021-02-23\n\n- Initial release.\n",
133
			),
134
			'Run with extra command line args'          => array(
135
				array(
136
					'--prerelease' => 'dev',
137
					'--buildinfo'  => 'g1234567',
138
					'--prologue'   => 'Prologue for the new entry',
139
					'--epilogue'   => 'Epilogue for the new entry',
140
					'--link'       => 'https://example.org/link',
141
				),
142
				$defaultOptions,
143
				array(),
144
				0,
145
				array( '/^$/' ),
146
				true,
147
				"# Changelog\n\n## [1.0.2-dev+g1234567] - $date\n\nPrologue for the new entry\n\n### Fixed\n- Fixed a thing.\n\nEpilogue for the new entry\n\n## 1.0.1 - 2021-02-23\n\nPrologue for v1.0.1\n\n### Added\n- Stuff.\n\n### Removed\n- Other stuff.\n\nEpilogue for v1.0.1\n\n## 1.0.0 - 2021-02-23\n\n- Initial release.\n\n[1.0.2-dev+g1234567]: https://example.org/link\n",
148
			),
149
150
			'Invalid formatter'                         => array(
151
				array(),
152
				array( 'composer.json' => array( 'formatter' => 'bogus' ) ),
153
				array(),
154
				WriteCommand::FATAL_EXIT,
155
				array( '/^Unknown formatter plugin "bogus"$/' ),
156
			),
157
			'Invalid versioning'                        => array(
158
				array(),
159
				array( 'composer.json' => array( 'versioning' => 'bogus' ) ),
160
				array(),
161
				WriteCommand::FATAL_EXIT,
162
				array( '/^Unknown versioning plugin "bogus"$/' ),
163
			),
164
165
			'No changelog file, interactive'            => array(
166
				array(),
167
				array( 'changelog' => null ) + $defaultOptions,
168
				array( 'N' ),
169
				WriteCommand::ASKED_EXIT,
170
				array( '{^Changelog file /.*/CHANGELOG\.md does not exist! Proceed\? \[y/N\]}m' ),
171
			),
172
			'No changelog file, interactive (2)'        => array(
173
				array(),
174
				array( 'changelog' => null ) + $defaultOptions,
175
				array( 'Y' ),
176
				WriteCommand::FATAL_EXIT,
177
				array( '/Changelog file contains no entries! Use --use-version to specify the initial version\.$/m' ),
178
			),
179
			'No changelog file, interactive (3)'        => array(
180
				array( '--use-version' => '1.0.0' ),
181
				array( 'changelog' => null ) + $defaultOptions,
182
				array( 'Y' ),
183
				0,
184
				array(),
185
				true,
186
				"## 1.0.0 - $date\n### Fixed\n- Fixed a thing.\n",
187
			),
188
			'No changelog file, non-interactive'        => array(
189
				array(),
190
				array(
191
					'interactive' => false,
192
					'changelog'   => null,
193
				) + $defaultOptions,
194
				array(),
195
				WriteCommand::ASKED_EXIT,
196
				array( '{^Changelog file /.*/CHANGELOG\.md does not exist!$}m' ),
197
			),
198
			'No changelog file, non-interactive, --yes' => array(
199
				array( '--yes' => true ),
200
				array(
201
					'interactive' => false,
202
					'changelog'   => null,
203
				) + $defaultOptions,
204
				array(),
205
				WriteCommand::FATAL_EXIT,
206
				array(
207
					'{^<warning>Changelog file /.*/CHANGELOG\.md does not exist! Continuing anyway\.$}m',
208
					'/Changelog file contains no entries! Use --use-version to specify the initial version\.$/m',
209
				),
210
			),
211
			'No changelog file, non-interactive, --yes (2)' => array(
212
				array(
213
					'--yes'         => true,
214
					'--use-version' => '1.0.0',
215
				),
216
				array(
217
					'interactive' => false,
218
					'changelog'   => null,
219
				) + $defaultOptions,
220
				array(),
221
				0,
222
				array(
223
					'{^<warning>Changelog file /.*/CHANGELOG\.md does not exist! Continuing anyway\.$}m',
224
				),
225
				true,
226
				"## 1.0.0 - $date\n### Fixed\n- Fixed a thing.\n",
227
			),
228
229
			// TODO: More tests.
230
		);
231
	}
232
233
}
234