Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Browser/PasswordResetTest.php
Show All 30 Lines | public function tearDown(): void | ||||
$this->deleteTestUser('passwordresettestdusk@' . \config('app.domain')); | $this->deleteTestUser('passwordresettestdusk@' . \config('app.domain')); | ||||
parent::tearDown(); | parent::tearDown(); | ||||
} | } | ||||
/** | /** | ||||
* Test the link from logon to password-reset page | * Test the link from logon to password-reset page | ||||
*/ | */ | ||||
public function testPasswordResetLinkOnLogon(): void | public function testLinkOnLogon(): void | ||||
{ | { | ||||
$this->browse(function (Browser $browser) { | $this->browse(function (Browser $browser) { | ||||
$browser->visit(new Home()); | $browser->visit(new Home()); | ||||
$browser->assertSeeLink('Forgot password?'); | $browser->assertSeeLink('Forgot password?'); | ||||
$browser->clickLink('Forgot password?'); | $browser->clickLink('Forgot password?'); | ||||
$browser->on(new PasswordReset()); | $browser->on(new PasswordReset()); | ||||
$browser->assertVisible('@step1'); | $browser->assertVisible('@step1'); | ||||
}); | }); | ||||
} | } | ||||
/** | /** | ||||
* Test 1st step of password-reset | * Test 1st step of password-reset | ||||
*/ | */ | ||||
public function testPasswordResetStep1(): void | public function testStep1(): void | ||||
{ | { | ||||
$user = $this->getTestUser('passwordresettestdusk@' . \config('app.domain')); | $user = $this->getTestUser('passwordresettestdusk@' . \config('app.domain')); | ||||
$user->setSetting('external_email', 'external@domain.tld'); | $user->setSetting('external_email', 'external@domain.tld'); | ||||
$this->browse(function (Browser $browser) { | $this->browse(function (Browser $browser) { | ||||
$browser->visit(new PasswordReset()); | $browser->visit(new PasswordReset()); | ||||
$browser->assertVisible('@step1'); | $browser->assertVisible('@step1'); | ||||
Show All 36 Lines | public function testStep1(): void | ||||
$browser->waitFor('@step2'); | $browser->waitFor('@step2'); | ||||
$browser->assertMissing('@step1'); | $browser->assertMissing('@step1'); | ||||
}); | }); | ||||
} | } | ||||
/** | /** | ||||
* Test 2nd Step of the password reset process | * Test 2nd Step of the password reset process | ||||
* | * | ||||
* @depends testPasswordResetStep1 | * @depends testStep1 | ||||
*/ | */ | ||||
public function testPasswordResetStep2(): void | public function testStep2(): void | ||||
{ | { | ||||
$user = $this->getTestUser('passwordresettestdusk@' . \config('app.domain')); | $user = $this->getTestUser('passwordresettestdusk@' . \config('app.domain')); | ||||
$user->setSetting('external_email', 'external@domain.tld'); | $user->setSetting('external_email', 'external@domain.tld'); | ||||
$this->browse(function (Browser $browser) { | $this->browse(function (Browser $browser) { | ||||
$browser->assertVisible('@step2'); | $browser->assertVisible('@step2'); | ||||
// Here we expect one text input, Back and Continue buttons | // Here we expect one text input, Back and Continue buttons | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | public function testStep2(): void | ||||
$browser->waitFor('@step3'); | $browser->waitFor('@step3'); | ||||
$browser->assertMissing('@step2'); | $browser->assertMissing('@step2'); | ||||
}); | }); | ||||
} | } | ||||
/** | /** | ||||
* Test 3rd Step of the password reset process | * Test 3rd Step of the password reset process | ||||
* | * | ||||
* @depends testPasswordResetStep2 | * @depends testStep2 | ||||
*/ | */ | ||||
public function testPasswordResetStep3(): void | public function testStep3(): void | ||||
{ | { | ||||
$user = $this->getTestUser('passwordresettestdusk@' . \config('app.domain')); | $user = $this->getTestUser('passwordresettestdusk@' . \config('app.domain')); | ||||
$user->setSetting('external_email', 'external@domain.tld'); | $user->setSetting('external_email', 'external@domain.tld'); | ||||
$user->setSetting('password_policy', 'upper,digit'); | |||||
$this->browse(function (Browser $browser) { | $this->browse(function (Browser $browser) { | ||||
$browser->assertVisible('@step3'); | $browser->assertVisible('@step3') | ||||
->clearToasts(); | |||||
// Here we expect 2 text inputs, Back and Continue buttons | // Here we expect 2 text inputs, Back and Continue buttons | ||||
$browser->with('@step3', function ($step) { | $browser->with('@step3', function (Browser $step) { | ||||
$step->assertVisible('#reset_password'); | $step->assertVisible('#reset_password') | ||||
$step->assertVisible('#reset_confirm'); | ->assertVisible('#reset_password_confirmation') | ||||
$step->assertVisible('[type=button]'); | ->assertVisible('[type=button]') | ||||
$step->assertVisible('[type=submit]'); | ->assertVisible('[type=submit]') | ||||
$step->assertFocused('#reset_password'); | ->assertFocused('#reset_password'); | ||||
}); | }); | ||||
// Test Back button | // Test Back button | ||||
$browser->click('@step3 [type=button]'); | $browser->click('@step3 [type=button]') | ||||
$browser->waitFor('@step2'); | ->waitFor('@step2') | ||||
$browser->assertFocused('@step2 #reset_short_code'); | ->assertFocused('@step2 #reset_short_code') | ||||
$browser->assertMissing('@step3'); | ->assertMissing('@step3') | ||||
$browser->assertMissing('@step1'); | ->assertMissing('@step1'); | ||||
// TODO: Test form reset when going back | // TODO: Test form reset when going back | ||||
// Because the verification code is removed in tearDown() | // Because the verification code is removed in tearDown() | ||||
// we'll start from the beginning (Step 1) | // we'll start from the beginning (Step 1) | ||||
$browser->click('@step2 [type=button]'); | $browser->click('@step2 [type=button]') | ||||
$browser->waitFor('@step1'); | ->waitFor('@step1') | ||||
$browser->assertFocused('@step1 #reset_email'); | ->assertFocused('@step1 #reset_email') | ||||
$browser->assertMissing('@step3'); | ->assertMissing('@step3') | ||||
$browser->assertMissing('@step2'); | ->assertMissing('@step2'); | ||||
// Submit valid data | // Submit valid data | ||||
$browser->with('@step1', function ($step) { | $browser->with('@step1', function ($step) { | ||||
$step->type('#reset_email', 'passwordresettestdusk@' . \config('app.domain')); | $step->type('#reset_email', 'passwordresettestdusk@' . \config('app.domain')); | ||||
$step->click('[type=submit]'); | $step->click('[type=submit]'); | ||||
}); | }); | ||||
$browser->waitFor('@step2'); | $browser->waitFor('@step2') | ||||
$browser->waitUntilMissing('@step2 #reset_code[value=""]'); | ->waitUntilMissing('@step2 #reset_code[value=""]'); | ||||
// Submit valid code again | // Submit valid code again | ||||
$browser->with('@step2', function ($step) { | $browser->with('@step2', function ($step) { | ||||
$code = $step->value('#reset_code'); | $code = $step->value('#reset_code'); | ||||
$this->assertNotEmpty($code); | $this->assertNotEmpty($code); | ||||
$code = VerificationCode::find($code); | $code = VerificationCode::find($code); | ||||
$step->type('#reset_short_code', $code->short_code); | $step->type('#reset_short_code', $code->short_code); | ||||
$step->click('[type=submit]'); | $step->click('[type=submit]'); | ||||
}); | }); | ||||
$browser->waitFor('@step3'); | $browser->waitFor('@step3'); | ||||
// Submit invalid data | // Submit invalid data | ||||
$browser->with('@step3', function ($step) use ($browser) { | $browser->with('@step3', function ($step) use ($browser) { | ||||
$step->assertFocused('#reset_password'); | $step->assertFocused('#reset_password') | ||||
->whenAvailable('#reset_password_policy', function (Browser $browser) { | |||||
$step->type('#reset_password', '12345678'); | $browser->assertElementsCount('li', 2) | ||||
$step->type('#reset_confirm', '123456789'); | ->assertMissing('li:first-child svg.text-success') | ||||
->assertSeeIn('li:first-child small', "Password contains an upper-case character") | |||||
->assertMissing('li:last-child svg.text-success') | |||||
->assertSeeIn('li:last-child small', "Password contains a digit"); | |||||
}) | |||||
->type('#reset_password', 'A2345678') | |||||
->type('#reset_password_confirmation', '123456789') | |||||
->with('#reset_password_policy', function (Browser $browser) { | |||||
$browser->waitFor('li:first-child svg.text-success') | |||||
->waitFor('li:last-child svg.text-success'); | |||||
}); | |||||
$step->click('[type=submit]'); | $step->click('[type=submit]'); | ||||
$browser->waitFor('.toast-error'); | $browser->waitFor('.toast-error'); | ||||
$step->waitFor('#reset_password.is-invalid') | $step->waitFor('#reset_password.is-invalid') | ||||
->assertVisible('#reset_password.is-invalid') | ->assertVisible('#reset_password_input .invalid-feedback') | ||||
->assertVisible('#reset_password + .invalid-feedback') | |||||
->assertFocused('#reset_password'); | ->assertFocused('#reset_password'); | ||||
$browser->click('.toast-error'); // remove the toast | $browser->click('.toast-error'); // remove the toast | ||||
}); | }); | ||||
// Submit valid data | // Submit valid data | ||||
$browser->with('@step3', function ($step) { | $browser->with('@step3', function ($step) { | ||||
$step->type('#reset_confirm', '12345678'); | $step->type('#reset_password_confirmation', 'A2345678') | ||||
->click('[type=submit]'); | |||||
$step->click('[type=submit]'); | |||||
}); | }); | ||||
$browser->waitUntilMissing('@step3'); | $browser->waitUntilMissing('@step3'); | ||||
// At this point we should be auto-logged-in to dashboard | // At this point we should be auto-logged-in to dashboard | ||||
$browser->on(new Dashboard()); | $browser->on(new Dashboard()); | ||||
// FIXME: Is it enough to be sure user is logged in? | // FIXME: Is it enough to be sure user is logged in? | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* Test password reset process for a user with 2FA enabled. | |||||
*/ | |||||
public function testResetWith2FA(): void | |||||
{ | |||||
$this->markTestIncomplete(); | |||||
} | |||||
} | } |