Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Browser/UsersTest.php
<?php | <?php | ||||
namespace Tests\Browser; | namespace Tests\Browser; | ||||
use App\User; | use App\User; | ||||
use App\UserAlias; | use App\UserAlias; | ||||
use Tests\Browser; | use Tests\Browser; | ||||
use Tests\Browser\Components\Dialog; | |||||
use Tests\Browser\Components\ListInput; | use Tests\Browser\Components\ListInput; | ||||
use Tests\Browser\Components\Toast; | use Tests\Browser\Components\Toast; | ||||
use Tests\Browser\Pages\Dashboard; | use Tests\Browser\Pages\Dashboard; | ||||
use Tests\Browser\Pages\Home; | use Tests\Browser\Pages\Home; | ||||
use Tests\Browser\Pages\UserInfo; | use Tests\Browser\Pages\UserInfo; | ||||
use Tests\Browser\Pages\UserList; | use Tests\Browser\Pages\UserList; | ||||
use Tests\DuskTestCase; | use Tests\DuskTestCase; | ||||
use Illuminate\Foundation\Testing\DatabaseMigrations; | use Illuminate\Foundation\Testing\DatabaseMigrations; | ||||
class UsersTest extends DuskTestCase | class UsersTest extends DuskTestCase | ||||
{ | { | ||||
private $profile = [ | private $profile = [ | ||||
'first_name' => 'John', | 'first_name' => 'John', | ||||
'last_name' => 'Doe', | 'last_name' => 'Doe', | ||||
]; | ]; | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
public function setUp(): void | public function setUp(): void | ||||
{ | { | ||||
parent::setUp(); | parent::setUp(); | ||||
// TODO: Use TestCase::deleteTestUser() | $this->deleteTestUser('julia.roberts@kolab.org'); | ||||
User::withTrashed()->where('email', 'john.rambo@kolab.org')->forceDelete(); | |||||
$john = User::where('email', 'john@kolab.org')->first(); | $john = User::where('email', 'john@kolab.org')->first(); | ||||
$john->setSettings($this->profile); | $john->setSettings($this->profile); | ||||
UserAlias::where('user_id', $john->id) | UserAlias::where('user_id', $john->id) | ||||
->where('alias', 'john.test@kolab.org')->delete(); | ->where('alias', 'john.test@kolab.org')->delete(); | ||||
} | } | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
public function tearDown(): void | public function tearDown(): void | ||||
{ | { | ||||
// TODO: Use TestCase::deleteTestUser() | $this->deleteTestUser('julia.roberts@kolab.org'); | ||||
User::withTrashed()->where('email', 'john.rambo@kolab.org')->forceDelete(); | |||||
$john = User::where('email', 'john@kolab.org')->first(); | $john = User::where('email', 'john@kolab.org')->first(); | ||||
$john->setSettings($this->profile); | $john->setSettings($this->profile); | ||||
UserAlias::where('user_id', $john->id) | UserAlias::where('user_id', $john->id) | ||||
->where('alias', 'john.test@kolab.org')->delete(); | ->where('alias', 'john.test@kolab.org')->delete(); | ||||
parent::tearDown(); | parent::tearDown(); | ||||
} | } | ||||
Show All 15 Lines | class UsersTest extends DuskTestCase | ||||
* Test users list page (unauthenticated) | * Test users list page (unauthenticated) | ||||
*/ | */ | ||||
public function testListUnauth(): void | public function testListUnauth(): void | ||||
{ | { | ||||
// Test that the page requires authentication | // Test that the page requires authentication | ||||
$this->browse(function (Browser $browser) { | $this->browse(function (Browser $browser) { | ||||
$browser->visit('/users')->on(new Home()); | $browser->visit('/users')->on(new Home()); | ||||
}); | }); | ||||
// TODO: Test that jack@kolab.org can't access this page | |||||
} | } | ||||
/** | /** | ||||
* Test users list page | * Test users list page | ||||
*/ | */ | ||||
public function testList(): void | public function testList(): void | ||||
{ | { | ||||
// Test that the page requires authentication | // Test that the page requires authentication | ||||
$this->browse(function (Browser $browser) { | $this->browse(function (Browser $browser) { | ||||
$browser->visit(new Home()) | $browser->visit(new Home()) | ||||
->submitLogon('john@kolab.org', 'simple123', true) | ->submitLogon('john@kolab.org', 'simple123', true) | ||||
->on(new Dashboard()) | ->on(new Dashboard()) | ||||
->assertSeeIn('@links .link-users', 'User accounts') | ->assertSeeIn('@links .link-users', 'User accounts') | ||||
->click('@links .link-users') | ->click('@links .link-users') | ||||
->on(new UserList()) | ->on(new UserList()) | ||||
->whenAvailable('@table', function ($browser) { | ->whenAvailable('@table', function (Browser $browser) { | ||||
$this->assertCount(1, $browser->elements('tbody tr')); | $browser->assertElementsCount('tbody tr', 2) | ||||
$browser->assertSeeIn('tbody tr td a', 'john@kolab.org'); | ->assertSeeIn('tbody tr:nth-child(1) a', 'jack@kolab.org') | ||||
->assertSeeIn('tbody tr:nth-child(2) a', 'john@kolab.org') | |||||
->assertVisible('tbody tr:nth-child(1) button.button-delete') | |||||
->assertVisible('tbody tr:nth-child(2) button.button-delete'); | |||||
}); | }); | ||||
}); | }); | ||||
} | } | ||||
/** | /** | ||||
* Test user account editing page (not profile page) | * Test user account editing page (not profile page) | ||||
* | * | ||||
* @depends testList | * @depends testList | ||||
*/ | */ | ||||
public function testInfo(): void | public function testInfo(): void | ||||
{ | { | ||||
$this->browse(function (Browser $browser) { | $this->browse(function (Browser $browser) { | ||||
$browser->on(new UserList()) | $browser->on(new UserList()) | ||||
->click('@table tr:first-child a') | ->click('@table tr:last-child a') | ||||
->on(new UserInfo()) | ->on(new UserInfo()) | ||||
->assertSeeIn('#user-info .card-title', 'User account') | ->assertSeeIn('#user-info .card-title', 'User account') | ||||
->with('@form', function (Browser $browser) { | ->with('@form', function (Browser $browser) { | ||||
// Assert form content | // Assert form content | ||||
$browser->assertFocused('div.row:nth-child(1) input') | $browser->assertFocused('div.row:nth-child(1) input') | ||||
->assertSeeIn('div.row:nth-child(1) label', 'First name') | ->assertSeeIn('div.row:nth-child(1) label', 'First name') | ||||
->assertValue('div.row:nth-child(1) input[type=text]', $this->profile['first_name']) | ->assertValue('div.row:nth-child(1) input[type=text]', $this->profile['first_name']) | ||||
->assertSeeIn('div.row:nth-child(2) label', 'Last name') | ->assertSeeIn('div.row:nth-child(2) label', 'Last name') | ||||
->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['last_name']) | ->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['last_name']) | ||||
->assertSeeIn('div.row:nth-child(3) label', 'Email') | ->assertSeeIn('div.row:nth-child(3) label', 'Email') | ||||
->assertValue('div.row:nth-child(3) input[type=text]', 'john@kolab.org') | ->assertValue('div.row:nth-child(3) input[type=text]', 'john@kolab.org') | ||||
//TODO ->assertDisabled('div.row:nth-child(3) input') | ->assertDisabled('div.row:nth-child(3) input[type=text]') | ||||
->assertSeeIn('div.row:nth-child(4) label', 'Email aliases') | ->assertSeeIn('div.row:nth-child(4) label', 'Email aliases') | ||||
->assertVisible('div.row:nth-child(4) .listinput-widget') | ->assertVisible('div.row:nth-child(4) .listinput-widget') | ||||
->with(new ListInput('#aliases'), function (Browser $browser) { | ->with(new ListInput('#aliases'), function (Browser $browser) { | ||||
$browser->assertListInputValue(['john.doe@kolab.org']) | $browser->assertListInputValue(['john.doe@kolab.org']) | ||||
->assertValue('@input', ''); | ->assertValue('@input', ''); | ||||
}) | }) | ||||
->assertSeeIn('div.row:nth-child(5) label', 'Password') | ->assertSeeIn('div.row:nth-child(5) label', 'Password') | ||||
->assertValue('div.row:nth-child(5) input[type=password]', '') | ->assertValue('div.row:nth-child(5) input[type=password]', '') | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | public function testNewUser(): void | ||||
// Assert form content | // Assert form content | ||||
$browser->assertFocused('div.row:nth-child(1) input') | $browser->assertFocused('div.row:nth-child(1) input') | ||||
->assertSeeIn('div.row:nth-child(1) label', 'First name') | ->assertSeeIn('div.row:nth-child(1) label', 'First name') | ||||
->assertValue('div.row:nth-child(1) input[type=text]', '') | ->assertValue('div.row:nth-child(1) input[type=text]', '') | ||||
->assertSeeIn('div.row:nth-child(2) label', 'Last name') | ->assertSeeIn('div.row:nth-child(2) label', 'Last name') | ||||
->assertValue('div.row:nth-child(2) input[type=text]', '') | ->assertValue('div.row:nth-child(2) input[type=text]', '') | ||||
->assertSeeIn('div.row:nth-child(3) label', 'Email') | ->assertSeeIn('div.row:nth-child(3) label', 'Email') | ||||
->assertValue('div.row:nth-child(3) input[type=text]', '') | ->assertValue('div.row:nth-child(3) input[type=text]', '') | ||||
->assertEnabled('div.row:nth-child(3) input') | ->assertEnabled('div.row:nth-child(3) input[type=text]') | ||||
->assertSeeIn('div.row:nth-child(4) label', 'Email aliases') | ->assertSeeIn('div.row:nth-child(4) label', 'Email aliases') | ||||
->assertVisible('div.row:nth-child(4) .listinput-widget') | ->assertVisible('div.row:nth-child(4) .listinput-widget') | ||||
->with(new ListInput('#aliases'), function (Browser $browser) { | ->with(new ListInput('#aliases'), function (Browser $browser) { | ||||
$browser->assertListInputValue([]) | $browser->assertListInputValue([]) | ||||
->assertValue('@input', ''); | ->assertValue('@input', ''); | ||||
}) | }) | ||||
->assertSeeIn('div.row:nth-child(5) label', 'Password') | ->assertSeeIn('div.row:nth-child(5) label', 'Password') | ||||
->assertValue('div.row:nth-child(5) input[type=password]', '') | ->assertValue('div.row:nth-child(5) input[type=password]', '') | ||||
Show All 20 Lines | public function testNewUser(): void | ||||
}) | }) | ||||
->with('@form', function (Browser $browser) { | ->with('@form', function (Browser $browser) { | ||||
$browser->assertSeeIn('#email + .invalid-feedback', 'The specified email is invalid.') | $browser->assertSeeIn('#email + .invalid-feedback', 'The specified email is invalid.') | ||||
->assertSeeIn('#password + .invalid-feedback', 'The password confirmation does not match.'); | ->assertSeeIn('#password + .invalid-feedback', 'The password confirmation does not match.'); | ||||
}); | }); | ||||
// Test form error handling (aliases) | // Test form error handling (aliases) | ||||
$browser->with('@form', function (Browser $browser) { | $browser->with('@form', function (Browser $browser) { | ||||
$browser->type('#email', 'john.rambo@kolab.org') | $browser->type('#email', 'julia.roberts@kolab.org') | ||||
->type('#password_confirmation', 'simple123') | ->type('#password_confirmation', 'simple123') | ||||
->with(new ListInput('#aliases'), function (Browser $browser) { | ->with(new ListInput('#aliases'), function (Browser $browser) { | ||||
$browser->addListEntry('invalid address'); | $browser->addListEntry('invalid address'); | ||||
}) | }) | ||||
->click('button[type=submit]'); | ->click('button[type=submit]'); | ||||
}) | }) | ||||
->with(new Toast(Toast::TYPE_ERROR), function (Browser $browser) { | ->with(new Toast(Toast::TYPE_ERROR), function (Browser $browser) { | ||||
$browser->assertToastTitle('Error') | $browser->assertToastTitle('Error') | ||||
->assertToastMessage('Form validation error') | ->assertToastMessage('Form validation error') | ||||
->closeToast(); | ->closeToast(); | ||||
}) | }) | ||||
->with('@form', function (Browser $browser) { | ->with('@form', function (Browser $browser) { | ||||
$browser->with(new ListInput('#aliases'), function (Browser $browser) { | $browser->with(new ListInput('#aliases'), function (Browser $browser) { | ||||
$browser->assertFormError(1, 'The specified alias is invalid.', false); | $browser->assertFormError(1, 'The specified alias is invalid.', false); | ||||
}); | }); | ||||
}); | }); | ||||
// Successful account creation | // Successful account creation | ||||
$browser->with('@form', function (Browser $browser) { | $browser->with('@form', function (Browser $browser) { | ||||
$browser->with(new ListInput('#aliases'), function (Browser $browser) { | $browser->with(new ListInput('#aliases'), function (Browser $browser) { | ||||
$browser->removeListEntry(1) | $browser->removeListEntry(1) | ||||
->addListEntry('john.rambo2@kolab.org'); | ->addListEntry('julia.roberts2@kolab.org'); | ||||
}) | }) | ||||
->click('button[type=submit]'); | ->click('button[type=submit]'); | ||||
}) | }) | ||||
->with(new Toast(Toast::TYPE_SUCCESS), function (Browser $browser) { | ->with(new Toast(Toast::TYPE_SUCCESS), function (Browser $browser) { | ||||
$browser->assertToastTitle('') | $browser->assertToastTitle('') | ||||
->assertToastMessage('User created successfully') | ->assertToastMessage('User created successfully') | ||||
->closeToast(); | ->closeToast(); | ||||
}) | |||||
// check redirection to users list | |||||
->waitForLocation('/users') | |||||
->on(new UserList()) | |||||
->whenAvailable('@table', function (Browser $browser) { | |||||
// TODO: This will not work until we handle entitlements on user creation | |||||
// $browser->assertElementsCount('tbody tr', 3) | |||||
// ->assertSeeIn('tbody tr:nth-child(3) a', 'julia.roberts@kolab.org'); | |||||
}); | }); | ||||
// TODO: assert redirect to users list | $julia = User::where('email', 'julia.roberts@kolab.org')->first(); | ||||
$alias = UserAlias::where('user_id', $julia->id)->where('alias', 'julia.roberts2@kolab.org')->first(); | |||||
$john = User::where('email', 'john.rambo@kolab.org')->first(); | |||||
$alias = UserAlias::where('user_id', $john->id)->where('alias', 'john.rambo2@kolab.org')->first(); | |||||
$this->assertTrue(!empty($alias)); | $this->assertTrue(!empty($alias)); | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* Test user delete | |||||
* | |||||
* @depends testNewUser | |||||
*/ | |||||
public function testDeleteUser(): void | |||||
{ | |||||
// First create a new user | |||||
$john = $this->getTestUser('john@kolab.org'); | |||||
$julia = $this->getTestUser('julia.roberts@kolab.org'); | |||||
$package_kolab = \App\Package::where('title', 'kolab')->first(); | |||||
$john->assignPackage($package_kolab, $julia); | |||||
// Test deleting non-controller user | |||||
$this->browse(function (Browser $browser) { | |||||
$browser->visit(new UserList()) | |||||
->whenAvailable('@table', function (Browser $browser) { | |||||
$browser->assertElementsCount('tbody tr', 3) | |||||
->assertSeeIn('tbody tr:nth-child(3) a', 'julia.roberts@kolab.org') | |||||
->click('tbody tr:nth-child(3) button.button-delete'); | |||||
}) | |||||
->with(new Dialog('#delete-warning'), function (Browser $browser) { | |||||
$browser->assertSeeIn('@title', 'Delete julia.roberts@kolab.org') | |||||
->assertFocused('@button-cancel') | |||||
->assertSeeIn('@button-cancel', 'Cancel') | |||||
->assertSeeIn('@button-action', 'Delete') | |||||
->click('@button-cancel'); | |||||
}) | |||||
->whenAvailable('@table', function (Browser $browser) { | |||||
$browser->click('tbody tr:nth-child(3) button.button-delete'); | |||||
}) | |||||
->with(new Dialog('#delete-warning'), function (Browser $browser) { | |||||
$browser->click('@button-action'); | |||||
}) | |||||
->with(new Toast(Toast::TYPE_SUCCESS), function (Browser $browser) { | |||||
$browser->assertToastTitle('') | |||||
->assertToastMessage('User deleted successfully') | |||||
->closeToast(); | |||||
}) | |||||
->with('@table', function (Browser $browser) { | |||||
$browser->assertElementsCount('tbody tr', 2) | |||||
->assertSeeIn('tbody tr:nth-child(1) a', 'jack@kolab.org') | |||||
->assertSeeIn('tbody tr:nth-child(2) a', 'john@kolab.org'); | |||||
}); | |||||
$julia = User::where('email', 'julia.roberts@kolab.org')->first(); | |||||
$this->assertTrue(empty($julia)); | |||||
// Test clicking Delete on the controller record redirects to /profile/delete | |||||
$browser | |||||
->with('@table', function (Browser $browser) { | |||||
$browser->click('tbody tr:nth-child(2) button.button-delete'); | |||||
}) | |||||
->waitForLocation('/profile/delete'); | |||||
}); | |||||
// Test that non-controller user cannot see/delete himself on the users list | |||||
// Note: Access to /profile/delete page is tested in UserProfileTest.php | |||||
$this->browse(function (Browser $browser) { | |||||
$browser->visit('/logout') | |||||
->on(new Home()) | |||||
->submitLogon('jack@kolab.org', 'simple123', true) | |||||
->visit(new UserList()) | |||||
->whenAvailable('@table', function (Browser $browser) { | |||||
$browser->assertElementsCount('tbody tr', 0); | |||||
}); | |||||
}); | |||||
// TODO: Test what happens with the logged in user session after he's been deleted by another user | |||||
} | |||||
} | } |