10000 Fake test double for WindowManager::Class: (#422) · arifhossen-dev/Native-laravel@3e0c562 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3e0c562

Browse files
authored
Fake test double for WindowManager::Class: (NativePHP#422)
- Usage of (relatively lenient) WindowManagerContract::class in Laravel container - Implement WindowManagerFake::class with several testing assertions and helper methods - Laravel-style facade Window::fake() method - Tests
1 parent c29bd0d commit 3e0c562

File tree

6 files changed

+278
-2
lines changed

6 files changed

+278
-2
lines changed

src/Contracts/WindowManager.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Native\Laravel\Contracts;
4+
5+
use Native\Laravel\Windows\Window;
6+
7+
interface WindowManager
8+
{
9+
public function open(string $id = 'main');
10+
11+
public function close($id = null);
12+
13+
public function hide($id = null);
14+
15+
public function current(): Window;
16+
17+
/**
18+
* @return array<int, Window>
19+
*/
20+
public function all(): array;
21+
22+
public function get(string $id): Window;
23+
}

src/Facades/Window.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Native\Laravel\Facades;
44

55
use Illuminate\Support\Facades\Facade;
6+
use Native\Laravel\Contracts\WindowManager as WindowManagerContract;
7+
use Native\Laravel\Fakes\WindowManagerFake;
68

79
/**
810
* @method static \Native\Laravel\Windows\PendingOpenWindow open(string $id = 'main')
@@ -18,8 +20,15 @@
1820
*/
1921
class Window extends Facade
2022
{
23+
public static function fake()
24+
{
25+
return tap(new WindowManagerFake, function ($fake) {
26+
static::swap($fake);
27+
});
28+
}
29+
2130
protected static function getFacadeAccessor()
2231
{
23-
return \Native\Laravel\Windows\WindowManager::class;
32+
return WindowManagerContract::class;
2433
}
2534
}

src/Fakes/WindowManagerFake.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
namespace Native\Laravel\Fakes;
4+
5+
use Illuminate\Support\Arr;
6+
use Native\Laravel\Contracts\WindowManager as WindowManagerContract;
7+
use Native\Laravel\Windows\Window;
8+
use PHPUnit\Framework\Assert as PHPUnit;
9+
use RuntimeException;
10+
11+
class WindowManagerFake implements WindowManagerContract
12+
{
13+
public array $opened = [];
14+
15+
public array $closed = [];
16+
17+
public array $hidden = [];
18+
19+
public array $forcedWindowReturnValues = [];
20+
21+
/**
22+
* @param array<int, Window> $windows
23+
*/
24+
public function alwaysReturnWindows(array $windows): self
25+
{
26+
$this->forcedWindowReturnValues = $windows;
27+
28+
return $this;
29+
}
30+
31+
public function open(string $id = 'main')
32+
{
33+
$this->opened[] = $id;
34+
}
35+
36+
public function close($id = null)
37+
{
38+
$this->closed[] = $id;
39+
}
40+
41+
public function hide($id = null)
42+
{
43+
$this->hidden[] = $id;
44+
}
45+
46+
public function current(): Window
47+
{
48+
$this->ensureForceReturnWindowsProvided();
49+
50+
return $this->forcedWindowReturnValues[array_rand($this->forcedWindowReturnValues)];
51+
}
52+
53+
/**
54+
* @return array<int, Window>
55+
*/
56+
public function all(): array
57+
{
58+
$this->ensureForceReturnWindowsProvided();
59+
60+
return $this->forcedWindowReturnValues;
61+
}
62+
63+
public function get(string $id): Window
64+
{
65+
$this->ensureForceReturnWindowsProvided();
66+
67+
$matchingWindows = array_filter($this->forcedWindowReturnValues, fn (Window $window) => $window->getId() === $id);
68+
69+
PHPUnit::assertNotEmpty($matchingWindows);
70+
PHPUnit::assertCount(1, $matchingWindows);
71+
72+
return Arr::first($matchingWindows);
73+
}
74+
75+
public function assertOpened(string $id): void
76+
{
77+
PHPUnit::assertContains($id, $this->opened);
78+
}
79+
80+
public function assertClosed(?string $id): void
81+
{
82+
PHPUnit::assertContains($id, $this->closed);
83+
}
84+
85+
public function assertHidden(?string $id): void
86+
{
87+
PHPUnit::assertContains($id, $this->hidden);
88+
}
89+
90+
private function ensureForceReturnWindowsProvided(): void
91+
{
92+
PHPUnit::assertNotEmpty($this->forcedWindowReturnValues);
93+
}
94+
}

src/NativeServiceProvider.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Native\Laravel;
44

55
use Illuminate\Console\Application;
6+
use Illuminate\Foundation\Application as Foundation;
67
use Illuminate\Support\Arr;
78
use Illuminate\Support\Facades\Artisan;
89
use Illuminate\Support\Facades\DB;
@@ -12,9 +13,11 @@
1213
use Native\Laravel\Commands\MigrateCommand;
1314
use Native\Laravel\Commands\MinifyApplicationCommand;
1415
use Native\Laravel\Commands\SeedDatabaseCommand;
16+
use Native\Laravel\Contracts\WindowManager as WindowManagerContract;
1517
use Native\Laravel\Events\EventWatcher;
1618
use Native\Laravel\Exceptions\Handler;
1719
use Native\Laravel\Logging\LogWatcher;
20+
use Native\Laravel\Windows\WindowManager as WindowManagerImplementation;
1821
use Spatie\LaravelPackageTools\Package;
1922
use Spatie\LaravelPackageTools\PackageServiceProvider;
2023

@@ -47,6 +50,10 @@ public function packageRegistered()
4750
return new MigrateCommand($app['migrator'], $app['events']);
4851
});
4952

53+
$this->app->bind(WindowManagerContract::class, function (Foundation $app) {
54+
return $app->make(WindowManagerImplementation::class);
55+
});
56+
5057
if (config('nativephp-internal.running')) {
5158
$this->app->singleton(
5259
\Illuminate\Contracts\Debug\ExceptionHandler::class,

src/Windows/WindowManager.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
use Native\Laravel\Client\Client;
66
use Native\Laravel\Concerns\DetectsWindowId;
7+
use Native\Laravel\Contracts\WindowManager as WindowManagerContract;
78

8-
class WindowManager
9+
class WindowManager implements WindowManagerContract
910
{
1011
use DetectsWindowId;
1112

tests/Fakes/FakeWindowManagerTest.php

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
3+
use Native\Laravel\Contracts\WindowManager as WindowManagerContract;
4+
use Native\Laravel\Facades\Window;
97AE 5+
use Native\Laravel\Fakes\WindowManagerFake;
6+
use Native\Laravel\Windows\Window as WindowClass;
7+
use PHPUnit\Framework\AssertionFailedError;
8+
9+
use function Pest\Laravel\swap;
10+
11+
it('swaps implementations using facade', function () {
12+
Window::fake();
13+
14+
expect(app(WindowManagerContract::class))->toBeInstanceOf(WindowManagerFake::class);
15+
});
16+
17+
it('asserts that a window was opened', function () {
18+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
19+
20+
app(WindowManagerContract::class)->open('main');
21+
app(WindowManagerContract::class)->open('secondary');
22+
23+
$fake->assertOpened('main');
24+
$fake->assertOpened('secondary');
25+
26+
try {
27+
$fake->assertOpened('tertiary');
28+
} catch (AssertionFailedError) {
29+
expect(true)->toBeTrue();
30+
31+
return;
32+
}
33+
34+
$this->fail('Expected assertion to fail');
35+
});
36+
37+
it('asserts that a window was closed', function () {
38+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
39+
40+
app(WindowManagerContract::class)->close('main');
41+
app(WindowManagerContract::class)->close('secondary');
42+
43+
$fake->assertClosed('main');
44+
$fake->assertClosed('secondary');
45+
46+
try {
47+
$fake->assertClosed('tertiary');
48+
} catch (AssertionFailedError) {
49+
expect(true)->toBeTrue();
50+
51+
return;
52+
}
53+
54+
$this->fail('Expected assertion to fail');
55+
});
56+
57+
it('asserts that a window was hidden', function () {
58+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
59+
60+
app(WindowManagerContract::class)->hide('main');
61+
app(WindowManagerContract::class)->hide('secondary');
62+
63+
$fake->assertHidden('main');
64+
$fake->assertHidden('secondary');
65+
66+
try {
67+
$fake->assertHidden('tertiary');
68+
} catch (AssertionFailedError) {
69+
expect(true)->toBeTrue();
70+
71+
return;
72+
}
73+
74+
$this->fail('Expected assertion to fail');
75+
});
76+
77+
it('forces the return value of current window', function () {
78+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
79+
80+
$fake->alwaysReturnWindows($windows = [
81+
new WindowClass('testA'),
82+
new WindowClass('testB'),
83+
]);
84+
85+
expect($windows)->toContain(app(WindowManagerContract::class)->current());
86+
});
87+
88+
it('forces the return value of all windows', function () {
89+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
90+
91+
$fake->alwaysReturnWindows($windows = [
92+
new WindowClass('testA'),
93+
new WindowClass('testB'),
94+
]);
95+
96+
expect(app(WindowManagerContract::class)->all())->toBe($windows);
97+
});
98+
99+
it('forces the return value of a specific window', function () {
100+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
101+
102+
$fake->alwaysReturnWindows($windows = [
103+
new WindowClass('testA'),
104+
new WindowClass('testB'),
105+
]);
106+
107+
expect(app(WindowManagerContract::class)->get('testA'))->toBe($windows[0]);
108+
expect(app(WindowManagerContract::class)->get('testB'))->toBe($windows[1]);
109+
});
110+
111+
test('that the get method throws an exception if multiple matching window ids exist', function () {
112+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
113+
114+
$fake->alwaysReturnWindows($windows = [
115+
new WindowClass('testA'),
116+
new WindowClass('testA'),
117+
]);
118+
119+
app(WindowManagerContract::class)->get('testA');
120+
})->throws(AssertionFailedError::class);
121+
122+
test('that the get method throws an exception if no matching window id exists', function () {
123+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
124+
125+
$fake->alwaysReturnWindows($windows = [
126+
new WindowClass('testA'),
127+
]);
128+
129+
app(WindowManagerContract::class)->get('testB');
130+
})->throws(AssertionFailedError::class);
131+
132+
test('that the current method throws an exception if no forced window return values are provided', function () {
133+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
134+
135+
app(WindowManagerContract::class)->current();
136+
})->throws(AssertionFailedError::class);
137+
138+
test('that the all method throws an exception if no forced window return values are provided', function () {
139+
swap(WindowManagerContract::class, $fake = new WindowManagerFake);
140+
141+
app(WindowManagerContract::class)->all();
142+
})->throws(AssertionFailedError::class);

0 commit comments

Comments
 (0)
0