Skip to content

Commit c11d521

Browse files
committed
Chore: refactor
- Code style improvements in EntrypointLookup class; - Fixed unit tests; - Added composer command for running unit tests with coverage; Signed-off-by: Oleksii Bulba <[email protected]>
1 parent d0c807d commit c11d521

File tree

4 files changed

+178
-37
lines changed

4 files changed

+178
-37
lines changed

composer.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,19 @@
4747
}
4848
},
4949
"scripts": {
50+
"coverage": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-text",
5051
"php-cs-fix": "./vendor/bin/php-cs-fixer fix --verbose --using-cache=no",
5152
"php-cs-try": "./vendor/bin/php-cs-fixer fix --verbose --dry-run --using-cache=no",
5253
"phpstan": "./vendor/bin/phpstan analyze --no-progress",
53-
"phpunit": "./vendor/bin/phpunit"
54+
"phpunit": "./vendor/bin/phpunit",
55+
"statics": [
56+
"@phpstan",
57+
"@php-cs-try"
58+
],
59+
"test": [
60+
"@statics",
61+
"@phpunit",
62+
"@coverage"
63+
]
5464
}
5565
}

src/Asset/EntrypointLookup.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,19 @@ private function validateEntryName(string $entryName): void
8080
{
8181
/** @var array<string, array> $entriesData */
8282
$entriesData = $this->getEntriesData();
83-
if (!isset($entriesData['entrypoints'][$entryName])) {
84-
if (false !== $dotPos = strrpos($entryName, '.')) {
85-
$withoutExtension = substr($entryName, 0, $dotPos);
86-
87-
if (isset($entriesData['entrypoints'][$withoutExtension])) {
88-
throw new EntrypointNotFoundException(sprintf('Could not find the entry "%s". Try "%s" instead (without the extension).', $entryName, $withoutExtension));
89-
}
90-
}
83+
if (isset($entriesData['entrypoints'][$entryName])) {
84+
return;
85+
}
9186

87+
if (false === $dotPos = strrpos($entryName, '.')) {
9288
throw new EntrypointNotFoundException(sprintf('Could not find the entry "%s" in "%s". Found: %s.', $entryName, $this->getEntrypointJsonPath(), implode(', ', array_keys($entriesData['entrypoints']))));
9389
}
90+
91+
if (isset($entriesData['entrypoints'][$withoutExtension = substr($entryName, 0, $dotPos)])) {
92+
throw new EntrypointNotFoundException(sprintf('Could not find the entry "%s". Try "%s" instead (without the extension).', $entryName, $withoutExtension));
93+
}
94+
95+
throw new EntrypointNotFoundException(sprintf('Could not find the entry "%s" in "%s". Found: %s.', $entryName, $this->getEntrypointJsonPath(), implode(', ', array_keys($entriesData['entrypoints']))));
9496
}
9597

9698
private function getEntriesData(): array

tests/unit/Asset/EntrypointLookupTest.php

Lines changed: 156 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,74 @@
1717
use PHPUnit\Framework\MockObject\MockObject;
1818
use PHPUnit\Framework\TestCase;
1919
use Symfony\Component\Serializer\Encoder\JsonDecode;
20+
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
2021

2122
/**
2223
* @covers \OleksiiBulba\WebpackEncorePlugin\Asset\EntrypointLookup
2324
*/
2425
class EntrypointLookupTest extends TestCase
2526
{
27+
public const DECODED_ENTRYPOINTS = [
28+
'entrypoints' => [
29+
'entrypoint1' => [
30+
'js' => [
31+
'/some/path/to/jsFile.js',
32+
'/another/path/to/js/file.js',
33+
'/build/app.js',
34+
],
35+
],
36+
'entrypoint2' => [
37+
'js' => [
38+
'/some/path/to/another/js/file.js',
39+
],
40+
'css' => [
41+
'/some/path/to/js/file.css',
42+
],
43+
],
44+
],
45+
];
46+
2647
private EntrypointLookup $model;
2748

2849
private WebpackEncorePluginConfigurationInterface|MockObject $configurationMock;
2950

51+
private JsonDecode|MockObject $jsonDecodeMock;
52+
3053
protected function setUp(): void
3154
{
3255
$this->configurationMock = $this->getMockBuilder(WebpackEncorePluginConfigurationInterface::class)
3356
->disableOriginalConstructor()
3457
->onlyMethods(['getOutputPath'])
3558
->getMockForAbstractClass();
3659

37-
$this->model = new EntrypointLookup($this->configurationMock, new JsonDecode([JsonDecode::ASSOCIATIVE => true]));
60+
$this->jsonDecodeMock = $this->getMockBuilder(JsonDecode::class)
61+
->disableOriginalConstructor()
62+
->onlyMethods(['decode'])
63+
->getMock();
64+
65+
$this->model = new EntrypointLookup($this->configurationMock, $this->jsonDecodeMock);
3866
}
3967

4068
/**
4169
* @dataProvider getCssFilesDataProvider
4270
*
4371
* @covers \OleksiiBulba\WebpackEncorePlugin\Asset\EntrypointLookup::getCssFiles
4472
*/
45-
public function testGetCssFiles(string $entryName, array $expectedResult): void
46-
{
73+
public function testGetCssFiles(
74+
string $entryName,
75+
array $expectedResult,
76+
string $expectedJson,
77+
?array $decodedJson
78+
): void {
4779
$this->configurationMock->expects($this->any())
4880
->method('getOutputPath')
4981
->willReturn(__DIR__.'/../fixtures/correct');
5082

83+
$this->jsonDecodeMock->expects($this->once())
84+
->method('decode')
85+
->with($expectedJson)
86+
->willReturn($decodedJson);
87+
5188
$this->assertEquals($expectedResult, $this->model->getCssFiles($entryName));
5289
}
5390

@@ -57,12 +94,16 @@ public function getCssFilesDataProvider(): array
5794
[
5895
'entryName' => 'entrypoint1',
5996
'expectedResult' => [],
97+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
98+
'decodedJson' => self::DECODED_ENTRYPOINTS,
6099
],
61100
[
62101
'entryName' => 'entrypoint2',
63102
'expectedResult' => [
64103
'/some/path/to/js/file.css',
65104
],
105+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
106+
'decodedJson' => self::DECODED_ENTRYPOINTS,
66107
],
67108
];
68109
}
@@ -72,12 +113,21 @@ public function getCssFilesDataProvider(): array
72113
*
73114
* @covers \OleksiiBulba\WebpackEncorePlugin\Asset\EntrypointLookup::getJavaScriptFiles
74115
*/
75-
public function testGetJavaScriptFiles(string $entryName, array $expectedResult): void
76-
{
116+
public function testGetJavaScriptFiles(
117+
string $entryName,
118+
array $expectedResult,
119+
string $expectedJson,
120+
?array $decodedJson
121+
): void {
77122
$this->configurationMock->expects($this->any())
78123
->method('getOutputPath')
79124
->willReturn(__DIR__.'/../fixtures/correct');
80125

126+
$this->jsonDecodeMock->expects($this->once())
127+
->method('decode')
128+
->with($expectedJson)
129+
->willReturn($decodedJson);
130+
81131
$this->assertEquals($expectedResult, $this->model->getJavaScriptFiles($entryName));
82132
}
83133

@@ -91,12 +141,16 @@ public function getJavaScriptFilesDataProvider(): array
91141
'/another/path/to/js/file.js',
92142
'/build/app.js',
93143
],
144+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
145+
'decodedJson' => self::DECODED_ENTRYPOINTS,
94146
],
95147
[
96148
'entryName' => 'entrypoint2',
97149
'expectedResult' => [
98150
'/some/path/to/another/js/file.js',
99151
],
152+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
153+
'decodedJson' => self::DECODED_ENTRYPOINTS,
100154
],
101155
];
102156
}
@@ -106,12 +160,21 @@ public function getJavaScriptFilesDataProvider(): array
106160
*
107161
* @covers \OleksiiBulba\WebpackEncorePlugin\Asset\EntrypointLookup::entryExists
108162
*/
109-
public function testEntryExists(string $entryName, bool $expectedResult): void
110-
{
163+
public function testEntryExists(
164+
string $entryName,
165+
bool $expectedResult,
166+
string $expectedJson,
167+
?array $decodedJson
168+
): void {
111169
$this->configurationMock->expects($this->any())
112170
->method('getOutputPath')
113171
->willReturn(__DIR__.'/../fixtures/correct');
114172

173+
$this->jsonDecodeMock->expects($this->once())
174+
->method('decode')
175+
->with($expectedJson)
176+
->willReturn($decodedJson);
177+
115178
$this->assertEquals($expectedResult, $this->model->entryExists($entryName));
116179
}
117180

@@ -121,27 +184,42 @@ public function entryExistsDataProvider(): array
121184
[
122185
'entryName' => 'entrypoint1',
123186
'expectedResult' => true,
187+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
188+
'decodedJson' => self::DECODED_ENTRYPOINTS,
124189
],
125190
[
126191
'entryName' => 'entrypoint2',
127192
'expectedResult' => true,
193+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
194+
'decodedJson' => self::DECODED_ENTRYPOINTS,
128195
],
129196
[
130197
'entryName' => 'entrypoint3',
131198
'expectedResult' => false,
199+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
200+
'decodedJson' => self::DECODED_ENTRYPOINTS,
132201
],
133202
];
134203
}
135204

136205
/**
137206
* @dataProvider exceptionsInValidateEntryNameDataProvider
138207
*/
139-
public function testExceptionsInValidateEntryName(string $entryName, string $expectedExceptionMessageMatches): void
140-
{
208+
public function testExceptionsInValidateEntryName(
209+
string $entryName,
210+
string $expectedExceptionMessageMatches,
211+
string $expectedJson,
212+
?array $decodedJson
213+
): void {
141214
$this->configurationMock->expects($this->any())
142215
->method('getOutputPath')
143216
->willReturn(__DIR__.'/../fixtures/correct');
144217

218+
$this->jsonDecodeMock->expects($this->once())
219+
->method('decode')
220+
->with($expectedJson)
221+
->willReturn($decodedJson);
222+
145223
$this->expectException(EntrypointNotFoundException::class);
146224
$this->expectExceptionMessageMatches($expectedExceptionMessageMatches);
147225
$this->model->getJavaScriptFiles($entryName);
@@ -153,23 +231,42 @@ public function exceptionsInValidateEntryNameDataProvider(): array
153231
[
154232
'entryName' => 'entrypoint1.js',
155233
'expectedExceptionMessageMatches' => '/Could not find the entry "entrypoint1.js"\. Try "entrypoint1" instead \(without the extension\)\./',
234+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
235+
'decodedJson' => self::DECODED_ENTRYPOINTS,
156236
],
157237
[
158238
'entryName' => 'entrypoint3',
159239
'expectedExceptionMessageMatches' => '/Could not find the entry "entrypoint3" in ".*". Found: entrypoint1, entrypoint2\./',
240+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
241+
'decodedJson' => self::DECODED_ENTRYPOINTS,
242+
],
243+
[
244+
'entryName' => 'entrypoint4.js',
245+
'expectedExceptionMessageMatches' => '/Could not find the entry "entrypoint4.js" in ".*". Found: entrypoint1, entrypoint2\./',
246+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/correct/entrypoints.json'),
247+
'decodedJson' => self::DECODED_ENTRYPOINTS,
160248
],
161249
];
162250
}
163251

164252
/**
165253
* @dataProvider invalidArgumentExceptionInGetEntriesDataDataProvider
166254
*/
167-
public function testInvalidArgumentExceptionInGetEntriesData(string $entrypointFilePath, string $expectedExceptionMessageMatches): void
168-
{
255+
public function testInvalidArgumentExceptionInGetEntriesData(
256+
string $entrypointFilePath,
257+
string $expectedExceptionMessageMatches,
258+
string $expectedJson,
259+
?array $decodedJson
260+
): void {
169261
$this->configurationMock->expects($this->any())
170262
->method('getOutputPath')
171263
->willReturn(__DIR__.$entrypointFilePath);
172264

265+
$this->jsonDecodeMock->expects($this->any())
266+
->method('decode')
267+
->with($expectedJson)
268+
->willReturn($decodedJson);
269+
173270
$this->expectException(\InvalidArgumentException::class);
174271
$this->expectExceptionMessageMatches($expectedExceptionMessageMatches);
175272
$this->model->entryExists('some-entry-name');
@@ -181,14 +278,62 @@ public function invalidArgumentExceptionInGetEntriesDataDataProvider(): array
181278
[
182279
'entrypointFilePath' => '/../fixtures/bad_json',
183280
'expectedExceptionMessageMatches' => '/There was a problem JSON decoding the ".*\/fixtures\/bad_json\/entrypoints.json" file/',
281+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/bad_json/entrypoints.json'),
282+
'decodedJson' => null,
184283
],
185284
[
186285
'entrypointFilePath' => '/../fixtures/no_entrypoint_key',
187286
'expectedExceptionMessageMatches' => '/Could not find an "entrypoints" key in the ".*\/fixtures\/no_entrypoint_key\/entrypoints.json" file/',
287+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/no_entrypoint_key/entrypoints.json'),
288+
'decodedJson' => ['entrypoint' => []],
188289
],
189290
[
190291
'entrypointFilePath' => '/../fixtures/no_file',
191292
'expectedExceptionMessageMatches' => '/Could not find the entrypoints file from Webpack: the file ".*\/fixtures\/no_file\/entrypoints.json" does not exist\./',
293+
'expectedJson' => '',
294+
'decodedJson' => null,
295+
],
296+
[
297+
'entrypointFilePath' => '/../fixtures/bad_json',
298+
'expectedExceptionMessageMatches' => '/There was a problem JSON decoding the ".*" file/',
299+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/bad_json/entrypoints.json'),
300+
'decodedJson' => null,
301+
],
302+
];
303+
}
304+
305+
/**
306+
* @dataProvider jsonDecoderThrowsExceptionDataProvider
307+
*/
308+
public function testJsonDecoderThrowsException(
309+
string $entrypointFilePath,
310+
string $expectedExceptionMessageMatches,
311+
string $expectedJson
312+
): void {
313+
$this->configurationMock->expects($this->any())
314+
->method('getOutputPath')
315+
->willReturn(__DIR__.$entrypointFilePath);
316+
317+
$exception = new UnexpectedValueException('UnexpectedValueException message');
318+
319+
$this->jsonDecodeMock->expects($this->any())
320+
->method('decode')
321+
->with($expectedJson)
322+
->willThrowException($exception);
323+
324+
$this->expectException(\InvalidArgumentException::class);
325+
$this->expectExceptionMessageMatches($expectedExceptionMessageMatches);
326+
327+
$this->model->entryExists('some-entry-name');
328+
}
329+
330+
public function jsonDecoderThrowsExceptionDataProvider(): array
331+
{
332+
return [
333+
[
334+
'entrypointFilePath' => '/../fixtures/bad_json',
335+
'expectedExceptionMessageMatches' => '/There was a problem JSON decoding the ".*" file/',
336+
'expectedJson' => file_get_contents(__DIR__.'/../fixtures/bad_json/entrypoints.json'),
192337
],
193338
];
194339
}
Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
11
{
2-
"entrypoint": {
3-
"entrypoint1": {
4-
"js": [
5-
"/some/path/to/jsFile.js",
6-
"/another/path/to/js/file.js",
7-
"/build/app.js"
8-
]
9-
},
10-
"entrypoint2": {
11-
"js": [
12-
"/some/path/to/another/js/file.js"
13-
],
14-
"css": [
15-
"/some/path/to/js/file.css"
16-
]
17-
}
18-
}
2+
"entrypoint": {}
193
}

0 commit comments

Comments
 (0)