diff --git a/src/resources/sass/app.scss b/src/resources/sass/app.scss index ceba4c33..f05f4b89 100644 --- a/src/resources/sass/app.scss +++ b/src/resources/sass/app.scss @@ -1,21 +1,40 @@ // Fonts // Variables @import 'variables'; // Bootstrap @import '~bootstrap/scss/bootstrap'; // Toastr @import '~@deveodk/vue-toastr/dist/@deveodk/vue-toastr.css'; // Fixes Toastr incompatibility with Bootstrap .toast-container > .toast { opacity: 1; } @import 'menu'; nav + .container { margin-top: 120px; } + +#error-page { + align-items: center; + display: flex; + justify-content: center; + height: 100vh; + color: #636b6f; + + .code { + border-right: 2px solid; + font-size: 26px; + padding: 0 15px; + } + + .message { + font-size: 18px; + padding: 0 15px; + } +} diff --git a/src/resources/vue/components/404.vue b/src/resources/vue/components/404.vue index f20bcfda..04e64cc3 100644 --- a/src/resources/vue/components/404.vue +++ b/src/resources/vue/components/404.vue @@ -1,27 +1,6 @@ - - diff --git a/src/tests/Browser/ErrorTest.php b/src/tests/Browser/ErrorTest.php new file mode 100644 index 00000000..f0e674b3 --- /dev/null +++ b/src/tests/Browser/ErrorTest.php @@ -0,0 +1,36 @@ +browse(function (Browser $browser) { + $browser->visit('/unknown'); + + $browser->waitFor('#app > #error-page'); + $browser->assertVisible('#app > #primary-menu'); + $this->assertSame('404', $browser->text('#error-page .code')); + $this->assertSame('Not Found', $browser->text('#error-page .message')); + + $browser->visit('/login/unknown'); + + $browser->waitFor('#app > #error-page'); + $browser->assertVisible('#app > #primary-menu'); + $this->assertSame('404', $browser->text('#error-page .code')); + $this->assertSame('Not Found', $browser->text('#error-page .message')); + }); + + // TODO: Test the same as above, but with use of Vue router + } +} diff --git a/src/tests/Browser/Pages/Dashboard.php b/src/tests/Browser/Pages/Dashboard.php index fadaeeac..a9d28c94 100644 --- a/src/tests/Browser/Pages/Dashboard.php +++ b/src/tests/Browser/Pages/Dashboard.php @@ -1,44 +1,43 @@ assertPathIs('/dashboard') - ->assertSee('Dashboard'); + $browser->assertPathIs('/dashboard'); + $browser->assertSee('Dashboard'); } /** * Get the element shortcuts for the page. * * @return array */ public function elements() { return [ '@app' => '#app', ]; } } diff --git a/src/tests/Browser/Pages/Home.php b/src/tests/Browser/Pages/Home.php index ad93d870..d7374f0c 100644 --- a/src/tests/Browser/Pages/Home.php +++ b/src/tests/Browser/Pages/Home.php @@ -1,64 +1,65 @@ assertPathIs('/login'); $browser->assertVisible('form.form-signin'); } /** * Get the element shortcuts for the page. * * @return array */ public function elements() { return [ '@app' => '#app', ]; } /** * Submit logon form. * * @param Browser $browser * @param string $username * @param string $password * @param bool $wait_for_dashboard * * @return void */ public function submitLogon(Browser $browser, $username, $password, $wait_for_dashboard = false) { $browser ->type('#inputEmail', $username) ->type('#inputPassword', $password) ->press('form button'); if ($wait_for_dashboard) { $browser->waitForLocation('/dashboard'); } } } diff --git a/src/tests/Browser/Pages/Signup.php b/src/tests/Browser/Pages/Signup.php index 42a5d1be..de74b560 100644 --- a/src/tests/Browser/Pages/Signup.php +++ b/src/tests/Browser/Pages/Signup.php @@ -1,48 +1,47 @@ assertPathIs('/signup') - ->assertPresent('@step1'); + $browser->assertPathIs('/signup'); + $browser->assertPresent('@step1'); } /** * Get the element shortcuts for the page. * * @return array */ public function elements(): array { return [ '@app' => '#app', '@step1' => '#step1', '@step2' => '#step2', '@step3' => '#step3', ]; } } diff --git a/src/tests/Browser/SignupTest.php b/src/tests/Browser/SignupTest.php index 904edffb..b6b5c63e 100644 --- a/src/tests/Browser/SignupTest.php +++ b/src/tests/Browser/SignupTest.php @@ -1,267 +1,267 @@ delete(); parent::tearDown(); } /** * Test 1st step of the signup process * * @return void */ public function testSignupStep1() { $this->browse(function (Browser $browser) { $browser->visit(new Signup()); $browser->assertVisible('@step1'); // Here we expect two text inputs and Continue $browser->with('@step1', function ($step) { $step->assertVisible('#signup_name'); $step->assertFocused('#signup_name'); $step->assertVisible('#signup_email'); $step->assertVisible('[type=submit]'); }); // Submit empty form // Both Step 1 inputs are required, so after pressing Submit // we expect focus to be moved to the first input $browser->with('@step1', function ($step) { $step->click('[type=submit]'); $step->assertFocused('#signup_name'); }); // Submit invalid email // We expect email input to have is-invalid class added, with .invalid-feedback element $browser->with('@step1', function ($step) use ($browser) { $step->type('#signup_name', 'Test User'); $step->type('#signup_email', '@test'); $step->click('[type=submit]'); $step->waitFor('#signup_email.is-invalid'); $step->waitFor('#signup_email + .invalid-feedback'); $browser->waitFor('.toast-error'); $browser->click('.toast-error'); // remove the toast }); // Submit valid data // We expect error state on email input to be removed, and Step 2 form visible $browser->with('@step1', function ($step) { $step->type('#signup_name', 'Test User'); $step->type('#signup_email', 'BrowserSignupTestUser1@kolab.org'); $step->click('[type=submit]'); $step->assertMissing('#signup_email.is-invalid'); $step->assertMissing('#signup_email + .invalid-feedback'); $step->waitUntilMissing('#signup_code[value=""]'); }); $browser->waitFor('@step2'); $browser->assertMissing('@step1'); }); } /** * Test 2nd Step of the signup process * * @depends testSignupStep1 * @return void */ public function testSignupStep2() { $this->browse(function (Browser $browser) { $browser->assertVisible('@step2'); // Here we expect one text input, Back and Continue buttons $browser->with('@step2', function ($step) { $step->assertVisible('#signup_short_code'); $step->assertFocused('#signup_short_code'); $step->assertVisible('[type=button]'); $step->assertVisible('[type=submit]'); }); // Test Back button functionality $browser->click('@step2 [type=button]'); $browser->waitFor('@step1'); $browser->assertMissing('@step2'); // Submit valid Step 1 data (again) $browser->with('@step1', function ($step) { $step->type('#signup_name', 'Test User'); $step->type('#signup_email', 'BrowserSignupTestUser1@kolab.org'); $step->click('[type=submit]'); }); $browser->waitFor('@step2'); $browser->assertMissing('@step1'); // Submit invalid code // We expect code input to have is-invalid class added, with .invalid-feedback element $browser->with('@step2', function ($step) use ($browser) { $step->type('#signup_short_code', 'XXXXX'); $step->click('[type=submit]'); $browser->waitFor('.toast-error'); $step->assertVisible('#signup_short_code.is-invalid'); $step->assertVisible('#signup_short_code + .invalid-feedback'); $step->assertFocused('#signup_short_code'); $browser->click('.toast-error'); // remove the toast }); // Submit valid code // We expect error state on code input to be removed, and Step 3 form visible $browser->with('@step2', function ($step) { // Get the code and short_code from database // FIXME: Find a nice way to read javascript data without using hidden inputs $code = $step->value('#signup_code'); $this->assertNotEmpty($code); $code = SignupCode::find($code); $step->type('#signup_short_code', $code->short_code); $step->click('[type=submit]'); $step->assertMissing('#signup_short_code.is-invalid'); $step->assertMissing('#signup_short_code + .invalid-feedback'); }); $browser->waitFor('@step3'); $browser->assertMissing('@step2'); }); // TODO: Test code verification with an external link } /** * Test 3rd Step of the signup process * * @depends testSignupStep2 * @return void */ public function testSignupStep3() { $this->browse(function (Browser $browser) { $browser->assertVisible('@step3'); // Here we expect one text input, Back and Continue buttons $browser->with('@step3', function ($step) { $step->assertVisible('#signup_login'); $step->assertVisible('#signup_password'); $step->assertVisible('#signup_confirm'); $step->assertVisible('[type=button]'); $step->assertVisible('[type=submit]'); $step->assertFocused('#signup_login'); $step->assertSeeIn('#signup_login + span', '@' . \config('app.domain')); }); // Test Back button $browser->click('@step3 [type=button]'); $browser->waitFor('@step2'); $browser->assertMissing('@step3'); // TODO: Test form reset when going back // Submit valid code again $browser->with('@step2', function ($step) { $code = $step->value('#signup_code'); $this->assertNotEmpty($code); $code = SignupCode::find($code); $step->type('#signup_short_code', $code->short_code); $step->click('[type=submit]'); }); $browser->waitFor('@step3'); // Submit invalid data $browser->with('@step3', function ($step) use ($browser) { $step->assertFocused('#signup_login'); $step->type('#signup_login', '*'); $step->type('#signup_password', '12345678'); $step->type('#signup_confirm', '123456789'); $step->click('[type=submit]'); $browser->waitFor('.toast-error'); $step->assertVisible('#signup_login.is-invalid'); $step->assertVisible('#signup_login + span + .invalid-feedback'); $step->assertVisible('#signup_password.is-invalid'); $step->assertVisible('#signup_password + .invalid-feedback'); $step->assertFocused('#signup_login'); $browser->click('.toast-error'); // remove the toast }); // Submit invalid data (valid login, invalid password) $browser->with('@step3', function ($step) use ($browser) { // Make sure the user does not exist (it may happen when executing // tests again after failure) User::where('email', 'SignupTestDusk@' . \config('app.domain'))->delete(); - // FIXME: FOr some reason I can just use ->value() here + // FIXME: For some reason I can't just use ->value() here $step->clear('#signup_login'); $step->type('#signup_login', 'SignupTestDusk'); $step->click('[type=submit]'); $browser->waitFor('.toast-error'); $step->assertVisible('#signup_password.is-invalid'); $step->assertVisible('#signup_password + .invalid-feedback'); $step->assertMissing('#signup_login.is-invalid'); $step->assertMissing('#signup_login + span + .invalid-feedback'); $step->assertFocused('#signup_password'); $browser->click('.toast-error'); // remove the toast }); // Submit valid data $browser->with('@step3', function ($step) { - // FIXME: FOr some reason I can just use ->value() here + // FIXME: For some reason I can't just use ->value() here $step->clear('#signup_confirm'); $step->type('#signup_confirm', '12345678'); $step->click('[type=submit]'); }); $browser->waitUntilMissing('@step3'); // At this point we should be auto-logged-in to dashboard $dashboard = new Dashboard(); $dashboard->assert($browser); // FIXME: Is it enough to be sure user is logged in? }); } }