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>
This commit is contained in:
parent
a62c796f07
commit
549940ddb9
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -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 = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
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 groupsCellForUser($user) {
|
||||
return Locator::forThe()->css(".groups")->descendantOf(self::rowForUser($user))->
|
||||
describedAs("Groups cell 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 passwordInputForUser($user) {
|
||||
return Locator::forThe()->css("input")->descendantOf(self::passwordCellForUser($user))->
|
||||
describedAs("Password input 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");
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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…
Reference in New Issue