8000 Global shortcut test double: (#436) · NativePHP/laravel@7f4994d · GitHub
[go: up one dir, main page]

Skip to content

Commit 7f4994d

Browse files
authored
Global shortcut test double: (#436)
- GlobalShortcut::class now implements Contracts\GlobalShortcut::class interface - Facades\GlobalShortcut::fake() swaps implementations with a test double concrete - Implement new binding in NativeServiceProvider::clas - Implement GlobalShortcutFake::class with assertion helpers - Test that GlobalShortcutFake::class assertions work
1 parent 49dee31 commit 7f4994d

File tree

6 files changed

+256
-2
lines changed

6 files changed

+256
-2
lines changed

src/Contracts/GlobalShortcut.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Native\Laravel\Contracts;
4+
5+
interface GlobalShortcut
6+
{
7+
public function key(string $key): self;
8+
9+
public function event(string $event): self;
10+
11+
public function register(): void;
12+
13+
public function unregister(): void;
14+
}

src/Facades/GlobalShortcut.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\GlobalShortcut as GlobalShortcutContract;
7+
use Native\Laravel\Fakes\GlobalShortcutFake;
68

79
/**
810
* @method static \Native\Laravel\GlobalShortcut key(string $key)
@@ -12,8 +14,15 @@
1214
*/
1315
class GlobalShortcut extends Facade
1416
{
17+
public static function fake()
18+
{
19+
return tap(static::getFacadeApplication()->make(GlobalShortcutFake::class), function ($fake) {
20+
static::swap($fake);
21+
});
22+
}
23+
1524
protected static function getFacadeAccessor()
1625
{
17-
return \Native\Laravel\GlobalShortcut::class;
26+
return GlobalShortcutContract::class;
1827
}
1928
}

src/Fakes/GlobalShortcutFake.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
namespace Native\Laravel\Fakes;
4+
5+
use Closure;
6+
use Native\Laravel\Contracts\GlobalShortcut as GlobalShortcutContract;
7+
use PHPUnit\Framework\Assert as PHPUnit;
8+
9+
class GlobalShortcutFake implements GlobalShortcutContract
10+
{
11+
/**
12+
* @var array<int, string>
13+
*/
14+
public array $keys = [];
15+
16+
/**
17+
* @var array<int, string>
18+
*/
19+
public array $events = [];
20+
21+
public int $registeredCount = 0;
22+
23+
public int $unregisteredCount = 0;
24+
25+
public function key(string $key): self
26+
{
27+
$this->keys[] = $key;
28+
29+
return $this;
30+
}
31+
32+
public< A3E2 /span> function event(string $event): self
33+
{
34+
$this->events[] = $event;
35+
36+
return $this;
37+
}
38+
39+
public function register(): void
40+
{
41+
$this->registeredCount++;
42+
}
43+
44+
public function unregister(): void
45+
{
46+
$this->unregisteredCount++;
47+
}
48+
49+
/**
50+
* @param string|Closure(string): bool $key
51+
*/
52+
public function assertKey(string|Closure $key): void
53+
{
54+
if (is_callable($key) === false) {
55+
PHPUnit::assertContains($key, $this->keys);
56+
57+
return;
58+
}
59+
60+
$hit = empty(
61+
array_filter(
62+
$this->keys,
63+
fn (string $keyIteration) => $key($keyIteration) === true
64+
)
65+
) === false;
66+
67+
PHPUnit::assertTrue($hit);
68+
}
69+
70+
/**
71+
* @param string|Closure(string): bool $event
72+
*/
73+
public function assertEvent(string|Closure $event): void
74+
{
75+
if (is_callable($event) === false) {
76+
PHPUnit::assertContains($event, $this->events);
77+
78+
return;
79+
}
80+
81+
$hit = empty(
82+
array_filter(
83+
$this->events,
84+
fn (string $eventIteration) => $event($eventIteration) === true
85+
)
86+
) === false;
87+
88+
PHPUnit::assertTrue($hit);
89+
}
90+
91+
public function assertRegisteredCount(int $count): void
92+
{
93+
PHPUnit::assertSame($count, $this->registeredCount);
94+
}
95+
96+
public function assertUnregisteredCount(int $count): void
97+
{
98+
PHPUnit::assertSame($count, $this->unregisteredCount);
99+
}
100+
}

src/GlobalShortcut.php

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

55
use Native\Laravel\Client\Client;
6+
use Native\Laravel\Contracts\GlobalShortcut as GlobalShortcutContract;
67

7-
class GlobalShortcut
8+
class GlobalShortcut implements GlobalShortcutContract
89
{
910
protected string $key;
1011

src/NativeServiceProvider.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
use Native\Laravel\Commands\MinifyApplicationCommand;
1616
use Native\Laravel\Commands\SeedDatabaseCommand;
1717
use Native\Laravel\Contracts\ChildProcess as ChildProcessContract;
18+
use Native\Laravel\Contracts\GlobalShortcut as GlobalShortcutContract;
1819
use Native\Laravel\Contracts\WindowManager as WindowManagerContract;
1920
use Native\Laravel\Events\EventWatcher;
2021
use Native\Laravel\Exceptions\Handler;
22+
use Native\Laravel\GlobalShortcut as GlobalShortcutImplementation;
2123
use Native\Laravel\Logging\LogWatcher;
2224
use Native\Laravel\Windows\WindowManager as WindowManagerImplementation;
2325
use Spatie\LaravelPackageTools\Package;
@@ -60,6 +62,10 @@ public function packageRegistered()
6062
return $app->make(ChildProcessImplementation::class);
6163
});
6264

65+
$this->app->bind(GlobalShortcutContract::class, function (Foundation $app) {
66+
return $app->make(GlobalShortcutImplementation::class);
67+
});
68+
6369
if (config('nativephp-internal.running')) {
6470
$this->app->singleton(
6571
\Illuminate\Contracts\Debug\ExceptionHandler::class,
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
use Native\Laravel\Facades\GlobalShortcut;
4+
use Native\Laravel\Contracts\GlobalShortcut as GlobalShortcutContract;
5+
use Native\Laravel\Fakes\GlobalShortcutFake;
6+
7+
use PHPUnit\Framework\AssertionFailedError;
8+
9+
use function Pest\Laravel\swap;
10+
11+
it('swaps implementations using facade', function () {
12+
GlobalShortcut::fake();
13+
14+
expect(app(GlobalShortcutContract::class))->toBeInstanceOf(GlobalShortcutFake::class);
15+
});
16+
17+
it('asserts key using string', function () {
18+
swap(GlobalShortcutContract::class, $fake = app(GlobalShortcutFake::class));
19+
20+
$fake->key('testA');
21+
$fake->key('testB');
22+
23+
$fake->assertKey('testA');
24+
$fake->assertKey('testB');
25+
26+
try {
27+
$fake->assertKey('testC');
28+
} catch (AssertionFailedError) {
29+
return;
30+
}
31+
32+
$this->fail('Expected assertion to fail');
33+
});
34+
35+
it('asserts key using callable', function () {
36+
swap(GlobalShortcutContract::class, $fake = app(GlobalShortcutFake::class));
37+
38+
$fake->key('testA');
39+
$fake->key('testB');
40+
41+
$fake->assertKey(fn (string $key) => $key === 'testA');
42+
$fake->assertKey(fn (string $key) => $key === 'testB');
43+
44+
try {
45+
$fake->assertKey(fn (string $key) => $key === 'testC');
46+
} catch (AssertionFailedError) {
47+
return;
48+
}
49+
50+
$this->fail('Expected assertion to fail');
51+
});
52+
53+
it('asserts event using string', function () {
54+
swap(GlobalShortcutContract::class, $fake = app(GlobalShortcutFake::class));
55+
56+
$fake->event('testA');
57+
$fake->event('testB');
58+
59+
$fake->assertEvent('testA');
60+
$fake->assertEvent('testB');
61+
62+
try {
63+
$fake->assertEvent('testC');
64+
} catch (AssertionFailedError) {
65+
return;
66+
}
67+
68+
$this->fail('Expected assertion to fail');
69+
});
70+
71+
it('asserts event using callable', function () {
72+
swap(GlobalShortcutContract::class, $fake = app(GlobalShortcutFake::class));
73+
74+
$fake->event('testA');
75+
$fake->event('testB');
76+
77+
$fake->assertEvent(fn (string $event) => $event === 'testA');
78+
$fake->assertEvent(fn (string $event) => $event === 'testB');
79+
80+
try {
81+
$fake->assertEvent(fn (string $event) => $event === 'testC');
82+
} catch (AssertionFailedError) {
83+
return;
84+
}
85+
86+
$this->fail('Expected assertion to fail');
87+
});
88+
89+
it('asserts registered count', function () {
90+
swap(GlobalShortcutContract::class, $fake = app(GlobalShortcutFake::class));
91+
92+
$fake->register();
93+
$fake->register();
94+
$fake->register();
95+
96+
$fake->assertRegisteredCount(3);
97+
98+
try {
99+
$fake->assertRegisteredCount(2);
100+
} catch (AssertionFailedError) {
101+
return;
102+
}
103+
104+
$this->fail('Expected assertion to fail');
105+
});
106+
107+
it('asserts unregistered count', function () {
108+
swap(GlobalShortcutContract::class, $fake = app(GlobalShortcutFake::class));
109+
110+
$fake->unregister();
111+
$fake->unregister();
112+
$fake->unregister();
113+
114+
$fake->assertUnregisteredCount(3);
115+
116+
try {
117+
$fake->assertUnregisteredCount(2);
118+
} catch (AssertionFailedError) {
119+
return;
120+
}
121+
122+
$this->fail('Expected assertion to fail');
123+
});
124+

0 commit comments

Comments
 (0)
0