+
-
+
@@ -61,7 +67,7 @@
-
+
{{ $t('user.pass-link-label') }} {{ passwordLink }}
@@ -75,14 +81,14 @@
-
+
{{ $t('btn.submit') }}
-
-
- {{ $t('user.delete-text') }}
+
+
{{ $t('user.profile-delete-text1') }} {{ $t('user.profile-delete-warning') }}.
+
{{ $t('user.profile-delete-text2') }}
+
+
{{ $t('user.profile-delete-contact', { app: $root.appName }) }}
+
+ {{ $t('user.delete-text') }}
@@ -159,33 +221,63 @@
},
data() {
return {
+ countries: window.config.countries,
+ isSelf: false,
passwordLinkCode: '',
passwordMode: '',
user_id: null,
user: { aliases: [], config: [] },
- status: {}
+ supportEmail: window.config['app.support_email'],
+ status: {},
+ successRoute: { name: 'users' }
}
},
computed: {
- isSelf: function () {
- return this.user_id == this.$root.authInfo.id
+ deleteButton: function () {
+ return {
+ className: 'btn-danger modal-action',
+ dismiss: 'modal',
+ label: this.isSelf ? 'user.profile-delete' : 'btn.delete',
+ icon: 'trash-can'
+ }
+ },
+ isController: function () {
+ return this.$root.hasPermission('users')
},
passwordLink: function () {
return this.$root.appUrl + '/password-reset/' + this.passwordLinkCode
+ },
+ tabs: function () {
+ let tabs = ['form.general']
+
+ if (this.user_id === 'new') {
+ return tabs
+ }
+
+ if (this.isController) {
+ tabs.push('form.settings')
+ }
+
+ tabs.push('form.personal')
+
+ return tabs
}
},
created() {
- this.user_id = this.$route.params.user
+ if (this.$route.name === 'settings') {
+ this.user_id = this.$root.authInfo.id
+ this.successRoute = null
+ } else {
+ this.user_id = this.$route.params.user
+ }
+
+ this.isSelf = this.user_id == this.$root.authInfo.id
if (this.user_id !== 'new') {
axios.get('/api/v4/users/' + this.user_id, { loader: true })
.then(response => {
- this.user = response.data
- this.user.first_name = response.data.settings.first_name
- this.user.last_name = response.data.settings.last_name
- this.user.organization = response.data.settings.organization
+ this.user = { ...response.data, ...response.data.settings }
this.status = response.data.statusInfo
-
this.passwordLinkCode = this.user.passwordLinkCode
})
.catch(this.$root.errorHandler)
@@ -250,14 +342,21 @@
submit() {
this.$root.clearFormValidation($('#general form'))
+ let props = this.isController ? ['aliases'] : []
+ if (this.user_id === 'new') {
+ props = props.concat(['email', 'first_name', 'last_name', 'organization'])
+ }
+
let method = 'post'
let location = '/api/v4/users'
- let post = this.$root.pick(this.user, ['aliases', 'email', 'first_name', 'last_name', 'organization'])
+ let post = this.$root.pick(this.user, props)
if (this.user_id !== 'new') {
method = 'put'
location += '/' + this.user_id
- post.skus = this.$refs.skus.getSkus()
+ if (this.$refs.skus) {
+ post.skus = this.$refs.skus.getSkus()
+ }
} else {
post.package = $('#user-packages input:checked').val()
}
@@ -276,7 +375,27 @@
}
this.$toast.success(response.data.message)
- this.$router.push({ name: 'users' })
+ if (this.successRoute) {
+ this.$router.push(this.successRoute)
+ }
+ })
+ },
+ submitPersonalSettings() {
+ this.$root.clearFormValidation($('#personal form'))
+
+ let post = this.$root.pick(this.user, ['first_name', 'last_name', 'organization', 'phone',
+ 'country', 'external_email', 'billing_address'])
+
+ axios.put('/api/v4/users' + '/' + this.user_id, post)
+ .then(response => {
+ if (response.data.statusInfo) {
+ this.$root.authInfo.statusInfo = response.data.statusInfo
+ }
+
+ this.$toast.success(response.data.message)
+ if (this.successRoute) {
+ this.$router.push(this.successRoute)
+ }
})
},
submitSettings() {
@@ -305,18 +424,14 @@
.then(response => {
if (response.data.status == 'success') {
this.$toast.success(response.data.message)
- this.$router.push({ name: 'users' })
+
+ if (this.isSelf) {
+ this.$root.logoutUser()
+ } else {
+ this.$router.push(this.successRoute)
+ }
}
})
- },
- showDeleteConfirmation() {
- if (this.user_id == this.$root.authInfo.id) {
- // Deleting self, redirect to /profile/delete page
- this.$router.push({ name: 'profile-delete' })
- } else {
- // Display the warning
- this.$refs.deleteWarning.show()
- }
}
}
}
diff --git a/src/resources/vue/User/Profile.vue b/src/resources/vue/User/Profile.vue
deleted file mode 100644
--- a/src/resources/vue/User/Profile.vue
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
-
- {{ $t('user.profile-title') }}
-
- {{ $t('user.profile-delete') }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/resources/vue/User/ProfileDelete.vue b/src/resources/vue/User/ProfileDelete.vue
deleted file mode 100644
--- a/src/resources/vue/User/ProfileDelete.vue
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
{{ $t('user.delete-account') }}
-
-
{{ $t('user.profile-delete-text1') }} {{ $t('user.profile-delete-warning') }}.
-
{{ $t('user.profile-delete-text2') }}
-
-
{{ $t('user.profile-delete-contact', { app: $root.appName }) }}
-
- {{ $t('btn.cancel') }}
- {{ $t('user.profile-delete') }}
-
-
-
-
-
-
-
-
diff --git a/src/tests/Browser/DomainTest.php b/src/tests/Browser/DomainTest.php
--- a/src/tests/Browser/DomainTest.php
+++ b/src/tests/Browser/DomainTest.php
@@ -13,7 +13,6 @@
use Tests\Browser\Pages\DomainList;
use Tests\Browser\Pages\Home;
use Tests\TestCaseDusk;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
class DomainTest extends TestCaseDusk
{
@@ -223,7 +222,7 @@
->on(new Home())
->submitLogon('jack@kolab.org', 'simple123', true)
->on(new Dashboard())
- ->assertVisible('@links a.link-profile')
+ ->assertVisible('@links a.link-settings')
->assertMissing('@links a.link-domains')
->assertMissing('@links a.link-users')
->assertMissing('@links a.link-wallet');
diff --git a/src/tests/Browser/LogonTest.php b/src/tests/Browser/LogonTest.php
--- a/src/tests/Browser/LogonTest.php
+++ b/src/tests/Browser/LogonTest.php
@@ -7,9 +7,7 @@
use Tests\Browser\Components\Toast;
use Tests\Browser\Pages\Dashboard;
use Tests\Browser\Pages\Home;
-use Tests\Browser\Pages\UserProfile;
use Tests\TestCaseDusk;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
class LogonTest extends TestCaseDusk
{
@@ -133,7 +131,7 @@
->submitLogon('john@kolab.org', 'simple123', true)
// Checks if we're really on Dashboard page
->on(new Dashboard())
- ->assertVisible('@links a.link-profile')
+ ->assertVisible('@links a.link-settings')
->assertVisible('@links a.link-domains')
->assertVisible('@links a.link-users')
->assertVisible('@links a.link-wallet')
@@ -278,15 +276,17 @@
public function testAfterLogonRedirect(): void
{
$this->browse(function (Browser $browser) {
- // User is logged in
- $browser->visit(new UserProfile());
-
- // Test redirect if the token is invalid
- $browser->script("localStorage.setItem('token', '123')");
- $browser->refresh()
+ // User is logged in, visit the My account page
+ $browser->visit('/settings')
+ // invalidate the session token
+ ->execScript("localStorage.setItem('token', '123')")
+ // refresh the page
+ ->refresh()
->on(new Home())
+ // log in the user
->submitLogon('john@kolab.org', 'simple123', false)
- ->waitForLocation('/profile');
+ // wait for a "redirect" to the My account page
+ ->waitForLocation('/settings');
});
}
}
diff --git a/src/tests/Browser/Pages/Settings.php b/src/tests/Browser/Pages/Policies.php
rename from src/tests/Browser/Pages/Settings.php
rename to src/tests/Browser/Pages/Policies.php
--- a/src/tests/Browser/Pages/Settings.php
+++ b/src/tests/Browser/Pages/Policies.php
@@ -4,7 +4,7 @@
use Laravel\Dusk\Page;
-class Settings extends Page
+class Policies extends Page
{
/**
* Get the URL for the page.
@@ -13,7 +13,7 @@
*/
public function url(): string
{
- return '/settings';
+ return '/policies';
}
/**
@@ -38,7 +38,7 @@
{
return [
'@app' => '#app',
- '@form' => '#settings form',
+ '@form' => '#policies form',
];
}
}
diff --git a/src/tests/Browser/Pages/UserInfo.php b/src/tests/Browser/Pages/UserInfo.php
--- a/src/tests/Browser/Pages/UserInfo.php
+++ b/src/tests/Browser/Pages/UserInfo.php
@@ -25,7 +25,7 @@
*/
public function assert($browser)
{
- $browser->waitFor('@form')
+ $browser->waitFor('@general form')
->waitUntilMissing('.app-loader');
}
@@ -38,11 +38,11 @@
{
return [
'@app' => '#app',
- '@form' => '#user-info form',
'@nav' => 'ul.nav-tabs',
'@packages' => '#user-packages',
'@settings' => '#settings',
'@general' => '#general',
+ '@personal' => '#personal',
'@skus' => '#user-skus',
'@status' => '#status-box',
];
diff --git a/src/tests/Browser/Pages/UserProfile.php b/src/tests/Browser/Pages/UserProfile.php
deleted file mode 100644
--- a/src/tests/Browser/Pages/UserProfile.php
+++ /dev/null
@@ -1,45 +0,0 @@
-assertPathIs($this->url())
- ->waitUntilMissing('@app .app-loader')
- ->assertSeeIn('#user-profile .card-title', 'Your profile');
- }
-
- /**
- * Get the element shortcuts for the page.
- *
- * @return array
- */
- public function elements(): array
- {
- return [
- '@app' => '#app',
- '@form' => '#user-profile form',
- ];
- }
-}
diff --git a/src/tests/Browser/PasswordResetTest.php b/src/tests/Browser/PasswordResetTest.php
--- a/src/tests/Browser/PasswordResetTest.php
+++ b/src/tests/Browser/PasswordResetTest.php
@@ -10,7 +10,6 @@
use Tests\Browser\Pages\Home;
use Tests\Browser\Pages\PasswordReset;
use Tests\TestCaseDusk;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
class PasswordResetTest extends TestCaseDusk
{
diff --git a/src/tests/Browser/SettingsTest.php b/src/tests/Browser/PoliciesTest.php
copy from src/tests/Browser/SettingsTest.php
copy to src/tests/Browser/PoliciesTest.php
--- a/src/tests/Browser/SettingsTest.php
+++ b/src/tests/Browser/PoliciesTest.php
@@ -7,24 +7,24 @@
use Tests\Browser\Components\Toast;
use Tests\Browser\Pages\Dashboard;
use Tests\Browser\Pages\Home;
-use Tests\Browser\Pages\Settings;
+use Tests\Browser\Pages\Policies;
use Tests\TestCaseDusk;
-class SettingsTest extends TestCaseDusk
+class PoliciesTest extends TestCaseDusk
{
/**
- * Test settings page (unauthenticated)
+ * Test Policies page (unauthenticated)
*/
- public function testSettingsUnauth(): void
+ public function testPoliciesUnauth(): void
{
// Test that the page requires authentication
$this->browse(function (Browser $browser) {
- $browser->visit('/settings')->on(new Home());
+ $browser->visit('/policies')->on(new Home());
});
}
/**
- * Test settings "box" on Dashboard
+ * Test Policies "box" on Dashboard
*/
public function testDashboard(): void
{
@@ -33,8 +33,8 @@
$browser->visit(new Home())
->submitLogon('jack@kolab.org', 'simple123', true)
->on(new Dashboard())
- ->assertMissing('@links .link-settings')
- ->visit('/settings')
+ ->assertMissing('@links .link-policies')
+ ->visit('/policies')
->assertErrorPage(403)
->within(new Menu(), function (Browser $browser) {
$browser->clickMenuItem('logout');
@@ -45,25 +45,25 @@
->on(new Home())
->submitLogon('john@kolab.org', 'simple123', true)
->on(new Dashboard())
- ->assertSeeIn('@links .link-settings svg + span', 'Settings');
+ ->assertSeeIn('@links .link-policies svg + span', 'Policies');
});
}
/**
- * Test Settings page
+ * Test Policies page
*
* @depends testDashboard
*/
- public function testSettings(): void
+ public function testPolicies(): void
{
$john = $this->getTestUser('john@kolab.org');
$john->setSetting('password_policy', 'min:5,max:100,lower');
$john->setSetting('max_password_age', null);
$this->browse(function (Browser $browser) {
- $browser->click('@links .link-settings')
- ->on(new Settings())
- ->assertSeeIn('#settings .card-title', 'Settings')
+ $browser->click('@links .link-policies')
+ ->on(new Policies())
+ ->assertSeeIn('#policies .card-title', 'Policies')
// Password policy
->assertSeeIn('@form .row:nth-child(1) > label', 'Password Policy')
->with('@form #password_policy', function (Browser $browser) {
diff --git a/src/tests/Browser/SettingsTest.php b/src/tests/Browser/SettingsTest.php
--- a/src/tests/Browser/SettingsTest.php
+++ b/src/tests/Browser/SettingsTest.php
@@ -2,16 +2,51 @@
namespace Tests\Browser;
+use App\User;
use Tests\Browser;
-use Tests\Browser\Components\Menu;
+use Tests\Browser\Components\Dialog;
+use Tests\Browser\Components\ListInput;
use Tests\Browser\Components\Toast;
use Tests\Browser\Pages\Dashboard;
use Tests\Browser\Pages\Home;
-use Tests\Browser\Pages\Settings;
+use Tests\Browser\Pages\UserInfo;
use Tests\TestCaseDusk;
class SettingsTest extends TestCaseDusk
{
+ private $profile = [
+ 'first_name' => 'John',
+ 'last_name' => 'Doe',
+ 'currency' => 'USD',
+ 'country' => 'US',
+ 'billing_address' => "601 13th Street NW\nSuite 900 South\nWashington, DC 20005",
+ 'external_email' => 'john.doe.external@gmail.com',
+ 'phone' => '+1 509-248-1111',
+ 'organization' => 'Kolab Developers',
+ ];
+
+ /**
+ * {@inheritDoc}
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ User::where('email', 'john@kolab.org')->first()->setSettings($this->profile);
+ $this->deleteTestUser('profile-delete@kolabnow.com');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function tearDown(): void
+ {
+ User::where('email', 'john@kolab.org')->first()->setSettings($this->profile);
+ $this->deleteTestUser('profile-delete@kolabnow.com');
+
+ parent::tearDown();
+ }
+
/**
* Test settings page (unauthenticated)
*/
@@ -24,97 +59,194 @@
}
/**
- * Test settings "box" on Dashboard
+ * Test settings page (wallet controller)
*/
- public function testDashboard(): void
+ public function testSettingsController(): void
{
$this->browse(function (Browser $browser) {
- // Test a user that is not an account owner
+ $user = $this->getTestUser('john@kolab.org');
+ $user->setSetting('password_policy', 'min:10,upper,digit');
+
$browser->visit(new Home())
- ->submitLogon('jack@kolab.org', 'simple123', true)
- ->on(new Dashboard())
- ->assertMissing('@links .link-settings')
- ->visit('/settings')
- ->assertErrorPage(403)
- ->within(new Menu(), function (Browser $browser) {
- $browser->clickMenuItem('logout');
- });
-
- // Test the account owner
- $browser->waitForLocation('/login')
- ->on(new Home())
->submitLogon('john@kolab.org', 'simple123', true)
->on(new Dashboard())
- ->assertSeeIn('@links .link-settings svg + span', 'Settings');
+ ->assertSeeIn('@links .link-settings', 'My account')
+ ->click('@links .link-settings')
+ ->on(new UserInfo())
+ ->assertSeeIn('#user-info button.button-delete', 'Delete account')
+ ->assertSeeIn('#user-info .card-title', 'My account')
+ ->assertSeeIn('@nav #tab-general', 'General')
+ ->with('@general', function (Browser $browser) use ($user) {
+ $browser->assertSeeIn('div.row:nth-child(1) label', 'Status (Customer No.)')
+ ->assertSeeIn('div.row:nth-child(1) #status', 'Active')
+ ->assertSeeIn('div.row:nth-child(1) #userid', "({$user->id})")
+ ->assertSeeIn('div.row:nth-child(2) label', 'Email')
+ ->assertValue('div.row:nth-child(2) input[type=text]', $user->email)
+ ->assertDisabled('div.row:nth-child(2) input[type=text]')
+ ->assertSeeIn('div.row:nth-child(3) label', 'Email Aliases')
+ ->assertVisible('div.row:nth-child(3) .list-input')
+ ->with(new ListInput('#aliases'), function (Browser $browser) {
+ $browser->assertListInputValue(['john.doe@kolab.org'])
+ ->assertValue('@input', '');
+ })
+ ->assertSeeIn('div.row:nth-child(4) label', 'Password')
+ ->assertValue('div.row:nth-child(4) input#password', '')
+ ->assertValue('div.row:nth-child(4) input#password_confirmation', '')
+ ->assertAttribute('#password', 'placeholder', 'Password')
+ ->assertAttribute('#password_confirmation', 'placeholder', 'Confirm Password')
+ ->assertMissing('div.row:nth-child(4) .btn-group')
+ ->assertMissing('div.row:nth-child(4) #password-link')
+ ->assertSeeIn('div.row:nth-child(5) label', 'Subscriptions')
+ ->assertVisible('div.row:nth-child(5) table');
+ })
+ ->assertSeeIn('@nav #tab-settings', 'Settings')
+ ->click('@nav #tab-settings')
+ ->with('@settings', function (Browser $browser) {
+ $browser->assertSeeIn('div.row:nth-child(1) label', 'Greylisting')
+ ->click('div.row:nth-child(1) input[type=checkbox]');
+ })
+ ->assertSeeIn('@nav #tab-personal', 'Personal information')
+ ->click('@nav #tab-personal')
+ ->with('@personal', function (Browser $browser) {
+ $browser->assertSeeIn('div.row:nth-child(1) label', 'First Name')
+ ->assertValue('div.row:nth-child(1) input[type=text]', $this->profile['first_name'])
+ ->assertSeeIn('div.row:nth-child(2) label', 'Last Name')
+ ->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['last_name'])
+ ->assertSeeIn('div.row:nth-child(3) label', 'Organization')
+ ->assertValue('div.row:nth-child(3) input[type=text]', $this->profile['organization'])
+ ->assertSeeIn('div.row:nth-child(4) label', 'Phone')
+ ->assertValue('div.row:nth-child(4) input[type=text]', $this->profile['phone'])
+ ->assertSeeIn('div.row:nth-child(5) label', 'External Email')
+ ->assertValue('div.row:nth-child(5) input[type=text]', $this->profile['external_email'])
+ ->assertSeeIn('div.row:nth-child(6) label', 'Address')
+ ->assertValue('div.row:nth-child(6) textarea', $this->profile['billing_address'])
+ ->assertSeeIn('div.row:nth-child(7) label', 'Country')
+ ->assertValue('div.row:nth-child(7) select', $this->profile['country'])
+ // Set some fields and submit
+ ->type('#first_name', 'Arnie')
+ ->vueClear('#last_name')
+ ->click('button[type=submit]');
+ })
+ ->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.');
});
}
/**
- * Test Settings page
- *
- * @depends testDashboard
+ * Test settings page (non-controller user)
*/
- public function testSettings(): void
+ public function testProfileNonController(): void
{
- $john = $this->getTestUser('john@kolab.org');
- $john->setSetting('password_policy', 'min:5,max:100,lower');
- $john->setSetting('max_password_age', null);
+ $user = $this->getTestUser('john@kolab.org');
+ $user->setSetting('password_policy', 'min:10,upper,digit');
+ // Test acting as non-controller
$this->browse(function (Browser $browser) {
- $browser->click('@links .link-settings')
- ->on(new Settings())
- ->assertSeeIn('#settings .card-title', 'Settings')
- // Password policy
- ->assertSeeIn('@form .row:nth-child(1) > label', 'Password Policy')
- ->with('@form #password_policy', function (Browser $browser) {
- $browser->assertElementsCount('li', 7)
- ->assertSeeIn('li:nth-child(1) label', 'Minimum password length')
- ->assertChecked('li:nth-child(1) input[type=checkbox]')
- ->assertDisabled('li:nth-child(1) input[type=checkbox]')
- ->assertValue('li:nth-child(1) input[type=text]', '5')
- ->assertSeeIn('li:nth-child(2) label', 'Maximum password length')
- ->assertChecked('li:nth-child(2) input[type=checkbox]')
- ->assertDisabled('li:nth-child(2) input[type=checkbox]')
- ->assertValue('li:nth-child(2) input[type=text]', '100')
- ->assertSeeIn('li:nth-child(3) label', 'Password contains a lower-case character')
- ->assertChecked('li:nth-child(3) input[type=checkbox]')
- ->assertMissing('li:nth-child(3) input[type=text]')
- ->assertSeeIn('li:nth-child(4) label', 'Password contains an upper-case character')
- ->assertNotChecked('li:nth-child(4) input[type=checkbox]')
- ->assertMissing('li:nth-child(4) input[type=text]')
- ->assertSeeIn('li:nth-child(5) label', 'Password contains a digit')
- ->assertNotChecked('li:nth-child(5) input[type=checkbox]')
- ->assertMissing('li:nth-child(5) input[type=text]')
- ->assertSeeIn('li:nth-child(6) label', 'Password contains a special character')
- ->assertNotChecked('li:nth-child(6) input[type=checkbox]')
- ->assertMissing('li:nth-child(6) input[type=text]')
- ->assertSeeIn('li:nth-child(7) label', 'Password cannot be the same as the last')
- ->assertNotChecked('li:nth-child(7) input[type=checkbox]')
- ->assertMissing('li:nth-child(7) input[type=text]')
- ->assertSelected('li:nth-child(7) select', 3)
- ->assertSelectHasOptions('li:nth-child(7) select', [1,2,3,4,5,6])
- // Change the policy
- ->type('li:nth-child(1) input[type=text]', '11')
- ->type('li:nth-child(2) input[type=text]', '120')
- ->click('li:nth-child(3) input[type=checkbox]')
- ->click('li:nth-child(4) input[type=checkbox]');
+ $browser->visit(new Home())
+ ->submitLogon('jack@kolab.org', 'simple123', true)
+ ->on(new Dashboard())
+ ->assertSeeIn('@links .link-settings', 'My account')
+ ->click('@links .link-settings')
+ ->on(new UserInfo())
+ ->assertMissing('#user-info button.button-delete')
+ ->assertSeeIn('#user-info .card-title', 'My account')
+ ->assertSeeIn('@nav #tab-general', 'General')
+ ->with('@general', function (Browser $browser) {
+ $browser->assertSeeIn('div.row:nth-child(1) label', 'Email')
+ ->assertValue('div.row:nth-child(1) input[type=text]', 'jack@kolab.org')
+ ->assertSeeIn('div.row:nth-child(2) label', 'Password')
+ ->assertValue('div.row:nth-child(2) input#password', '')
+ ->assertValue('div.row:nth-child(2) input#password_confirmation', '')
+ ->assertAttribute('#password', 'placeholder', 'Password')
+ ->assertAttribute('#password_confirmation', 'placeholder', 'Confirm Password')
+ ->assertMissing('div.row:nth-child(2) .btn-group')
+ ->assertMissing('div.row:nth-child(2) #password-link')
+ ->assertMissing('div.row:nth-child(3)')
+ ->whenAvailable('#password_policy', function (Browser $browser) {
+ $browser->assertElementsCount('li', 3)
+ ->assertMissing('li:nth-child(1) svg.text-success')
+ ->assertSeeIn('li:nth-child(1) small', "Minimum password length: 10 characters")
+ ->assertMissing('li:nth-child(2) svg.text-success')
+ ->assertSeeIn('li:nth-child(2) small', "Password contains an upper-case character")
+ ->assertMissing('li:nth-child(3) svg.text-success')
+ ->assertSeeIn('li:nth-child(3) small', "Password contains a digit");
+ });
+ })
+ ->assertMissing('@nav #tab-settings')
+ ->assertSeeIn('@nav #tab-personal', 'Personal information')
+ ->click('@nav #tab-personal')
+ ->with('@personal', function (Browser $browser) {
+ $browser->assertSeeIn('div.row:nth-child(1) label', 'First Name')
+ ->assertValue('div.row:nth-child(1) input[type=text]', 'Jack')
+ ->assertSeeIn('div.row:nth-child(2) label', 'Last Name')
+ ->assertValue('div.row:nth-child(2) input[type=text]', 'Daniels')
+ ->assertSeeIn('div.row:nth-child(3) label', 'Organization')
+ ->assertSeeIn('div.row:nth-child(4) label', 'Phone')
+ ->assertSeeIn('div.row:nth-child(5) label', 'External Email')
+ ->assertSeeIn('div.row:nth-child(6) label', 'Address')
+ ->assertSeeIn('div.row:nth-child(7) label', 'Country')
+ ->click('button[type=submit]');
})
- ->assertSeeIn('@form .row:nth-child(2) > label', 'Password Retention')
- ->with('@form #password_retention', function (Browser $browser) {
- $browser->assertElementsCount('li', 1)
- ->assertSeeIn('li:nth-child(1) label', 'Require a password change every')
- ->assertNotChecked('li:nth-child(1) input[type=checkbox]')
- ->assertSelected('li:nth-child(1) select', 3)
- ->assertSelectHasOptions('li:nth-child(1) select', [3, 6, 9, 12])
- // change the policy
- ->check('li:nth-child(1) input[type=checkbox]')
- ->select('li:nth-child(1) select', 6);
+ ->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.');
+ });
+
+ $user = $this->getTestUser('profile-delete@kolabnow.com', ['password' => 'simple123']);
+ $oldpassword = $user->password;
+
+ // Test password change
+ $this->browse(function (Browser $browser) use ($user) {
+ $browser->visit(new Home())
+ ->submitLogon($user->email, 'simple123', true)
+ ->on(new Dashboard())
+ ->click('@links .link-settings')
+ ->on(new UserInfo())
+ ->assertSeeIn('@nav #tab-general', 'General')
+ ->with('@general', function (Browser $browser) {
+ $browser
+ ->type('input#password', '12345678')
+ ->type('input#password_confirmation', '12345678')
+ ->click('button[type=submit]');
})
- ->click('button[type=submit]')
- ->assertToast(Toast::TYPE_SUCCESS, 'User settings updated successfully.');
+ ->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.');
});
- $this->assertSame('min:11,max:120,upper', $john->getSetting('password_policy'));
- $this->assertSame('6', $john->getSetting('max_password_age'));
+ $this->assertTrue($oldpassword != $user->fresh()->password);
+ }
+
+ /**
+ * Test deleting an account
+ */
+ public function testAccountDelete(): void
+ {
+ $this->browse(function (Browser $browser) {
+ $user = $this->getTestUser('profile-delete@kolabnow.com', ['password' => 'simple123']);
+
+ $browser->visit(new Home())
+ ->submitLogon('profile-delete@kolabnow.com', 'simple123', true)
+ ->on(new Dashboard())
+ ->assertSeeIn('@links .link-settings', 'My account')
+ ->click('@links .link-settings')
+ ->on(new UserInfo())
+ ->assertSeeIn('#user-info button.button-delete', 'Delete account')
+ ->click('#user-info button.button-delete')
+ ->with(new Dialog('#delete-warning'), function (Browser $browser) {
+ $browser->assertSeeIn('@title', 'Delete this account?')
+ ->assertSeeIn('@body', 'This will delete the account as well as all domains')
+ ->assertSeeIn('@body strong', 'This operation is irreversible')
+ ->assertFocused('@button-cancel')
+ ->assertSeeIn('@button-cancel', 'Cancel')
+ ->assertSeeIn('@button-action', 'Delete account')
+ ->click('@button-cancel');
+ })
+ ->waitUntilMissing('#delete-warning')
+ ->click('#user-info button.button-delete')
+ ->with(new Dialog('#delete-warning'), function (Browser $browser) {
+ $browser->click('@button-action');
+ })
+ ->waitUntilMissing('#delete-warning')
+ ->assertToast(Toast::TYPE_SUCCESS, 'User deleted successfully.')
+ ->on(new Home());
+
+ $this->assertTrue($user->fresh()->trashed());
+ });
}
}
diff --git a/src/tests/Browser/SignupTest.php b/src/tests/Browser/SignupTest.php
--- a/src/tests/Browser/SignupTest.php
+++ b/src/tests/Browser/SignupTest.php
@@ -17,7 +17,6 @@
use Tests\Browser\Pages\PaymentStatus;
use Tests\Browser\Pages\Signup;
use Tests\TestCaseDusk;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
class SignupTest extends TestCaseDusk
{
@@ -410,7 +409,7 @@
->waitUntilMissing('.app-loader')
->on(new Dashboard())
->assertUser('signuptestdusk@' . \config('app.domain'))
- ->assertVisible('@links a.link-profile')
+ ->assertVisible('@links a.link-settings')
->assertMissing('@links a.link-domains')
->assertVisible('@links a.link-users')
->assertVisible('@links a.link-wallet');
@@ -511,7 +510,7 @@
->waitUntilMissing('.app-loader')
->on(new Dashboard())
->assertUser('admin@user-domain-signup.com')
- ->assertVisible('@links a.link-profile')
+ ->assertVisible('@links a.link-settings')
->assertVisible('@links a.link-domains')
->assertVisible('@links a.link-users')
->assertVisible('@links a.link-wallet');
diff --git a/src/tests/Browser/UserProfileTest.php b/src/tests/Browser/UserProfileTest.php
deleted file mode 100644
--- a/src/tests/Browser/UserProfileTest.php
+++ /dev/null
@@ -1,228 +0,0 @@
- 'John',
- 'last_name' => 'Doe',
- 'currency' => 'USD',
- 'country' => 'US',
- 'billing_address' => "601 13th Street NW\nSuite 900 South\nWashington, DC 20005",
- 'external_email' => 'john.doe.external@gmail.com',
- 'phone' => '+1 509-248-1111',
- 'organization' => 'Kolab Developers',
- ];
-
- /**
- * {@inheritDoc}
- */
- public function setUp(): void
- {
- parent::setUp();
-
- User::where('email', 'john@kolab.org')->first()->setSettings($this->profile);
- $this->deleteTestUser('profile-delete@kolabnow.com');
- }
-
- /**
- * {@inheritDoc}
- */
- public function tearDown(): void
- {
- User::where('email', 'john@kolab.org')->first()->setSettings($this->profile);
- $this->deleteTestUser('profile-delete@kolabnow.com');
-
- parent::tearDown();
- }
-
- /**
- * Test profile page (unauthenticated)
- */
- public function testProfileUnauth(): void
- {
- // Test that the page requires authentication
- $this->browse(function (Browser $browser) {
- $browser->visit('/profile')->on(new Home());
- });
- }
-
- /**
- * Test profile page
- */
- public function testProfile(): void
- {
- $user = $this->getTestUser('john@kolab.org');
- $user->setSetting('password_policy', 'min:10,upper,digit');
-
- $this->browse(function (Browser $browser) {
- $browser->visit(new Home())
- ->submitLogon('john@kolab.org', 'simple123', true)
- ->on(new Dashboard())
- ->assertSeeIn('@links .link-profile', 'Your profile')
- ->click('@links .link-profile')
- ->on(new UserProfile())
- ->assertSeeIn('#user-profile .profile-delete', 'Delete account')
- ->whenAvailable('@form', function (Browser $browser) {
- $user = User::where('email', 'john@kolab.org')->first();
- // Assert form content
- $browser->assertFocused('div.row:nth-child(2) input')
- ->assertSeeIn('div.row:nth-child(1) label', 'Customer No.')
- ->assertSeeIn('div.row:nth-child(1) .form-control-plaintext', $user->id)
- ->assertSeeIn('div.row:nth-child(2) label', 'First Name')
- ->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['first_name'])
- ->assertSeeIn('div.row:nth-child(3) label', 'Last Name')
- ->assertValue('div.row:nth-child(3) input[type=text]', $this->profile['last_name'])
- ->assertSeeIn('div.row:nth-child(4) label', 'Organization')
- ->assertValue('div.row:nth-child(4) input[type=text]', $this->profile['organization'])
- ->assertSeeIn('div.row:nth-child(5) label', 'Phone')
- ->assertValue('div.row:nth-child(5) input[type=text]', $this->profile['phone'])
- ->assertSeeIn('div.row:nth-child(6) label', 'External Email')
- ->assertValue('div.row:nth-child(6) input[type=text]', $this->profile['external_email'])
- ->assertSeeIn('div.row:nth-child(7) label', 'Address')
- ->assertValue('div.row:nth-child(7) textarea', $this->profile['billing_address'])
- ->assertSeeIn('div.row:nth-child(8) label', 'Country')
- ->assertValue('div.row:nth-child(8) select', $this->profile['country'])
- ->assertSeeIn('div.row:nth-child(9) label', 'Password')
- ->assertValue('div.row:nth-child(9) input#password', '')
- ->assertValue('div.row:nth-child(9) input#password_confirmation', '')
- ->assertAttribute('#password', 'placeholder', 'Password')
- ->assertAttribute('#password_confirmation', 'placeholder', 'Confirm Password')
- ->whenAvailable('#password_policy', function (Browser $browser) {
- $browser->assertElementsCount('li', 3)
- ->assertMissing('li:nth-child(1) svg.text-success')
- ->assertSeeIn('li:nth-child(1) small', "Minimum password length: 10 characters")
- ->assertMissing('li:nth-child(2) svg.text-success')
- ->assertSeeIn('li:nth-child(2) small', "Password contains an upper-case character")
- ->assertMissing('li:nth-child(3) svg.text-success')
- ->assertSeeIn('li:nth-child(3) small', "Password contains a digit");
- })
- ->assertSeeIn('button[type=submit]', 'Submit');
-
- // Test password policy checking
- $browser->type('#password', '1A')
- ->whenAvailable('#password_policy', function (Browser $browser) {
- $browser->waitFor('li:nth-child(2) svg.text-success')
- ->waitFor('li:nth-child(3) svg.text-success')
- ->assertMissing('li:nth-child(1) svg.text-success');
- })
- ->vueClear('#password');
-
- // Test form error handling
- $browser->type('#phone', 'aaaaaa')
- ->type('#external_email', 'bbbbb')
- ->click('button[type=submit]')
- ->waitFor('#phone + .invalid-feedback')
- ->assertSeeIn('#phone + .invalid-feedback', 'The phone format is invalid.')
- ->assertSeeIn(
- '#external_email + .invalid-feedback',
- 'The external email must be a valid email address.'
- )
- ->assertFocused('#phone')
- ->assertToast(Toast::TYPE_ERROR, 'Form validation error')
- ->clearToasts();
-
- // Clear all fields and submit
- // FIXME: Should any of these fields be required?
- $browser->vueClear('#first_name')
- ->vueClear('#last_name')
- ->vueClear('#organization')
- ->vueClear('#phone')
- ->vueClear('#external_email')
- ->vueClear('#billing_address')
- ->click('button[type=submit]')
- ->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.');
- })
- // On success we're redirected to Dashboard
- ->on(new Dashboard());
- });
- }
-
- /**
- * Test profile of non-controller user
- */
- public function testProfileNonController(): void
- {
- $user = $this->getTestUser('john@kolab.org');
- $user->setSetting('password_policy', 'min:10,upper,digit');
-
- // Test acting as non-controller
- $this->browse(function (Browser $browser) {
- $browser->visit('/logout')
- ->visit(new Home())
- ->submitLogon('jack@kolab.org', 'simple123', true)
- ->on(new Dashboard())
- ->assertSeeIn('@links .link-profile', 'Your profile')
- ->click('@links .link-profile')
- ->on(new UserProfile())
- ->assertMissing('#user-profile .profile-delete')
- ->whenAvailable('@form', function (Browser $browser) {
- // TODO: decide on what fields the non-controller user should be able
- // to see/change
- })
- // Check that the account policy is used
- ->whenAvailable('#password_policy', function (Browser $browser) {
- $browser->assertElementsCount('li', 3)
- ->assertMissing('li:nth-child(1) svg.text-success')
- ->assertSeeIn('li:nth-child(1) small', "Minimum password length: 10 characters")
- ->assertMissing('li:nth-child(2) svg.text-success')
- ->assertSeeIn('li:nth-child(2) small', "Password contains an upper-case character")
- ->assertMissing('li:nth-child(3) svg.text-success')
- ->assertSeeIn('li:nth-child(3) small', "Password contains a digit");
- });
-
- // Test that /profile/delete page is not accessible
- $browser->visit('/profile/delete')
- ->assertErrorPage(403);
- });
- }
-
- /**
- * Test profile delete page
- */
- public function testProfileDelete(): void
- {
- $user = $this->getTestUser('profile-delete@kolabnow.com', ['password' => 'simple123']);
-
- $this->browse(function (Browser $browser) use ($user) {
- $browser->visit('/logout')
- ->on(new Home())
- ->submitLogon('profile-delete@kolabnow.com', 'simple123', true)
- ->on(new Dashboard())
- ->assertSeeIn('@links .link-profile', 'Your profile')
- ->click('@links .link-profile')
- ->on(new UserProfile())
- ->click('#user-profile .profile-delete')
- ->waitForLocation('/profile/delete')
- ->assertSeeIn('#user-delete .card-title', 'Delete this account?')
- ->assertSeeIn('#user-delete .button-cancel', 'Cancel')
- ->assertSeeIn('#user-delete .card-text', 'This operation is irreversible')
- ->assertFocused('#user-delete .button-cancel')
- ->click('#user-delete .button-cancel')
- ->waitForLocation('/profile')
- ->on(new UserProfile());
-
- // Test deleting the user
- $browser->click('#user-profile .profile-delete')
- ->waitForLocation('/profile/delete')
- ->click('#user-delete .button-delete')
- ->waitForLocation('/login')
- ->assertToast(Toast::TYPE_SUCCESS, 'User deleted successfully.');
-
- $this->assertTrue($user->fresh()->trashed());
- });
- }
-
- // TODO: Test that Ned (John's "delegatee") can delete himself
- // TODO: Test that Ned (John's "delegatee") can/can't delete John ?
-}
diff --git a/src/tests/Browser/UsersTest.php b/src/tests/Browser/UsersTest.php
--- a/src/tests/Browser/UsersTest.php
+++ b/src/tests/Browser/UsersTest.php
@@ -19,7 +19,6 @@
use Tests\Browser\Pages\UserList;
use Tests\Browser\Pages\Wallet as WalletPage;
use Tests\TestCaseDusk;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
class UsersTest extends TestCaseDusk
{
@@ -28,6 +27,11 @@
'last_name' => 'Doe',
'organization' => 'Kolab Developers',
'limit_geo' => null,
+ 'currency' => 'USD',
+ 'country' => 'US',
+ 'billing_address' => "601 13th Street NW\nSuite 900 South\nWashington, DC 20005",
+ 'external_email' => 'john.doe.external@gmail.com',
+ 'phone' => '+1 509-248-1111',
];
/**
@@ -89,9 +93,9 @@
}
/**
- * Test user account editing page (not profile page)
+ * Test user page - General tab
*/
- public function testInfo(): void
+ public function testUserGeneralTab(): void
{
$this->browse(function (Browser $browser) {
$john = $this->getTestUser('john@kolab.org');
@@ -106,45 +110,28 @@
->submitLogon('john@kolab.org', 'simple123', false)
->on(new UserInfo())
->assertSeeIn('#user-info .card-title', 'User account')
+ ->assertSeeIn('@nav #tab-general', 'General')
->with('@general', function (Browser $browser) {
- // Assert form content
+ // Assert the General tab content
$browser->assertSeeIn('div.row:nth-child(1) label', 'Status')
->assertSeeIn('div.row:nth-child(1) #status', 'Active')
- ->assertFocused('div.row:nth-child(2) input')
- ->assertSeeIn('div.row:nth-child(2) label', 'First Name')
- ->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['first_name'])
- ->assertSeeIn('div.row:nth-child(3) label', 'Last Name')
- ->assertValue('div.row:nth-child(3) input[type=text]', $this->profile['last_name'])
- ->assertSeeIn('div.row:nth-child(4) label', 'Organization')
- ->assertValue('div.row:nth-child(4) input[type=text]', $this->profile['organization'])
- ->assertSeeIn('div.row:nth-child(5) label', 'Email')
- ->assertValue('div.row:nth-child(5) input[type=text]', 'john@kolab.org')
- ->assertDisabled('div.row:nth-child(5) input[type=text]')
- ->assertSeeIn('div.row:nth-child(6) label', 'Email Aliases')
- ->assertVisible('div.row:nth-child(6) .list-input')
+ ->assertSeeIn('div.row:nth-child(2) label', 'Email')
+ ->assertValue('div.row:nth-child(2) input[type=text]', 'john@kolab.org')
+ ->assertDisabled('div.row:nth-child(2) input[type=text]')
+ ->assertSeeIn('div.row:nth-child(3) label', 'Email Aliases')
+ ->assertVisible('div.row:nth-child(3) .list-input')
->with(new ListInput('#aliases'), function (Browser $browser) {
$browser->assertListInputValue(['john.doe@kolab.org'])
->assertValue('@input', '');
})
- ->assertSeeIn('div.row:nth-child(7) label', 'Password')
- ->assertValue('div.row:nth-child(7) input#password', '')
- ->assertValue('div.row:nth-child(7) input#password_confirmation', '')
+ ->assertSeeIn('div.row:nth-child(4) label', 'Password')
+ ->assertValue('div.row:nth-child(4) input#password', '')
+ ->assertValue('div.row:nth-child(4) input#password_confirmation', '')
->assertAttribute('#password', 'placeholder', 'Password')
->assertAttribute('#password_confirmation', 'placeholder', 'Confirm Password')
- ->assertMissing('div.row:nth-child(7) .btn-group')
- ->assertMissing('div.row:nth-child(7) #password-link')
- ->assertSeeIn('button[type=submit]', 'Submit')
- // Clear some fields and submit
- ->vueClear('#first_name')
- ->vueClear('#last_name')
- ->click('button[type=submit]');
- })
- ->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.')
- ->on(new UserList())
- ->click('@table tr:nth-child(3) a')
- ->on(new UserInfo())
- ->assertSeeIn('#user-info .card-title', 'User account')
- ->with('@general', function (Browser $browser) {
+ ->assertMissing('div.row:nth-child(4) .btn-group')
+ ->assertMissing('div.row:nth-child(4) #password-link');
+
// Test error handling (password)
$browser->type('#password', 'aaaaaA')
->vueClear('#password_confirmation')
@@ -176,17 +163,13 @@
})
->scrollTo('button[type=submit]')->pause(500)
->click('button[type=submit]')
- ->assertToast(Toast::TYPE_ERROR, 'Form validation error');
-
- $browser->with(new ListInput('#aliases'), function (Browser $browser) {
- $browser->assertFormError(2, 'The specified alias is invalid.', false);
- });
-
- // Test adding aliases
- $browser->with(new ListInput('#aliases'), function (Browser $browser) {
- $browser->removeListEntry(2)
- ->addListEntry('john.test@kolab.org');
- })
+ ->assertToast(Toast::TYPE_ERROR, 'Form validation error')
+ ->with(new ListInput('#aliases'), function (Browser $browser) {
+ $browser->assertFormError(2, 'The specified alias is invalid.', false)
+ // Test adding aliases
+ ->removeListEntry(2)
+ ->addListEntry('john.test@kolab.org');
+ })
->click('button[type=submit]')
->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.');
})
@@ -199,8 +182,8 @@
// Test subscriptions
$browser->with('@general', function (Browser $browser) {
- $browser->assertSeeIn('div.row:nth-child(8) label', 'Subscriptions')
- ->assertVisible('@skus.row:nth-child(8)')
+ $browser->assertSeeIn('div.row:nth-child(5) label', 'Subscriptions')
+ ->assertVisible('@skus.row:nth-child(5)')
->with('@skus', function ($browser) {
$browser->assertElementsCount('tbody tr', 5)
// Mailbox SKU
@@ -301,7 +284,7 @@
->with('@general', function (Browser $browser) use ($jack, $john, $code) {
// Test displaying an existing password reset link
$link = Browser::$baseUrl . '/password-reset/' . $code->short_code . '-' . $code->code;
- $browser->assertSeeIn('div.row:nth-child(7) label', 'Password')
+ $browser->assertSeeIn('div.row:nth-child(4) label', 'Password')
->assertMissing('#password')
->assertMissing('#password_confirmation')
->assertMissing('#pass-mode-link:checked')
@@ -356,11 +339,76 @@
}
/**
- * Test user settings tab
+ * Test user page - General tab
+ *
+ * @depends testUserGeneralTab
+ */
+ public function testUserPersonalTab(): void
+ {
+ $this->browse(function (Browser $browser) {
+ $john = $this->getTestUser('john@kolab.org');
+ $jack = $this->getTestUser('jack@kolab.org');
+ $jack->setSetting('organization', null);
+
+ // Test the account controller
+ $browser->visit('/user/' . $john->id)
+ ->on(new UserInfo())
+ ->assertSeeIn('@nav #tab-personal', 'Personal information')
+ ->click('#tab-personal')
+ ->with('@personal', function (Browser $browser) {
+ $browser->assertSeeIn('div.row:nth-child(1) label', 'First Name')
+ ->assertValue('div.row:nth-child(1) input[type=text]', $this->profile['first_name'])
+ ->assertSeeIn('div.row:nth-child(2) label', 'Last Name')
+ ->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['last_name'])
+ ->assertSeeIn('div.row:nth-child(3) label', 'Organization')
+ ->assertValue('div.row:nth-child(3) input[type=text]', $this->profile['organization'])
+ ->assertSeeIn('div.row:nth-child(4) label', 'Phone')
+ ->assertValue('div.row:nth-child(4) input[type=text]', $this->profile['phone'])
+ ->assertSeeIn('div.row:nth-child(5) label', 'External Email')
+ ->assertValue('div.row:nth-child(5) input[type=text]', $this->profile['external_email'])
+ ->assertSeeIn('div.row:nth-child(6) label', 'Address')
+ ->assertValue('div.row:nth-child(6) textarea', $this->profile['billing_address'])
+ ->assertSeeIn('div.row:nth-child(7) label', 'Country')
+ ->assertValue('div.row:nth-child(7) select', $this->profile['country'])
+ // Set some fields and submit
+ ->type('#first_name', 'Arnie')
+ ->vueClear('#last_name')
+ ->click('button[type=submit]');
+ })
+ ->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.')
+ ->on(new UserList());
+
+ $this->assertSame('Arnie', $john->getSetting('first_name'));
+ $this->assertSame(null, $john->getSetting('last_name'));
+
+ // Test the non-controller user
+ $browser->visit('/user/' . $jack->id)
+ ->on(new UserInfo())
+ ->click('#tab-personal')
+ ->with('@personal', function (Browser $browser) {
+ $browser->assertSeeIn('div.row:nth-child(1) label', 'First Name')
+ ->assertValue('div.row:nth-child(1) input[type=text]', 'Jack')
+ ->assertSeeIn('div.row:nth-child(2) label', 'Last Name')
+ ->assertValue('div.row:nth-child(2) input[type=text]', 'Daniels')
+ ->assertSeeIn('div.row:nth-child(3) label', 'Organization')
+ ->assertValue('div.row:nth-child(3) input[type=text]', '')
+ // Set some fields and submit
+ ->type('#organization', 'Test')
+ ->click('button[type=submit]');
+ })
+ ->assertToast(Toast::TYPE_SUCCESS, 'User data updated successfully.')
+ ->on(new UserList());
+
+ $this->assertSame('Test', $jack->getSetting('organization'));
+ });
+ }
+
+ /**
+ * Test user page - Settings tab
*
- * @depends testInfo
+ * @depends testUserPersonalTab
*/
- public function testUserSettings(): void
+ public function testUserSettingsTab(): void
{
$john = $this->getTestUser('john@kolab.org');
$john->setSetting('greylist_enabled', null);
@@ -370,11 +418,9 @@
$this->browse(function (Browser $browser) use ($john) {
$browser->visit('/user/' . $john->id)
->on(new UserInfo())
- ->assertElementsCount('@nav a', 2)
- ->assertSeeIn('@nav #tab-general', 'General')
->assertSeeIn('@nav #tab-settings', 'Settings')
->click('@nav #tab-settings')
- ->with('#settings form', function (Browser $browser) {
+ ->with('@settings', function (Browser $browser) {
$browser->assertSeeIn('div.row:nth-child(1) label', 'Greylisting')
->assertMissing('div.row:nth-child(2)') // guam and geo-lockin settings are hidden
->click('div.row:nth-child(1) input[type=checkbox]:checked')
@@ -391,7 +437,7 @@
$browser->refresh()
->on(new UserInfo())
->click('@nav #tab-settings')
- ->with('#settings form', function (Browser $browser) use ($john) {
+ ->with('@settings', function (Browser $browser) use ($john) {
$browser->assertSeeIn('div.row:nth-child(1) label', 'Greylisting')
->assertSeeIn('div.row:nth-child(2) label', 'IMAP proxy')
->assertNotChecked('div.row:nth-child(2) input')
@@ -425,8 +471,6 @@
/**
* Test user adding page
- *
- * @depends testInfo
*/
public function testNewUser(): void
{
@@ -439,6 +483,8 @@
->click('button.user-new')
->on(new UserInfo())
->assertSeeIn('#user-info .card-title', 'New user account')
+ ->assertMissing('@nav #tab-settings')
+ ->assertMissing('@nav #tab-personal')
->with('@general', function (Browser $browser) {
// Assert form content
$browser->assertFocused('div.row:nth-child(1) input')