Merge branch 'feature/create-new-user' into 'master'

Allow to register new user accounts

Closes #17

See merge request pleroma/admin-fe!20
This commit is contained in:
feld 2019-06-11 15:13:48 +00:00
commit 46958a3b3c
9 changed files with 448 additions and 91 deletions

View file

@ -1,4 +1,4 @@
export const users = [
export let users = [
{ active: true, deactivated: false, id: '2', nickname: 'allis', local: true, external: false, roles: { admin: true, moderator: false }, tags: [] },
{ active: true, deactivated: false, id: '10', nickname: 'bob', local: false, external: true, roles: { admin: false, moderator: false }, tags: ['sandbox'] },
{ active: false, deactivated: true, id: 'abc', nickname: 'john', local: true, external: false, roles: { admin: false, moderator: false }, tags: ['strip_media'] }
@ -69,3 +69,9 @@ export async function tagUser(nickname, tag, authHost, token) {
export async function untagUser(nickname, tag, authHost, token) {
return Promise.resolve()
}
export async function createNewAccount(nickname, email, password, authHost, token) {
const newUser = { active: true, deactivated: false, id: '15', nickname, local: true, external: false, roles: { admin: false, moderator: false }, tags: [] }
users = [...users, newUser]
return Promise.resolve()
}

View file

@ -2,33 +2,6 @@ import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { baseName } from './utils'
export async function fetchUsers(filters, authHost, token, page = 1) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users?page=${page}&filters=${filters}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function toggleUserActivation(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/toggle_activation`,
method: 'patch',
headers: authHeaders(token)
})
}
export async function searchUsers(query, filters, authHost, token, page = 1) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users?query=${query}&page=${page}&filters=${filters}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function addRight(nickname, right, authHost, token) {
return await request({
baseURL: baseName(authHost),
@ -38,6 +11,16 @@ export async function addRight(nickname, right, authHost, token) {
})
}
export async function createNewAccount(nickname, email, password, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users',
method: 'post',
headers: authHeaders(token),
data: { nickname, email, password }
})
}
export async function deleteRight(nickname, right, authHost, token) {
return await request({
baseURL: baseName(authHost),
@ -56,6 +39,24 @@ export async function deleteUser(nickname, authHost, token) {
})
}
export async function fetchUsers(filters, authHost, token, page = 1) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users?page=${page}&filters=${filters}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function searchUsers(query, filters, authHost, token, page = 1) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users?query=${query}&page=${page}&filters=${filters}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function tagUser(nicknames, tags, authHost, token) {
return await request({
baseURL: baseName(authHost),
@ -66,6 +67,15 @@ export async function tagUser(nicknames, tags, authHost, token) {
})
}
export async function toggleUserActivation(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/toggle_activation`,
method: 'patch',
headers: authHeaders(token)
})
}
export async function untagUser(nicknames, tags, authHost, token) {
return await request({
baseURL: baseName(authHost),

View file

@ -182,16 +182,46 @@ export default {
revokeModerator: 'Revoke Moderator',
grantModerator: 'Grant Moderator',
activateAccount: 'Activate Account',
activateAccounts: 'Activate Accounts',
deactivateAccount: 'Deactivate Account',
deactivateAccounts: 'Deactivate Accounts',
deleteAccount: 'Delete Account',
deleteAccounts: 'Delete Accounts',
forceNsfw: 'Force posts to be NSFW',
stripMedia: 'Force posts not to have media',
forceUnlisted: 'Force posts to be unlisted',
sandbox: 'Force posts to be followers-only',
disableRemoteSubscription: 'Disallow following user from remote instances',
disableRemoteSubscriptionForMultiple: 'Disallow following users from remote instances',
disableAnySubscription: 'Disallow following user at all',
disableAnySubscriptionForMultiple: 'Disallow following users at all',
selectUsers: 'Select users to apply actions to multiple users',
moderateUsers: 'Moderate multiple users'
moderateUsers: 'Moderate multiple users',
createAccount: 'Create new user account',
apply: 'apply',
remove: 'remove',
grantRightConfirmation: 'Are you sure you want to grant {right} rights to all selected users?',
revokeRightConfirmation: 'Are you sure you want to revoke {right} rights from all selected users?',
activateMultipleUsersConfirmation: 'Are you sure you want to activate accounts of all selected users?',
deactivateMultipleUsersConfirmation: 'Are you sure you want to deactivate accounts of all selected users?',
deleteMultipleUsersConfirmation: 'Are you sure you want to delete accounts of all selected users?',
addTagForMultipleUsersConfirmation: 'Are you sure you want to apply tag to all selected users?',
removeTagFromMultipleUsersConfirmation: 'Are you sure you want to remove tag from all selected users?',
ok: 'Okay',
completed: 'Completed',
cancel: 'Cancel',
canceled: 'Canceled',
username: 'Username',
email: 'E-mail',
password: 'Password',
create: 'Create',
submitFormError: 'There are errors on the form. Please fix them before continuing.',
emptyEmailError: 'Please input the e-mail',
invalidEmailError: 'Please input valid e-mail',
emptyPasswordError: 'Please input the password',
emptyNicknameError: 'Please input the username',
invalidNicknameError: 'Username can include "a-z", "A-Z" and "0-9" characters'
},
usersFilter: {
inputPlaceholder: 'Select filter',

View file

@ -1,4 +1,4 @@
import { addRight, fetchUsers, deleteRight, deleteUser, searchUsers, tagUser, toggleUserActivation, untagUser } from '@/api/users'
import { addRight, createNewAccount, fetchUsers, deleteRight, deleteUser, searchUsers, tagUser, toggleUserActivation, untagUser } from '@/api/users'
const users = {
state: {
@ -61,6 +61,10 @@ const users = {
commit('CLEAR_USERS_FILTERS')
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
},
async CreateNewAccount({ dispatch, getters, state }, { nickname, email, password }) {
await createNewAccount(nickname, email, password, getters.authHost, getters.token)
dispatch('FetchUsers', { page: state.currentPage })
},
async DeleteUser({ commit, getters }, user) {
await deleteUser(user.nickname, getters.authHost, getters.token)
const updatedUser = { ...user, deactivated: true }
@ -83,7 +87,7 @@ const users = {
async SearchUsers({ commit, dispatch, state, getters }, { query, page }) {
if (query.length === 0) {
commit('SET_SEARCH_QUERY', query)
dispatch('FetchUsers', page)
dispatch('FetchUsers', { page })
} else {
commit('SET_LOADING', true)
commit('SET_SEARCH_QUERY', query)

View file

@ -29,22 +29,26 @@
<el-dropdown-item
divided
@click.native="activateMultipleUsers">
{{ $t('users.activateAccount') }}
{{ $t('users.activateAccounts') }}
</el-dropdown-item>
<el-dropdown-item
@click.native="deactivateMultipleUsers">
{{ $t('users.deactivateAccount') }}
{{ $t('users.deactivateAccounts') }}
</el-dropdown-item>
<el-dropdown-item
@click.native="deleteMultipleUsers">
{{ $t('users.deleteAccount') }}
{{ $t('users.deleteAccounts') }}
</el-dropdown-item>
<el-dropdown-item divided class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.forceNsfw') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('force_nsfw')">apply</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('force_nsfw')">remove</el-button>
<el-button size="mini" @click.native="addTagForMultipleUsers('force_nsfw')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('force_nsfw')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
@ -52,8 +56,12 @@
<div class="tag-container">
<span class="tag-text">{{ $t('users.stripMedia') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('strip_media')">apply</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('strip_media')">remove</el-button>
<el-button size="mini" @click.native="addTagForMultipleUsers('strip_media')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('strip_media')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
@ -61,8 +69,12 @@
<div class="tag-container">
<span class="tag-text">{{ $t('users.forceUnlisted') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('force_unlisted')">apply</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('force_unlisted')">remove</el-button>
<el-button size="mini" @click.native="addTagForMultipleUsers('force_unlisted')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('force_unlisted')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
@ -70,26 +82,38 @@
<div class="tag-container">
<span class="tag-text">{{ $t('users.sandbox') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('sandbox')">apply</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('sandbox')">remove</el-button>
<el-button size="mini" @click.native="addTagForMultipleUsers('sandbox')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('sandbox')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.disableRemoteSubscription') }}</span>
<span class="tag-text">{{ $t('users.disableRemoteSubscriptionForMultiple') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('disable_remote_subscription')">apply</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('disable_remote_subscription')">remove</el-button>
<el-button size="mini" @click.native="addTagForMultipleUsers('disable_remote_subscription')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('disable_remote_subscription')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.disableAnySubscription') }}</span>
<span class="tag-text">{{ $t('users.disableAnySubscriptionForMultiple') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('disable_any_subscription')">apply</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('disable_any_subscription')">remove</el-button>
<el-button size="mini" @click.native="addTagForMultipleUsers('disable_any_subscription')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('disable_any_subscription')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
@ -157,68 +181,68 @@ export default {
grantRightToMultipleUsers(right) {
const { grantRight } = this.mappers()
this.confirmMessage(
`Are you sure you want to grant ${right} rights to all selected users?`,
this.$t('users.grantRightConfirmation', { right }),
grantRight(right)
)
},
revokeRightFromMultipleUsers(right) {
const { revokeRight } = this.mappers()
this.confirmMessage(
`Are you sure you want to revoke ${right} rights from all selected users?`,
this.$t('users.revokeRightConfirmation', { right }),
revokeRight(right)
)
},
activateMultipleUsers() {
const { activate } = this.mappers()
this.confirmMessage(
'Are you sure you want to activate accounts of all selected users?',
this.$t('users.activateMultipleUsersConfirmation'),
activate
)
},
deactivateMultipleUsers() {
const { deactivate } = this.mappers()
this.confirmMessage(
'Are you sure you want to deactivate accounts of all selected users?',
this.$t('users.deactivateMultipleUsersConfirmation'),
deactivate
)
},
deleteMultipleUsers() {
const { remove } = this.mappers()
this.confirmMessage(
'Are you sure you want to delete accounts of all selected users?',
this.$t('users.deleteMultipleUsersConfirmation'),
remove
)
},
addTagForMultipleUsers(tag) {
const { addTag } = this.mappers()
this.confirmMessage(
'Are you sure you want to apply tag to all selected users?',
this.$t('users.addTagForMultipleUsersConfirmation'),
addTag(tag)
)
},
removeTagFromMultipleUsers(tag) {
const { removeTag } = this.mappers()
this.confirmMessage(
'Are you sure you want to remove tag from all selected users?',
this.$t('users.removeTagFromMultipleUsersConfirmation'),
removeTag(tag)
)
},
confirmMessage(message, applyAction) {
this.$confirm(message, {
confirmButtonText: 'OK',
cancelButtonText: 'Cancel',
confirmButtonText: this.$t('users.ok'),
cancelButtonText: this.$t('users.cancel'),
type: 'warning'
}).then(() => {
applyAction()
this.$emit('apply-action')
this.$message({
type: 'success',
message: 'Completed'
message: this.$t('users.completed')
})
}).catch(() => {
this.$message({
type: 'info',
message: 'Canceled'
message: this.$t('users.canceled')
})
})
}
@ -229,9 +253,8 @@ export default {
<style rel='stylesheet/scss' lang='scss' scoped>
.actions-button {
text-align: left;
margin: 0 15px 10px 0;
width: 350px;
padding: 10px 15px;
padding: 10px;
}
.actions-button-container {
display: flex;
@ -240,8 +263,8 @@ export default {
.el-dropdown {
float: right;
}
.el-dropdown-menu {
margin-right: 15px;
.el-icon-edit {
margin-right: 5px;
}
.tag-container {
display: flex;

View file

@ -0,0 +1,151 @@
<template>
<el-dialog
:visible.sync="isVisible"
:show-close="false"
:title="$t('users.createAccount')"
custom-class="create-user-dialog"
@open="resetForm">
<el-form ref="form" :model="form" :rules="rules" :label-width="getLabelWidth" status-icon>
<el-form-item :label="$t('users.username')" prop="nickname" class="create-account-form-item">
<el-input v-model="form.nickname" name="nickname" autofocus/>
</el-form-item>
<el-form-item :label="$t('users.email')" prop="email" class="create-account-form-item">
<el-input v-model="form.email" name="email" type="email"/>
</el-form-item>
<el-form-item :label="$t('users.password')" prop="password" class="create-account-form-item">
<el-input v-model="form.password" type="password" name="password" autocomplete="off"/>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="closeDialogWindow">{{ $t('users.cancel') }}</el-button>
<el-button type="primary" @click="submitForm('form')">{{ $t('users.create') }}</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: 'NewAccountDialog',
props: {
dialogFormVisible: {
type: Boolean,
default: function() {
return false
}
}
},
data() {
return {
form: {
nickname: '',
email: '',
password: ''
},
rules: {
nickname: [
{ validator: this.validateUsername, trigger: 'blur' }
],
email: [
{ validator: this.validateEmail, trigger: 'blur' }
],
password: [
{ validator: this.validatePassword, trigger: 'blur' }
]
}
}
},
computed: {
isDesktop() {
return this.$store.state.app.device === 'desktop'
},
isVisible: {
get() {
return this.$props.dialogFormVisible
},
set() {
this.closeDialogWindow()
}
},
getLabelWidth() {
return this.isDesktop ? '120px' : '80px'
}
},
methods: {
closeDialogWindow() {
this.$emit('closeWindow')
},
resetForm() {
this.$nextTick(() => {
this.$refs['form'].resetFields()
})
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$emit('createNewAccount', this.$data.form)
this.closeDialogWindow()
this.$message({
type: 'success',
message: this.$t('users.completed')
})
} else {
this.$message({
type: 'error',
message: this.$t('users.submitFormError')
})
return false
}
})
},
validateEmail(rule, value, callback) {
if (value === '') {
return callback(new Error(this.$t('users.emptyEmailError')))
} else if (!this.validEmail(value)) {
return callback(new Error(this.$t('users.invalidEmailError')))
} else {
return callback()
}
},
validatePassword(rule, value, callback) {
if (value === '') {
return callback(new Error(this.$t('users.emptyPasswordError')))
} else {
return callback()
}
},
validateUsername(rule, value, callback) {
if (value === '') {
return callback(new Error(this.$t('users.emptyNicknameError')))
} else if (!this.validNickname(value)) {
return callback(new Error(this.$t('users.invalidNicknameError')))
} else {
return callback()
}
},
validEmail(email) {
var re = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
return re.test(email)
},
validNickname(nickname) {
var re = /^[a-zA-Z\d]+$/
return re.test(nickname)
}
}
}
</script>
<style rel='stylesheet/scss' lang='scss'>
@media
only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-width: 1024px) {
.create-user-dialog {
width: 80%
}
.create-account-form-item {
margin-bottom: 30px;
}
.el-dialog__body {
padding: 20px 20px 0 20px
}
}
</style>

View file

@ -4,13 +4,25 @@
{{ $t('users.users') }}
<span class="user-count">({{ normalizedUsersCount }})</span>
</h1>
<div class="search-container">
<div class="filter-container">
<users-filter/>
<el-input :placeholder="$t('users.search')" v-model="search" class="search" @input="handleDebounceSearchInput"/>
</div>
<dropdown-actions-menu
:selected-users="selectedUsers"
@apply-action="clearSelection"/>
<div class="actions-container">
<el-button class="actions-button create-account" @click="dialogFormVisible = true">
<span>
<i class="el-icon-plus" />
{{ $t('users.createAccount') }}
</span>
</el-button>
<multiple-users-menu
:selected-users="selectedUsers"
@apply-action="clearSelection"/>
</div>
<new-account-dialog
:dialog-form-visible="dialogFormVisible"
@createNewAccount="createNewAccount"
@closeWindow="dialogFormVisible = false"/>
<el-table
v-loading="loading"
ref="usersTable"
@ -140,22 +152,21 @@
import debounce from 'lodash.debounce'
import numeral from 'numeral'
import UsersFilter from './components/UsersFilter'
import DropdownActionsMenu from './components/DropdownActionsMenu'
import MultipleUsersMenu from './components/MultipleUsersMenu'
import NewAccountDialog from './components/NewAccountDialog'
export default {
name: 'Users',
components: {
UsersFilter,
DropdownActionsMenu
},
data: function() {
return {
selectedUsers: []
}
MultipleUsersMenu,
NewAccountDialog
},
data() {
return {
search: ''
search: '',
selectedUsers: [],
dialogFormVisible: false
}
},
data() {
@ -207,6 +218,9 @@ export default {
clearSelection() {
this.$refs.usersTable.clearSelection()
},
createNewAccount(accountData) {
this.$store.dispatch('CreateNewAccount', accountData)
},
getFirstLetter(str) {
return str.charAt(0).toUpperCase()
},
@ -246,6 +260,18 @@ export default {
</script>
<style rel='stylesheet/scss' lang='scss' scoped>
.actions-button {
text-align: left;
width: 350px;
padding: 10px;
}
.actions-container {
display: flex;
height: 36px;
justify-content: space-between;
align-items: center;
margin: 0 15px 10px 15px;
}
.active-tag {
color: #409EFF;
font-weight: 700;
@ -256,9 +282,12 @@ export default {
}
}
.el-dropdown-link:hover {
cursor: pointer;
color: #409EFF;
}
cursor: pointer;
color: #409EFF;
}
.el-icon-plus {
margin-right: 5px;
}
.users-container {
h1 {
margin: 22px 0 0 15px;
@ -273,7 +302,7 @@ export default {
width: 350px;
float: right;
}
.search-container {
.filter-container {
display: flex;
height: 36px;
justify-content: space-between;
@ -292,17 +321,25 @@ only screen and (max-width: 760px),
h1 {
margin: 7px 10px 7px 10px;
}
.actions-container {
display: flex;
flex-direction: column;
margin: 0 10px 7px 10px
}
.create-account {
width: 100%;
}
.el-icon-arrow-down {
font-size: 12px;
}
.search {
width: 100%;
}
.search-container {
.filter-container {
display: flex;
height: 82px;
flex-direction: column;
margin: 0 10px 7px 10px
margin: 0 10px
}
.el-tag {
width: 30px;

View file

@ -3,6 +3,7 @@ import { mount, createLocalVue, config } from '@vue/test-utils'
import flushPromises from 'flush-promises'
import Element from 'element-ui'
import Users from '@/views/users/index'
import NewAccountDialog from '@/views/users/components/NewAccountDialog'
import storeConfig from './store.conf'
import { cloneDeep } from 'lodash'
@ -232,3 +233,98 @@ describe('Users actions', () => {
done()
})
})
describe('Creates new account', () => {
let store
const nicknameInput = 'input[name="nickname"]'
const emailInput = 'input[name="email"]'
const passwordInput = 'input[name="password"]'
beforeEach(async() => {
store = new Vuex.Store(cloneDeep(storeConfig))
})
it('opens and closes dialog window', async (done) => {
const wrapper = mount(Users, {
store,
localVue,
sync: false
})
await flushPromises()
const dialog = wrapper.find('div.el-dialog__wrapper')
expect(dialog.isVisible()).toBe(false)
const openDialogButton = wrapper.find('button.actions-button')
const closeDialogButton = wrapper.find('div.el-dialog__footer button')
openDialogButton.trigger('click')
await flushPromises()
expect(dialog.isVisible()).toBe(true)
closeDialogButton.trigger('click')
await flushPromises()
expect(dialog.isVisible()).toBe(false)
done()
})
it('creates new account', async (done) => {
const wrapper = mount(Users, {
store,
localVue,
sync: false
})
await flushPromises()
expect(wrapper.vm.usersCount).toEqual(3)
const openDialogButton = wrapper.find('button.actions-button')
openDialogButton.trigger('click')
await flushPromises()
const nickname = wrapper.find(nicknameInput)
nickname.element.value = 'marshall'
nickname.trigger('input')
const email = wrapper.find(emailInput)
email.element.value = 'marshall@marshall.com'
email.trigger('input')
const password = wrapper.find(passwordInput)
password.element.value = '1234'
password.trigger('input')
const createButton = wrapper.find('button.el-button--primary')
createButton.trigger('click')
await flushPromises()
expect(wrapper.vm.usersCount).toEqual(4)
done()
})
it('validates data', () => {
const wrapper = mount(NewAccountDialog, {
store,
localVue,
sync: false
})
const validateEmailRule = { validator: wrapper.vm.validateEmail, field: 'email', fullField: 'email', type: 'string' }
const validatePasswordRule = { validator: wrapper.vm.validatePassword, field: 'password', fullField: 'password', type: 'string' }
const validateUsernameRule = { validator: wrapper.vm.validateUsername, field: 'nickname', fullField: 'nickname', type: 'string' }
const identity = val => val
expect(wrapper.vm.validateUsername(validateUsernameRule, '', identity).message).toBe('Please input the username')
expect(wrapper.vm.validateUsername(validateUsernameRule, 'marshall%$', identity).message).toBe('Username can include "a-z", "A-Z" and "0-9" characters')
expect(wrapper.vm.validateUsername(validateUsernameRule, 'Marshall66', identity)).toBeUndefined()
expect(wrapper.vm.validateEmail(validateEmailRule, '', identity).message).toBe('Please input the e-mail')
expect(wrapper.vm.validateEmail(validateEmailRule, 'test', identity).message).toBe('Please input valid e-mail')
expect(wrapper.vm.validateEmail(validateEmailRule, 'test@test.com', identity)).toBeUndefined()
expect(wrapper.vm.validatePassword(validatePasswordRule, '', identity).message).toBe('Please input the password')
expect(wrapper.vm.validatePassword(validatePasswordRule, '1234', identity)).toBeUndefined()
})
})

View file

@ -1,7 +1,7 @@
import Vuex from 'vuex'
import { mount, createLocalVue, config } from '@vue/test-utils'
import Element from 'element-ui'
import DropdownMenu from '@/views/users/components/DropdownMenu'
import MultipleUsersMenu from '@/views/users/components/MultipleUsersMenu'
import storeConfig from './store.conf'
import { cloneDeep } from 'lodash'
import flushPromises from 'flush-promises'
@ -25,7 +25,7 @@ describe('Apply users actions to multiple users', () => {
})
it('grants admin rights to multiple users', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -62,7 +62,7 @@ describe('Apply users actions to multiple users', () => {
})
it('grants moderator rights to multiple users', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -99,7 +99,7 @@ describe('Apply users actions to multiple users', () => {
})
it('revokes admin rights from multiple users', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -132,7 +132,7 @@ describe('Apply users actions to multiple users', () => {
})
it('calls a function that revokes moderator rights from multiple users', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -152,7 +152,7 @@ describe('Apply users actions to multiple users', () => {
})
it('activates multiple accounts', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -180,7 +180,7 @@ describe('Apply users actions to multiple users', () => {
})
it('deactivates multiple accounts', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -212,7 +212,7 @@ describe('Apply users actions to multiple users', () => {
})
it('deletes multiple accounts', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -248,7 +248,7 @@ describe('Apply users actions to multiple users', () => {
})
it('applies tags for multiple accounts', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,
@ -289,7 +289,7 @@ describe('Apply users actions to multiple users', () => {
})
it('removes tags from multiple accounts', async (done) => {
const wrapper = mount(DropdownMenu, {
const wrapper = mount(MultipleUsersMenu, {
store,
localVue,
sync: false,