Skip to content

Commit f8fa62e

Browse files
committed
First round of authentication tests
1 parent b50f314 commit f8fa62e

File tree

5 files changed

+136
-6
lines changed

5 files changed

+136
-6
lines changed

resources/assets/scripts/components/auth/LoginForm.vue

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,38 @@
55
>
66
<div class="flex flex-wrap -mx-3 mb-6">
77
<div class="input-open">
8-
<input class="input" id="grid-username" type="text" name="user" aria-labelledby="grid-username" required
8+
<input class="input" id="grid-username" type="text" name="user" aria-labelledby="grid-username-label" required
99
ref="email"
1010
:class="{ 'has-content' : user.email.length > 0 }"
1111
:readonly="showSpinner"
1212
:value="user.email"
1313
v-on:input="updateEmail($event)"
1414
/>
15-
<label for="grid-username">{{ $t('strings.user_identifier') }}</label>
15+
<label id="grid-username-label" for="grid-username">{{ $t('strings.user_identifier') }}</label>
1616
</div>
1717
</div>
1818
<div class="flex flex-wrap -mx-3 mb-6">
1919
<div class="input-open">
20-
<input class="input" id="grid-password" type="password" name="password" aria-labelledby="grid-password" required
20+
<input class="input" id="grid-password" type="password" name="password" aria-labelledby="grid-password-label" required
2121
ref="password"
2222
:class="{ 'has-content' : user.password && user.password.length > 0 }"
2323
:readonly="showSpinner"
2424
v-model="user.password"
2525
/>
26-
<label for="grid-password">{{ $t('strings.password') }}</label>
26+
<label id="grid-password-label" for="grid-password">{{ $t('strings.password') }}</label>
2727
</div>
2828
</div>
2929
<div>
30-
<button class="btn btn-blue btn-jumbo" type="submit" v-bind:disabled="showSpinner">
30+
<button id="grid-login-button" class="btn btn-blue btn-jumbo" type="submit" aria-label="Log in"
31+
v-bind:disabled="showSpinner">
3132
<span class="spinner white" v-bind:class="{ hidden: ! showSpinner }">&nbsp;</span>
3233
<span v-bind:class="{ hidden: showSpinner }">
3334
{{ $t('auth.sign_in') }}
3435
</span>
3536
</button>
3637
</div>
3738
<div class="pt-6 text-center">
38-
<router-link class="text-xs text-grey tracking-wide no-underline uppercase hover:text-grey-dark"
39+
<router-link class="text-xs text-grey tracking-wide no-underline uppercase hover:text-grey-dark" aria-label="Forgot password"
3940
:to="{ name: 'forgot-password' }">
4041
{{ $t('auth.forgot_password.label') }}
4142
</router-link>

tests/Browser/BrowserTestCase.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ protected function driver()
4141
{
4242
$options = (new ChromeOptions)->addArguments([
4343
'--disable-gpu',
44+
'--disable-infobars',
4445
]);
4546

4647
return RemoteWebDriver::create(

tests/Browser/Pages/BasePage.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Pterodactyl\Tests\Browser\Pages;
4+
5+
use Laravel\Dusk\Page;
6+
7+
abstract class BasePage extends Page
8+
{
9+
/**
10+
* @return array
11+
*/
12+
public static function siteElements()
13+
{
14+
return [];
15+
}
16+
}

tests/Browser/Pages/LoginPage.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Pterodactyl\Tests\Browser\Pages;
4+
5+
class LoginPage extends BasePage
6+
{
7+
/**
8+
* @return string
9+
*/
10+
public function url(): string
11+
{
12+
return '/auth/login';
13+
}
14+
15+
public function elements()
16+
{
17+
return [
18+
'@username' => '#grid-username',
19+
'@password' => '#grid-password',
20+
'@loginButton' => '#grid-login-button',
21+
'@forgotPassword' => 'a[aria-label="Forgot password"]',
22+
];
23+
}
24+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace Pterodactyl\Tests\Browser\Processes\Authentication;
4+
5+
use Pterodactyl\Models\User;
6+
use Illuminate\Support\Facades\Hash;
7+
use Facebook\WebDriver\WebDriverKeys;
8+
use Pterodactyl\Tests\Browser\BrowserTestCase;
9+
use Pterodactyl\Tests\Browser\Pages\LoginPage;
10+
use Pterodactyl\Tests\Browser\PterodactylBrowser;
11+
12+
class LoginProcessTest extends BrowserTestCase
13+
{
14+
private $user;
15+
16+
/**
17+
* Setup tests.
18+
*/
19+
protected function setUp()
20+
{
21+
parent::setUp();
22+
23+
$this->user = factory(User::class)->create([
24+
'email' => 'test@example.com',
25+
'password' => Hash::make('Password123'),
26+
]);
27+
}
28+
29+
/**
30+
* Test that a user can login successfully using their email address.
31+
*/
32+
public function testLoginUsingEmail()
33+
{
34+
$this->browse(function (PterodactylBrowser $browser) {
35+
$browser->visit(new LoginPage)
36+
->waitFor('@username')
37+
->type('@username', 'test@example.com')
38+
->type('@password', 'Password123')
39+
->click('@loginButton')
40+
->waitForReload()
41+
->assertPathIs('/')
42+
->assertAuthenticatedAs($this->user);
43+
});
44+
}
45+
46+
/**
47+
* Test that a user can login successfully using their username.
48+
*/
49+
public function testLoginUsingUsername()
50+
{
51+
$this->browse(function (PterodactylBrowser $browser) {
52+
$browser->visit(new LoginPage)
53+
->waitFor('@username')
54+
->type('@username', $this->user->username)
55+
->type('@password', 'Password123')
56+
->click('@loginButton')
57+
->waitForReload()
58+
->assertPathIs('/')
59+
->assertAuthenticatedAs($this->user);
60+
});
61+
}
62+
63+
/**
64+
* Test that entering the wrong password shows the expected error and then allows
65+
* us to login without clearing the username field.
66+
*/
67+
public function testLoginWithErrors()
68+
{
69+
$this->browse(function (PterodactylBrowser $browser) {
70+
$browser->logout()
71+
->visit(new LoginPage())
72+
->waitFor('@username')
73+
->type('@username', 'test@example.com')
74+
->type('@password', 'invalid')
75+
->click('@loginButton')
76+
->waitFor('.alert.error')
77+
->assertSeeIn('.alert.error', trans('auth.failed'))
78+
->assertValue('@username', 'test@example.com')
79+
->assertValue('@password', '')
80+
->assertFocused('@password')
81+
->type('@password', 'Password123')
82+
->keys('@password', [WebDriverKeys::ENTER])
83+
->waitForReload()
84+
->assertPathIs('/')
85+
->assertAuthenticatedAs($this->user);
86+
});
87+
}
88+
}

0 commit comments

Comments
 (0)