Browse Source

Fixed root url detection, new tests, default new user group to current

opened group and user removal update fix

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
pull/8824/head
John Molakvoæ (skjnldsv) 8 years ago
parent
commit
549940ddb9
No known key found for this signature in database GPG Key ID: 60C25B8C072916CF
  1. 2
      settings/js/main.js
  2. 2
      settings/js/main.js.map
  3. 29
      settings/src/components/userList.vue
  4. 10
      settings/src/components/userList/userRow.vue
  5. 2
      settings/src/router.js
  6. 4
      settings/src/store/users.js
  7. 98
      tests/acceptance/features/bootstrap/UsersSettingsContext.php
  8. 42
      tests/acceptance/features/users.feature

2
settings/js/main.js
File diff suppressed because it is too large
View File

2
settings/js/main.js.map
File diff suppressed because it is too large
View File

29
settings/src/components/userList.vue

@ -144,12 +144,19 @@ export default {
if (!this.settings.canChangePassword) {
OC.Notification.showTemporary(t('settings', 'Password change is disabled because the master key is disabled'));
}
/**
* Init default language from server data. The use of this.settings
* requires a computed variable,vwhich break the v-model binding of the form,
* this is a much easier solution than getter and setter
* requires a computed variable, which break the v-model binding of the form,
* this is a much easier solution than getter and setter on a computed var
*/
Vue.set(this.newUser.language, 'code', this.settings.defaultLanguage);
/**
* In case the user directly loaded the user list within a group
* the watch won't be triggered. We need to initialize it.
*/
this.setNewUserDefaultGroup(this.$route.params.selectedGroup);
},
computed: {
settings() {
@ -212,6 +219,7 @@ export default {
selectedGroup: function (val, old) {
this.$store.commit('resetUsers');
this.$refs.infiniteLoading.$emit('$InfiniteLoading:reset');
this.setNewUserDefaultGroup(val);
}
},
methods: {
@ -241,8 +249,9 @@ export default {
this.$store.dispatch('getUsers', {
offset: this.usersOffset,
limit: this.usersLimit,
group: this.selectedGroup !== 'disabled' ? this.selectedGroup : ''})
.then((response) => {response?$state.loaded():$state.complete()});
group: this.selectedGroup !== 'disabled' ? this.selectedGroup : ''
})
.then((response) => { response ? $state.loaded() : $state.complete() });
},
resetForm() {
@ -261,6 +270,18 @@ export default {
quota: this.newUser.quota.id,
language: this.newUser.language.code,
}).then(() => this.resetForm());
},
setNewUserDefaultGroup(value) {
if (value && value.length > 0) {
// setting new user default group to the current selected one
let currentGroup = this.groups.find(group => group.id === value);
if (currentGroup) {
this.newUser.groups = [currentGroup];
return;
}
}
// fallback, empty selected group
this.newUser.groups = [];
}
}
}

10
settings/src/components/userList/userRow.vue

@ -9,7 +9,7 @@
<form class="displayName" :class="{'icon-loading-small': loading.displayName}" v-on:submit.prevent="updateDisplayName">
<input :id="'displayName'+user.id+rand" type="text"
:disabled="loading.displayName||loading.all"
:value="user.displayname"
:value="user.displayname" ref="displayName"
autocomplete="new-password" autocorrect="off" autocapitalize="off" spellcheck="false" />
<input type="submit" class="icon-confirm" value="" />
</form>
@ -353,7 +353,13 @@ export default {
let userid = this.user.id;
let gid = group.id;
return this.$store.dispatch('removeUserGroup', {userid, gid})
.then(() => this.loading.groups = false);
.then(() => {
this.loading.groups = false
// remove user from current list if current list is the removed group
if (this.$route.params.selectedGroup === gid) {
this.$store.commit('deleteUser', userid);
}
});
},
/**

2
settings/src/router.js

@ -17,7 +17,7 @@ export default new Router({
mode: 'history',
// if index.php is in the url AND we got this far, then it's working:
// let's keep using index.php in the url
base: window.location.pathname.indexOf('index.php') > 0 ? '/index.php/' : '/',
base: OC.generateUrl(''),
routes: [
{
path: '/:index(index.php/)?settings/users',

4
settings/src/store/users.js

@ -57,8 +57,6 @@ const mutations = {
}
},
addUserGroup(state, { userid, gid }) {
// this should not be needed as it would means the user contains a group
// the server database doesn't have.
let group = state.groups.find(groupSearch => groupSearch.id == gid);
if (group) {
group.usercount++; // increase count
@ -68,8 +66,6 @@ const mutations = {
state.groups = orderGroups(state.groups, state.orderBy);
},
removeUserGroup(state, { userid, gid }) {
// this should not be needed as it would means the user contains a group
// the server database doesn't have.
let group = state.groups.find(groupSearch => groupSearch.id == gid);
if (group) {
group.usercount--; // lower count

98
tests/acceptance/features/bootstrap/UsersSettingsContext.php

@ -77,50 +77,40 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
}
/**
* Warning: you need to watch out for the proper classes order
*
* @return Locator
*/
public static function passwordCellForUser($user) {
return Locator::forThe()->css(".password")->descendantOf(self::rowForUser($user))->
describedAs("Password cell for user $user in Users Settings");
}
/**
* @return Locator
*/
public static function groupsCellForUser($user) {
return Locator::forThe()->css(".groups")->descendantOf(self::rowForUser($user))->
describedAs("Groups cell for user $user in Users Settings");
}
/**
* @return Locator
*/
public static function passwordInputForUser($user) {
return Locator::forThe()->css("input")->descendantOf(self::passwordCellForUser($user))->
describedAs("Password input for user $user in Users Settings");
public static function classCellForUser($class, $user) {
return Locator::forThe()->xpath("//*[@class='$class']")->
descendantOf(self::rowForUser($user))->
describedAs("$class cell for user $user in Users Settings");
}
/**
* @return Locator
*/
public static function groupsInputForUser($user) {
return Locator::forThe()->css("input")->descendantOf(self::groupsCellForUser($user))->
describedAs("Groups input for user $user in Users Settings");
public static function inputForUserInCell($cell, $user) {
return Locator::forThe()->css("input")->
descendantOf(self::classCellForUser($cell, $user))->
describedAs("$cell input for user $user in Users Settings");
}
/**
* @return Locator
*/
public static function groupOptionInInputForUser($user) {
return Locator::forThe()->css(".multiselect__option--highlight")->descendantOf(self::groupsCellForUser($user))->
describedAs("Group option for input for user $user in Users Settings");
public static function optionInInputForUser($cell, $user) {
return Locator::forThe()->css(".multiselect__option--highlight")->
descendantOf(self::classCellForUser($cell, $user))->
describedAs("Selected $cell option in $cell input for user $user in Users Settings");
}
/**
* @return Locator
*/
public static function actionsMenuOf($user) {
return Locator::forThe()->css(".icon-more")->descendantOf(self::rowForUser($user))->
return Locator::forThe()->css(".icon-more")->
descendantOf(self::rowForUser($user))->
describedAs("Actions menu for user $user in Users Settings");
}
@ -130,7 +120,7 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
public static function theAction($action, $user) {
return Locator::forThe()->xpath("//button[normalize-space() = '$action']")->
descendantOf(self::rowForUser($user))->
describedAs("$action action for the user $user");
describedAs("$action action for the user $user row in Users Settings");
}
/**
@ -138,7 +128,16 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
*/
public static function theColumn($column) {
return Locator::forThe()->xpath("//div[@class='user-list-grid']//div[normalize-space() = '$column']")->
describedAs("The $column column");
describedAs("The $column column in Users Settings");
}
/**
* @return Locator
*/
public static function selectedSelectOption($cell, $user) {
return Locator::forThe()->css(".multiselect__single")->
descendantOf(self::classCellForUser($cell, $user))->
describedAs("The selected option of the $cell select for the user $user in Users Settings");
}
/**
@ -172,18 +171,26 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
}
/**
* @When I set the password for :user to :password
* @When I set the :field for :user to :value
*/
public function iSetThePasswordForUserTo($user, $password) {
$this->actor->find(self::passwordInputForUser($user), 2)->setValue($password . "\r");
public function iSetTheFieldForUserTo($field, $user, $value) {
$this->actor->find(self::inputForUserInCell($field, $user), 2)->setValue($value . "\r");
}
/**
* @When I assign the user :user to the group :group
*/
public function iAssignTheUserToTheGroup($user, $group) {
$this->actor->find(self::groupsInputForUser($user))->setValue($group);
$this->actor->find(self::groupOptionInInputForUser($user))->click();
$this->actor->find(self::inputForUserInCell('groups', $user))->setValue($group);
$this->actor->find(self::optionInInputForUser('groups', $user))->click();
}
/**
* @When I set the user :user quota to :quota
*/
public function iSetTheUserQuotaTo($user, $quota) {
$this->actor->find(self::inputForUserInCell('quota', $user))->setValue($quota);
$this->actor->find(self::optionInInputForUser('quota', $user))->click();
}
/**
@ -224,4 +231,29 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
$this->actor->find(self::theColumn($column), 10)->isVisible());
}
/**
* @Then I see that the :field of :user is :value
*/
public function iSeeThatTheFieldOfUserIs($field, $user, $value) {
PHPUnit_Framework_Assert::assertEquals(
$this->actor->find(self::inputForUserInCell($field, $user), 10)->getValue(), $value);
}
/**
* @Then I see that the :cell cell for user :user is done loading
*/
public function iSeeThatTheCellForUserIsDoneLoading($cell, $user) {
WaitFor::elementToBeEventuallyShown($this->actor, self::classCellForUser($cell.' icon-loading-small', $user));
WaitFor::elementToBeEventuallyNotShown($this->actor, self::classCellForUser($cell.' icon-loading-small', $user));
}
/**
* @Then I see that the user quota of :user is :quota
*/
public function iSeeThatTheuserQuotaIs($user, $quota) {
PHPUnit_Framework_Assert::assertEquals(
$this->actor->find(self::selectedSelectOption('quota', $user), 2)->getText(), $quota);
}
}

42
tests/acceptance/features/users.feature

@ -71,3 +71,45 @@ Feature: users
When I toggle the showUserBackend checkbox in the settings
Then I see that the "User backend" column is shown
Scenario: change display name
Given I act as Jane
And I am logged in as the admin
And I open the User settings
And I see that the list of users contains the user user0
And I see that the displayName of user0 is user0
When I set the displayName for user0 to user1
And I see that the displayName cell for user user0 is done loading
Then I see that the displayName of user0 is user1
Scenario: change password
Given I act as Jane
And I am logged in as the admin
And I open the User settings
And I see that the list of users contains the user user0
And I see that the password of user0 is ""
When I set the password for user0 to 123456
And I see that the password cell for user user0 is done loading
# password input is emptied on change
Then I see that the password of user0 is ""
Scenario: change email
Given I act as Jane
And I am logged in as the admin
And I open the User settings
And I see that the list of users contains the user user0
And I see that the mailAddress of user0 is ""
When I set the mailAddress for user0 to "test@nextcloud.com"
And I see that the mailAddress cell for user user0 is done loading
Then I see that the mailAddress of user0 is "test@nextcloud.com"
Scenario: change user quota
Given I act as Jane
And I am logged in as the admin
And I open the User settings
And I see that the list of users contains the user user0
And I see that the user quota of user0 is Unlimited
# disabled because we need the TAB patch:
# https://github.com/minkphp/MinkSelenium2Driver/pull/244
# When I set the user user0 quota to 1GB
# And I see that the quota cell for user user0 is done loading
# Then I see that the user quota of user0 is "1 GB"
Loading…
Cancel
Save