Skip to content

Commit 1fc9641

Browse files
authored
WatcherFactory: Merge options recursively to preserve nested values. (#115)
* WatcherFactory: Merge options recursively to preserve nested values. Previously, the following configuration would result in a file mask of `null`, because the entire `watch` item would be overridden. ```yml watch: directories: - ./public_html/wp-content/mu-plugins/ - ./public_html/wp-content/plugins/camptix/ - ./public_html/wp-content/plugins/wordcamp-organizer-reminders/ - ./public_html/wp-content/plugins/wordcamp-remote-css/ - ./public_html/wp-content/plugins/wordcamp-speaker-feedback/ notifications: passingTests: false failingTests: false ``` Now users can selective set a nested option like `watch.fileMask`, without having to set everything inside `watch`. * get tests working * exempt directories from merge
1 parent 073ff1b commit 1fc9641

File tree

2 files changed

+70
-8
lines changed

2 files changed

+70
-8
lines changed

src/WatcherFactory.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ public static function create(array $options = []): array
3030
return [$watcher, $options];
3131
}
3232

33-
protected static function mergeWithDefaultOptions(array $options): array
33+
public static function getDefaultOptions(): array
3434
{
35-
$options = array_merge([
36-
35+
return [
3736
'watch' => [
3837
'directories' => [
3938
'app',
@@ -47,16 +46,29 @@ protected static function mergeWithDefaultOptions(array $options): array
4746
'failingTests' => true,
4847
],
4948
'hideManual' => false,
50-
], $options);
49+
];
50+
}
51+
52+
protected static function mergeWithDefaultOptions(array $userOptions): array
53+
{
54+
// Merge all options with the defaults, so that there's always a complete set.
55+
$mergedOptions = array_replace_recursive(self::getDefaultOptions(), $userOptions);
56+
57+
// Exception to above: Allow directories to be overwritten entirely, because that's usually desired.
58+
if (isset($userOptions['watch']['directories'])) {
59+
$mergedOptions['watch']['directories'] = $userOptions['watch']['directories'];
60+
}
61+
62+
$mergedOptions['watch']['directories'] = array_unique($mergedOptions['watch']['directories']);
5163

52-
$options['watch']['directories'] = array_map(function ($directory) {
64+
$mergedOptions['watch']['directories'] = array_map(function ($directory) {
5365
return getcwd()."/{$directory}";
54-
}, $options['watch']['directories']);
66+
}, $mergedOptions['watch']['directories']);
5567

56-
$options['watch']['directories'] = array_filter($options['watch']['directories'], function ($directory) {
68+
$mergedOptions['watch']['directories'] = array_filter($mergedOptions['watch']['directories'], function ($directory) {
5769
return file_exists($directory);
5870
});
5971

60-
return $options;
72+
return $mergedOptions;
6173
}
6274
}

tests/WatcherFactoryTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace Spatie\PhpUnitWatcher\Test;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Spatie\PhpUnitWatcher\WatcherFactory;
7+
8+
class WatcherFactorTest extends TestCase
9+
{
10+
/** @test */
11+
public function it_can_be_instantiated()
12+
{
13+
$factory = new WatcherFactory();
14+
15+
$this->assertInstanceOf(WatcherFactory::class, $factory);
16+
}
17+
18+
/** @test */
19+
public function setting_notification_preserves_other_options()
20+
{
21+
$userOptions = [
22+
'notifications' => [
23+
'passingTests' => false,
24+
],
25+
];
26+
27+
$actualOptions = WatcherFactory::create($userOptions)[1];
28+
29+
$this->assertFalse($actualOptions['notifications']['passingTests']);
30+
$this->assertTrue($actualOptions['notifications']['failingTests']);
31+
$this->assertFalse($actualOptions['hideManual']);
32+
$this->assertSame('*.php', $actualOptions['watch']['fileMask']);
33+
}
34+
35+
/** @test */
36+
public function setting_directories_preserves_other_options()
37+
{
38+
$userOptions = [
39+
'watch' => [
40+
'directories' => ['lib', 'tests'],
41+
],
42+
];
43+
44+
$actualOptions = WatcherFactory::create($userOptions)[1];
45+
46+
$this->assertTrue($actualOptions['notifications']['failingTests']);
47+
$this->assertFalse($actualOptions['hideManual']);
48+
$this->assertSame('*.php', $actualOptions['watch']['fileMask']);
49+
}
50+
}

0 commit comments

Comments
 (0)