Skip to content

Commit 2d83ff9

Browse files
Migrate to PHPUnit (#168)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 84db385 commit 2d83ff9

23 files changed

+4820
-4271
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"pestphp/pest-plugin-arch": "^2.0|^3.0",
4242
"pestphp/pest-plugin-laravel": "^2.0|^3.0",
4343
"phpstan/phpstan": "^1.0",
44+
"phpunit/phpunit": "^10.0|^11.0",
4445
"ramsey/uuid": "^4.0",
4546
"spatie/laravel-ignition": "^2.0",
4647
"symfony/mailer": "^6.0|^7.0",

tests/Feature/ApplicationTest.php

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
<?php
22

3+
namespace Tests\Feature;
4+
35
use Illuminate\Foundation\Application;
6+
use Illuminate\Support\Env;
47
use Illuminate\Support\Facades\Artisan;
8+
use Tests\TestCase;
59

6-
it('can cache the config', function () {
7-
$basePath = app()->basePath();
10+
use function expect;
11+
use function version_compare;
812

9-
$result = Artisan::call('config:cache');
10-
expect($result)->toBe(0);
13+
class ApplicationTest extends TestCase
14+
{
15+
public function test_it_can_cache_the_config()
16+
{
17+
$this->markTestSkippedWhen(version_compare(Application::VERSION, '11.0.0', '<'), <<<'MESSAGE'
18+
Due to Laravel 11's new project structure, we only run this on Laravel 11+.
1119
12-
app()->setBasePath($basePath);
20+
The intention of this test is to ensure that we don't put any unseralizable values in the config.
1321
14-
$result = Artisan::call('config:clear');
15-
expect($result)->toBe(0);
16-
})->skip(version_compare(Application::VERSION, '11.0.0', '<'), <<<'MESSAGE'
17-
Due to Laravel 11's new project structure, we only run this on Laravel 11+.
22+
Running against 11+ should still give a good amount of assurance across other framework versions.
23+
MESSAGE);
24+
Env::getRepository()->set('APP_CONFIG_CACHE', $this->app->getCachedConfigPath());
1825

19-
The intention of this test is to ensure that we don't put any unseralizable values in the config.
26+
$result = Artisan::call('config:cache');
27+
expect($result)->toBe(0);
2028

21-
Running against 11+ should still give a good amount of assurance across other framework versions.
22-
MESSAGE);
29+
$result = Artisan::call('config:clear');
30+
expect($result)->toBe(0);
31+
}
32+
}
Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,44 @@
11
<?php
22

3-
use Tests\FakeIngest;
3+
namespace Tests\Feature\Console;
44

5-
use function Pest\Laravel\artisan;
5+
use RuntimeException;
6+
use Tests\FakeIngest;
7+
use Tests\TestCase;
68

7-
it('fails when nightwatch is disabled', function () {
8-
nightwatch()->config['enabled'] = false;
9+
class StatusCommandTest extends TestCase
10+
{
11+
public function test_it_fails_when_nightwatch_is_disabled()
12+
{
13+
$this->core->config['enabled'] = false;
914

10-
artisan('nightwatch:status')
11-
->expectsOutputToContain('Nightwatch is disabled')
12-
->assertExitCode(1);
13-
});
15+
$this->artisan('nightwatch:status')
16+
->expectsOutputToContain('Nightwatch is disabled')
17+
->assertExitCode(1)
18+
->run();
19+
}
1420

15-
it('fails when ingest throws an exception while pinging', function () {
16-
fakeIngest(new class extends FakeIngest
21+
public function test_it_fails_when_ingest_throws_an_exception_while_pinging()
1722
{
18-
public function ping(): void
23+
$this->fakeIngest(new class extends FakeIngest
1924
{
20-
throw new RuntimeException('Whoops!');
21-
}
22-
});
23-
artisan('nightwatch:status')
24-
->expectsOutputToContain('Whoops!')
25-
->assertExitCode(1);
26-
});
27-
28-
it('can ping', function () {
29-
fakeIngest();
30-
31-
artisan('nightwatch:status')
32-
->expectsOutputToContain('The Nightwatch agent is running and accepting connections')
33-
->assertExitCode(0);
34-
});
25+
public function ping(): void
26+
{
27+
throw new RuntimeException('Whoops!');
28+
}
29+
});
30+
31+
$this->artisan('nightwatch:status')
32+
->expectsOutputToContain('Whoops!')
33+
->assertExitCode(1);
34+
}
35+
36+
public function test_it_can_ping()
37+
{
38+
$this->fakeIngest();
39+
40+
$this->artisan('nightwatch:status')
41+
->expectsOutputToContain('The Nightwatch agent is running and accepting connections')
42+
->assertExitCode(0);
43+
}
44+
}
Lines changed: 80 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,87 @@
11
<?php
22

3+
namespace Tests\Feature\Facades;
4+
35
use Illuminate\Support\Facades\Facade;
46
use Illuminate\Support\Facades\Log;
57
use Laravel\Nightwatch\Core;
68
use Laravel\Nightwatch\Facades\Nightwatch;
9+
use ReflectionClass;
10+
use RuntimeException;
11+
use Tests\TestCase;
12+
use Throwable;
13+
14+
use function expect;
15+
16+
class NightwatchTest extends TestCase
17+
{
18+
public function test_it_resolves_to_bound_singleton_instance_of_the_core_class()
19+
{
20+
expect(Nightwatch::getFacadeRoot())->toBeInstanceOf(Core::class);
21+
22+
expect(Nightwatch::getFacadeRoot())->toBe($this->app[Core::class]);
23+
24+
Facade::clearResolvedInstances();
25+
expect(Nightwatch::getFacadeRoot())->toBe($this->app[Core::class]);
26+
}
27+
28+
public function test_it_silently_discards_unrecoverable_exceptions_by_default()
29+
{
30+
(new ReflectionClass(Nightwatch::class))->getProperty('handleUnrecoverableExceptionsUsing')->setValue(null);
31+
$calls = 0;
32+
Log::listen(function () use (&$calls) {
33+
$calls++;
34+
});
35+
36+
Nightwatch::unrecoverableExceptionOccurred(new RuntimeException('Whoops!'));
37+
38+
expect($calls)->toBe(0);
39+
}
40+
41+
public function test_it_can_register_a_callback_to_handle_unrecoverable_exceptions()
42+
{
43+
$handled = [];
44+
Nightwatch::handleUnrecoverableExceptionsUsing(function (Throwable $e) use (&$handled) {
45+
$handled[] = $e;
46+
});
47+
48+
Nightwatch::unrecoverableExceptionOccurred($first = new RuntimeException('Whoops!'));
49+
Nightwatch::unrecoverableExceptionOccurred($second = new RuntimeException('Whoops!'));
50+
51+
expect($handled)->toBe([
52+
$first,
53+
$second,
54+
]);
55+
}
56+
57+
public function test_it_handles_unrecoverable_exceptions_statelessly()
58+
{
59+
$this->app->forgetInstance(Core::class);
60+
$resolved = false;
61+
Nightwatch::resolved(function () use (&$resolved) {
62+
$resolved = true;
63+
});
64+
65+
$handled = [];
66+
Nightwatch::handleUnrecoverableExceptionsUsing(function (Throwable $e) use (&$handled) {
67+
$handled[] = $e;
68+
});
69+
Nightwatch::unrecoverableExceptionOccurred($first = new RuntimeException('Whoops!'));
70+
71+
expect($resolved)->toBeFalse();
72+
expect($handled)->toHaveCount(1);
73+
expect($this->app->resolved(Core::class))->toBeFalse();
74+
}
75+
76+
public function test_it_silences_exceptions_thrown_while_handling_exceptions()
77+
{
78+
Nightwatch::handleUnrecoverableExceptionsUsing(function (): object {
79+
// Should return an object. Returning an int to cause an exception.
80+
return 5;
81+
});
82+
83+
Nightwatch::unrecoverableExceptionOccurred(new RuntimeException('Whoops!'));
784

8-
it('resolves to bound singleton instance of the Core class', function () {
9-
expect(Nightwatch::getFacadeRoot())->toBeInstanceOf(Core::class);
10-
11-
expect(Nightwatch::getFacadeRoot())->toBe(app(Core::class));
12-
13-
Facade::clearResolvedInstances();
14-
expect(Nightwatch::getFacadeRoot())->toBe(app(Core::class));
15-
});
16-
17-
it('silently discards unrecoverable exceptions by default', function () {
18-
(new ReflectionClass(Nightwatch::class))->getProperty('handleUnrecoverableExceptionsUsing')->setValue(null);
19-
$calls = 0;
20-
Log::listen(function () use (&$calls) {
21-
$calls++;
22-
});
23-
24-
Nightwatch::unrecoverableExceptionOccurred(new RuntimeException('Whoops!'));
25-
26-
expect($calls)->toBe(0);
27-
});
28-
29-
it('can register a callback to handle unrecoverable exceptions', function () {
30-
$handled = [];
31-
Nightwatch::handleUnrecoverableExceptionsUsing(function (Throwable $e) use (&$handled) {
32-
$handled[] = $e;
33-
});
34-
35-
Nightwatch::unrecoverableExceptionOccurred($first = new RuntimeException('Whoops!'));
36-
Nightwatch::unrecoverableExceptionOccurred($second = new RuntimeException('Whoops!'));
37-
38-
expect($handled)->toBe([
39-
$first,
40-
$second,
41-
]);
42-
});
43-
44-
it('handles unrecoverable exceptions statelessly', function () {
45-
app()->forgetInstance(Core::class);
46-
$resolved = false;
47-
Nightwatch::resolved(function () use (&$resolved) {
48-
$resolved = true;
49-
});
50-
51-
$handled = [];
52-
Nightwatch::handleUnrecoverableExceptionsUsing(function (Throwable $e) use (&$handled) {
53-
$handled[] = $e;
54-
});
55-
Nightwatch::unrecoverableExceptionOccurred($first = new RuntimeException('Whoops!'));
56-
57-
expect($resolved)->toBeFalse();
58-
expect($handled)->toHaveCount(1);
59-
expect(app()->resolved(Core::class))->toBeFalse();
60-
});
61-
62-
it('silences exceptions thrown while handling exceptions', function () {
63-
Nightwatch::handleUnrecoverableExceptionsUsing(function (): object {
64-
// Should return an object. Returning an int to cause an exception.
65-
return 5;
66-
});
67-
68-
Nightwatch::unrecoverableExceptionOccurred(new RuntimeException('Whoops!'));
69-
});
85+
$this->assertTrue(true);
86+
}
87+
}

tests/Feature/IngestTest.php

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,39 @@
11
<?php
22

3+
namespace Tests\Feature;
4+
35
use Illuminate\Support\Facades\Route;
46
use Laravel\Nightwatch\Facades\Nightwatch;
7+
use RuntimeException;
8+
use Tests\TestCase;
9+
10+
use function expect;
11+
12+
class IngestTest extends TestCase
13+
{
14+
protected function setUp(): void
15+
{
16+
$this->forceRequestExecutionState();
17+
18+
parent::setUp();
19+
}
20+
21+
public function test_it_handles_ingesting_zero_records()
22+
{
23+
$exceptions = [];
24+
Nightwatch::handleUnrecoverableExceptionsUsing(function ($e) use (&$exceptions) {
25+
$exceptions[] = $e;
26+
});
27+
$ingest = $this->fakeIngest();
28+
$this->core->sensor->requestSensor = fn () => throw new RuntimeException('Whoops request!');
29+
$this->core->sensor->exceptionSensor = fn () => throw new RuntimeException('Whoops exception!');
30+
Route::get('/users', fn () => []);
31+
32+
$response = $this->get('/users');
533

6-
use function Pest\Laravel\get;
7-
8-
beforeAll(function () {
9-
forceRequestExecutionState();
10-
});
11-
12-
it('handles ingesting zero records', function () {
13-
$exceptions = [];
14-
Nightwatch::handleUnrecoverableExceptionsUsing(function ($e) use (&$exceptions) {
15-
$exceptions[] = $e;
16-
});
17-
$ingest = fakeIngest();
18-
nightwatch()->sensor->requestSensor = fn () => throw new RuntimeException('Whoops request!');
19-
nightwatch()->sensor->exceptionSensor = fn () => throw new RuntimeException('Whoops exception!');
20-
Route::get('/users', fn () => []);
21-
22-
$response = get('/users');
23-
24-
$response->assertOk();
25-
expect($exceptions)->toHaveCount(1);
26-
expect($exceptions[0]->getMessage())->toBe('Whoops exception!');
27-
expect($ingest->latestWriteAsString())->toBe('[]');
28-
});
34+
$response->assertOk();
35+
expect($exceptions)->toHaveCount(1);
36+
expect($exceptions[0]->getMessage())->toBe('Whoops exception!');
37+
expect($ingest->latestWriteAsString())->toBe('[]');
38+
}
39+
}

0 commit comments

Comments
 (0)