Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.x] Adds support for Pest #866

Merged
merged 17 commits into from
Sep 8, 2021
Merged
101 changes: 66 additions & 35 deletions src/Console/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class InstallCommand extends Command
*/
protected $signature = 'jetstream:install {stack : The development stack that should be installed}
{--teams : Indicates if team support should be installed}
{--pest : Indicate that Pest should be installed}
nunomaduro marked this conversation as resolved.
Show resolved Hide resolved
{--composer=global : Absolute path to the Composer binary which should be used to install packages}';

/**
Expand Down Expand Up @@ -70,11 +71,21 @@ public function handle()
}

// Tests...
copy(__DIR__.'/../../stubs/tests/AuthenticationTest.php', base_path('tests/Feature/AuthenticationTest.php'));
copy(__DIR__.'/../../stubs/tests/EmailVerificationTest.php', base_path('tests/Feature/EmailVerificationTest.php'));
copy(__DIR__.'/../../stubs/tests/PasswordConfirmationTest.php', base_path('tests/Feature/PasswordConfirmationTest.php'));
copy(__DIR__.'/../../stubs/tests/PasswordResetTest.php', base_path('tests/Feature/PasswordResetTest.php'));
copy(__DIR__.'/../../stubs/tests/RegistrationTest.php', base_path('tests/Feature/RegistrationTest.php'));
$stubs = $this->getTestStubsPath();

if ($this->option('pest')) {
$this->requireComposerPackages('pestphp/pest:^1.16', 'pestphp/pest-plugin-laravel:^1.1');

copy($stubs.'/Pest.php', base_path('tests/Pest.php'));
copy($stubs.'/ExampleTest.php', base_path('tests/Feature/ExampleTest.php'));
copy($stubs.'/ExampleUnitTest.php', base_path('tests/Unit/ExampleTest.php'));
}

copy($stubs.'/AuthenticationTest.php', base_path('tests/Feature/AuthenticationTest.php'));
copy($stubs.'/EmailVerificationTest.php', base_path('tests/Feature/EmailVerificationTest.php'));
copy($stubs.'/PasswordConfirmationTest.php', base_path('tests/Feature/PasswordConfirmationTest.php'));
copy($stubs.'/PasswordResetTest.php', base_path('tests/Feature/PasswordResetTest.php'));
copy($stubs.'/RegistrationTest.php', base_path('tests/Feature/RegistrationTest.php'));
}

/**
Expand Down Expand Up @@ -197,14 +208,16 @@ protected function installLivewireStack()
copy(__DIR__.'/../../stubs/livewire/resources/js/app.js', resource_path('js/app.js'));

// Tests...
copy(__DIR__.'/../../stubs/tests/livewire/ApiTokenPermissionsTest.php', base_path('tests/Feature/ApiTokenPermissionsTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/BrowserSessionsTest.php', base_path('tests/Feature/BrowserSessionsTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/CreateApiTokenTest.php', base_path('tests/Feature/CreateApiTokenTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/DeleteAccountTest.php', base_path('tests/Feature/DeleteAccountTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/DeleteApiTokenTest.php', base_path('tests/Feature/DeleteApiTokenTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/ProfileInformationTest.php', base_path('tests/Feature/ProfileInformationTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/TwoFactorAuthenticationSettingsTest.php', base_path('tests/Feature/TwoFactorAuthenticationSettingsTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/UpdatePasswordTest.php', base_path('tests/Feature/UpdatePasswordTest.php'));
$stubs = $this->getTestStubsPath();

copy($stubs.'/livewire/ApiTokenPermissionsTest.php', base_path('tests/Feature/ApiTokenPermissionsTest.php'));
copy($stubs.'/livewire/BrowserSessionsTest.php', base_path('tests/Feature/BrowserSessionsTest.php'));
copy($stubs.'/livewire/CreateApiTokenTest.php', base_path('tests/Feature/CreateApiTokenTest.php'));
copy($stubs.'/livewire/DeleteAccountTest.php', base_path('tests/Feature/DeleteAccountTest.php'));
copy($stubs.'/livewire/DeleteApiTokenTest.php', base_path('tests/Feature/DeleteApiTokenTest.php'));
copy($stubs.'/livewire/ProfileInformationTest.php', base_path('tests/Feature/ProfileInformationTest.php'));
copy($stubs.'/livewire/TwoFactorAuthenticationSettingsTest.php', base_path('tests/Feature/TwoFactorAuthenticationSettingsTest.php'));
copy($stubs.'/livewire/UpdatePasswordTest.php', base_path('tests/Feature/UpdatePasswordTest.php'));

// Teams...
if ($this->option('teams')) {
Expand All @@ -230,13 +243,15 @@ protected function installLivewireTeamStack()
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire/resources/views/teams', resource_path('views/teams'));

// Tests...
copy(__DIR__.'/../../stubs/tests/livewire/CreateTeamTest.php', base_path('tests/Feature/CreateTeamTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/DeleteTeamTest.php', base_path('tests/Feature/DeleteTeamTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/InviteTeamMemberTest.php', base_path('tests/Feature/InviteTeamMemberTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/LeaveTeamTest.php', base_path('tests/Feature/LeaveTeamTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/RemoveTeamMemberTest.php', base_path('tests/Feature/RemoveTeamMemberTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/UpdateTeamMemberRoleTest.php', base_path('tests/Feature/UpdateTeamMemberRoleTest.php'));
copy(__DIR__.'/../../stubs/tests/livewire/UpdateTeamNameTest.php', base_path('tests/Feature/UpdateTeamNameTest.php'));
$stubs = $this->getTestStubsPath();

copy($stubs.'/livewire/CreateTeamTest.php', base_path('tests/Feature/CreateTeamTest.php'));
copy($stubs.'/livewire/DeleteTeamTest.php', base_path('tests/Feature/DeleteTeamTest.php'));
copy($stubs.'/livewire/InviteTeamMemberTest.php', base_path('tests/Feature/InviteTeamMemberTest.php'));
copy($stubs.'/livewire/LeaveTeamTest.php', base_path('tests/Feature/LeaveTeamTest.php'));
copy($stubs.'/livewire/RemoveTeamMemberTest.php', base_path('tests/Feature/RemoveTeamMemberTest.php'));
copy($stubs.'/livewire/UpdateTeamMemberRoleTest.php', base_path('tests/Feature/UpdateTeamMemberRoleTest.php'));
copy($stubs.'/livewire/UpdateTeamNameTest.php', base_path('tests/Feature/UpdateTeamNameTest.php'));

$this->ensureApplicationIsTeamCompatible();
}
Expand Down Expand Up @@ -373,14 +388,16 @@ protected function installInertiaStack()
// static::flushNodeModules();

// Tests...
copy(__DIR__.'/../../stubs/tests/inertia/ApiTokenPermissionsTest.php', base_path('tests/Feature/ApiTokenPermissionsTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/BrowserSessionsTest.php', base_path('tests/Feature/BrowserSessionsTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/CreateApiTokenTest.php', base_path('tests/Feature/CreateApiTokenTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/DeleteAccountTest.php', base_path('tests/Feature/DeleteAccountTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/DeleteApiTokenTest.php', base_path('tests/Feature/DeleteApiTokenTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/ProfileInformationTest.php', base_path('tests/Feature/ProfileInformationTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/TwoFactorAuthenticationSettingsTest.php', base_path('tests/Feature/TwoFactorAuthenticationSettingsTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/UpdatePasswordTest.php', base_path('tests/Feature/UpdatePasswordTest.php'));
$stubs = $this->getTestStubsPath();

copy($stubs.'/inertia/ApiTokenPermissionsTest.php', base_path('tests/Feature/ApiTokenPermissionsTest.php'));
copy($stubs.'/inertia/BrowserSessionsTest.php', base_path('tests/Feature/BrowserSessionsTest.php'));
copy($stubs.'/inertia/CreateApiTokenTest.php', base_path('tests/Feature/CreateApiTokenTest.php'));
copy($stubs.'/inertia/DeleteAccountTest.php', base_path('tests/Feature/DeleteAccountTest.php'));
copy($stubs.'/inertia/DeleteApiTokenTest.php', base_path('tests/Feature/DeleteApiTokenTest.php'));
copy($stubs.'/inertia/ProfileInformationTest.php', base_path('tests/Feature/ProfileInformationTest.php'));
copy($stubs.'/inertia/TwoFactorAuthenticationSettingsTest.php', base_path('tests/Feature/TwoFactorAuthenticationSettingsTest.php'));
copy($stubs.'/inertia/UpdatePasswordTest.php', base_path('tests/Feature/UpdatePasswordTest.php'));

// Teams...
if ($this->option('teams')) {
Expand All @@ -406,13 +423,15 @@ protected function installInertiaTeamStack()
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia/resources/js/Pages/Teams', resource_path('js/Pages/Teams'));

// Tests...
copy(__DIR__.'/../../stubs/tests/inertia/CreateTeamTest.php', base_path('tests/Feature/CreateTeamTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/DeleteTeamTest.php', base_path('tests/Feature/DeleteTeamTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/InviteTeamMemberTest.php', base_path('tests/Feature/InviteTeamMemberTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/LeaveTeamTest.php', base_path('tests/Feature/LeaveTeamTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/RemoveTeamMemberTest.php', base_path('tests/Feature/RemoveTeamMemberTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/UpdateTeamMemberRoleTest.php', base_path('tests/Feature/UpdateTeamMemberRoleTest.php'));
copy(__DIR__.'/../../stubs/tests/inertia/UpdateTeamNameTest.php', base_path('tests/Feature/UpdateTeamNameTest.php'));
$stubs = $this->getTestStubsPath();

copy($stubs.'/inertia/CreateTeamTest.php', base_path('tests/Feature/CreateTeamTest.php'));
copy($stubs.'/inertia/DeleteTeamTest.php', base_path('tests/Feature/DeleteTeamTest.php'));
copy($stubs.'/inertia/InviteTeamMemberTest.php', base_path('tests/Feature/InviteTeamMemberTest.php'));
copy($stubs.'/inertia/LeaveTeamTest.php', base_path('tests/Feature/LeaveTeamTest.php'));
copy($stubs.'/inertia/RemoveTeamMemberTest.php', base_path('tests/Feature/RemoveTeamMemberTest.php'));
copy($stubs.'/inertia/UpdateTeamMemberRoleTest.php', base_path('tests/Feature/UpdateTeamMemberRoleTest.php'));
copy($stubs.'/inertia/UpdateTeamNameTest.php', base_path('tests/Feature/UpdateTeamNameTest.php'));

$this->ensureApplicationIsTeamCompatible();
}
Expand Down Expand Up @@ -512,6 +531,18 @@ protected function installMiddlewareAfter($after, $name, $group = 'web')
}
}

/**
* Returns the path to the correct test stubs.
*
* @return string
*/
protected function getTestStubsPath()
{
return $this->option('pest')
? __DIR__.'/../../stubs/pest-tests'
: __DIR__.'/../../stubs/tests';
}

/**
* Installs the given Composer Packages into the application.
*
Expand Down
33 changes: 33 additions & 0 deletions stubs/pest-tests/AuthenticationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

use App\Models\User;
use App\Providers\RouteServiceProvider;

test('login screen can be rendered', function () {
$response = $this->get('/login');

$response->assertStatus(200);
});

test('users can authenticate using the login screen', function () {
$user = User::factory()->create();

$response = $this->post('/login', [
'email' => $user->email,
'password' => 'password',
]);

$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
});

test('users can not authenticate with invalid_password', function () {
$user = User::factory()->create();

$this->post('/login', [
'email' => $user->email,
'password' => 'wrong-password',
]);

$this->assertGuest();
});
61 changes: 61 additions & 0 deletions stubs/pest-tests/EmailVerificationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Verified;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\URL;
use Laravel\Fortify\Features;

test('email verification screen can be rendered', function () {
$user = User::factory()->withPersonalTeam()->create([
'email_verified_at' => null,
]);

$response = $this->actingAs($user)->get('/email/verify');

$response->assertStatus(200);
})->skip(function () {
return ! Features::enabled(Features::emailVerification());
}, 'Email verification not enabled.');

test('email can be verified', function () {
Event::fake();

$user = User::factory()->create([
'email_verified_at' => null,
]);

$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)]
);

$response = $this->actingAs($user)->get($verificationUrl);

Event::assertDispatched(Verified::class);

expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
$response->assertRedirect(RouteServiceProvider::HOME.'?verified=1');
})->skip(function () {
return ! Features::enabled(Features::emailVerification());
}, 'Email verification not enabled.');

test('email can not verified with invalid hash', function () {
nunomaduro marked this conversation as resolved.
Show resolved Hide resolved
$user = User::factory()->create([
'email_verified_at' => null,
]);

$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1('wrong-email')]
);

$this->actingAs($user)->get($verificationUrl);

expect($user->fresh()->hasVerifiedEmail())->toBeFalse();
})->skip(function () {
return ! Features::enabled(Features::emailVerification());
}, 'Email verification not enabled.');
7 changes: 7 additions & 0 deletions stubs/pest-tests/ExampleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

test('example', function () {
$response = $this->get('/');

$response->assertStatus(200);
});
5 changes: 5 additions & 0 deletions stubs/pest-tests/ExampleUnitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

test('example', function () {
expect(true)->toBeTrue();
});
35 changes: 35 additions & 0 deletions stubs/pest-tests/PasswordConfirmationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

use App\Models\User;
use Laravel\Jetstream\Features;

test('confirm password screen can be rendered', function () {
$user = Features::hasTeamFeatures()
? User::factory()->withPersonalTeam()->create()
: User::factory()->create();

$response = $this->actingAs($user)->get('/user/confirm-password');

$response->assertStatus(200);
});

test('password can be confirmed', function () {
$user = User::factory()->create();

$response = $this->actingAs($user)->post('/user/confirm-password', [
'password' => 'password',
]);

$response->assertRedirect();
$response->assertSessionHasNoErrors();
});

test('password is not confirmed with invalid password', function () {
$user = User::factory()->create();

$response = $this->actingAs($user)->post('/user/confirm-password', [
'password' => 'wrong-password',
]);

$response->assertSessionHasErrors();
});
73 changes: 73 additions & 0 deletions stubs/pest-tests/PasswordResetTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\Facades\Notification;
use Laravel\Fortify\Features;

test('reset password link screen can be rendered', function () {
$response = $this->get('/forgot-password');

$response->assertStatus(200);
})->skip(function () {
return ! Features::enabled(Features::updatePasswords());
}, 'Password updates are not enabled.');

test('reset password link can be requested', function () {
Notification::fake();

$user = User::factory()->create();

$response = $this->post('/forgot-password', [
'email' => $user->email,
]);

Notification::assertSentTo($user, ResetPassword::class);
})->skip(function () {
return ! Features::enabled(Features::updatePasswords());
}, 'Password updates are not enabled.');

test('reset password screen can be rendered', function () {
Notification::fake();

$user = User::factory()->create();

$response = $this->post('/forgot-password', [
'email' => $user->email,
]);

Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
$response = $this->get('/reset-password/'.$notification->token);

$response->assertStatus(200);

return true;
});
})->skip(function () {
return ! Features::enabled(Features::updatePasswords());
}, 'Password updates are not enabled.');

test('password can be reset with valid token', function () {
Notification::fake();

$user = User::factory()->create();

$response = $this->post('/forgot-password', [
'email' => $user->email,
]);

Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
$response = $this->post('/reset-password', [
'token' => $notification->token,
'email' => $user->email,
'password' => 'password',
'password_confirmation' => 'password',
]);

$response->assertSessionHasNoErrors();

return true;
});
})->skip(function () {
return ! Features::enabled(Features::updatePasswords());
}, 'Password updates are not enabled.');
Loading