Merge branch 'feature/add-users-actions' into 'master'
Add actions to moderation menu Closes #4 See merge request pleroma/admin-fe!7
This commit is contained in:
commit
76736c795b
7 changed files with 356 additions and 113 deletions
|
@ -1,7 +1,7 @@
|
|||
const users = [
|
||||
{ deactivated: false, id: '1', nickname: 'john', local: true },
|
||||
{ deactivated: false, id: '2', nickname: 'bob', local: false },
|
||||
{ deactivated: true, id: '3', nickname: 'allis', local: true }
|
||||
{ deactivated: false, id: '2', nickname: 'allis', local: true, roles: { admin: true, moderator: false }, tags: [] },
|
||||
{ deactivated: false, id: '10', nickname: 'bob', local: false, roles: { admin: false, moderator: true }, tags: ['sandbox'] },
|
||||
{ deactivated: true, id: 'abc', nickname: 'john', local: true, roles: { admin: false, moderator: false }, tags: ['strip_media'] }
|
||||
]
|
||||
|
||||
export async function fetchUsers(showLocalUsersOnly, token, page = 1) {
|
||||
|
@ -27,3 +27,29 @@ export async function searchUsers(query, showLocalUsersOnly, token, page = 1) {
|
|||
page_size: 50
|
||||
}})
|
||||
}
|
||||
|
||||
export async function addRight(nickname, right, token) {
|
||||
return Promise.resolve({ data:
|
||||
{ [`is_${right}`]: true }
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteRight(nickname, right, token) {
|
||||
return Promise.resolve({ data:
|
||||
{ [`is_${right}`]: false }
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteUser(nickname, token) {
|
||||
return Promise.resolve({ data:
|
||||
nickname
|
||||
})
|
||||
}
|
||||
|
||||
export async function tagUser(nickname, tag, token) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
export async function untagUser(nickname, tag, token) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ export async function fetchUsers(showLocalUsersOnly, token, page = 1) {
|
|||
return await request({
|
||||
url: `/api/pleroma/admin/users?page=${page}&local_only=${showLocalUsersOnly}`,
|
||||
method: 'get',
|
||||
headers: token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
||||
headers: authHeaders(token)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ export async function toggleUserActivation(nickname, token) {
|
|||
return await request({
|
||||
url: `/api/pleroma/admin/users/${nickname}/toggle_activation`,
|
||||
method: 'patch',
|
||||
headers: token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
||||
headers: authHeaders(token)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,50 @@ export async function searchUsers(query, showLocalUsersOnly, token, page = 1) {
|
|||
return await request({
|
||||
url: `/api/pleroma/admin/users?query=${query}&page=${page}&local_only=${showLocalUsersOnly}`,
|
||||
method: 'get',
|
||||
headers: token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
||||
headers: authHeaders(token)
|
||||
})
|
||||
}
|
||||
|
||||
export async function addRight(nickname, right, token) {
|
||||
return await request({
|
||||
url: `/api/pleroma/admin/permission_group/${nickname}/${right}`,
|
||||
method: 'post',
|
||||
headers: authHeaders(token)
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteRight(nickname, right, token) {
|
||||
return await request({
|
||||
url: `/api/pleroma/admin/permission_group/${nickname}/${right}`,
|
||||
method: 'delete',
|
||||
headers: authHeaders(token)
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteUser(nickname, token) {
|
||||
return await request({
|
||||
url: `/api/pleroma/admin/user.json?nickname=${nickname}`,
|
||||
method: 'delete',
|
||||
headers: authHeaders(token)
|
||||
})
|
||||
}
|
||||
|
||||
export async function tagUser(nickname, tag, token) {
|
||||
return await request({
|
||||
url: '/api/pleroma/admin/users/tag',
|
||||
method: 'put',
|
||||
headers: authHeaders(token),
|
||||
data: { nicknames: [nickname], tags: [tag] }
|
||||
})
|
||||
}
|
||||
|
||||
export async function untagUser(nickname, tag, token) {
|
||||
return await request({
|
||||
url: '/api/pleroma/admin/users/tag',
|
||||
method: 'delete',
|
||||
headers: authHeaders(token),
|
||||
data: { nicknames: [nickname], tags: [tag] }
|
||||
})
|
||||
}
|
||||
|
||||
const authHeaders = (token) => token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
||||
|
|
|
@ -87,29 +87,11 @@ const user = {
|
|||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 第三方验证登录
|
||||
// LoginByThirdparty({ commit, state }, code) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// commit('SET_CODE', code)
|
||||
// loginByThirdparty(state.status, state.email, state.code).then(response => {
|
||||
// commit('SET_TOKEN', response.data.token)
|
||||
// setToken(response.data.token)
|
||||
// resolve()
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
// })
|
||||
// },
|
||||
|
||||
// 登出
|
||||
LogOut({ commit }) {
|
||||
commit('SET_TOKEN', '')
|
||||
commit('SET_ROLES', [])
|
||||
removeToken()
|
||||
},
|
||||
|
||||
// 前端 登出
|
||||
FedLogOut({ commit }) {
|
||||
return new Promise(resolve => {
|
||||
commit('SET_TOKEN', '')
|
||||
|
@ -117,24 +99,6 @@ const user = {
|
|||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
// 动态修改权限
|
||||
// ChangeRoles({ commit, dispatch }, role) {
|
||||
// return new Promise(resolve => {
|
||||
// commit('SET_TOKEN', role)
|
||||
// setToken(role)
|
||||
// getUserInfo(role).then(response => {
|
||||
// const data = response.data
|
||||
// commit('SET_ROLES', data.roles)
|
||||
// commit('SET_NAME', data.name)
|
||||
// commit('SET_ID', data.id)
|
||||
// commit('SET_AVATAR', data.avatar)
|
||||
// commit('SET_INTRODUCTION', data.introduction)
|
||||
// dispatch('GenerateRoutes', data) // 动态修改权限后 重绘侧边菜单
|
||||
// resolve()
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fetchUsers, toggleUserActivation, searchUsers } from '@/api/users'
|
||||
import { addRight, fetchUsers, deleteRight, deleteUser, searchUsers, tagUser, toggleUserActivation, untagUser } from '@/api/users'
|
||||
|
||||
const users = {
|
||||
state: {
|
||||
|
@ -22,7 +22,7 @@ const users = {
|
|||
})
|
||||
|
||||
state.fetchedUsers = [...usersWithoutSwapped, user].sort((a, b) =>
|
||||
a.id.localeCompare(b.id)
|
||||
a.nickname.localeCompare(b.nickname)
|
||||
)
|
||||
},
|
||||
SET_COUNT: (state, count) => {
|
||||
|
@ -70,6 +70,30 @@ const users = {
|
|||
async ToggleLocalUsersFilter({ commit, dispatch, state }, value) {
|
||||
commit('SET_LOCAL_USERS_FILTER', value)
|
||||
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
|
||||
},
|
||||
async ToggleRight({ commit, getters }, { user, right }) {
|
||||
user.roles[right]
|
||||
? await deleteRight(user.nickname, right, getters.token)
|
||||
: await addRight(user.nickname, right, getters.token)
|
||||
|
||||
const updatedUser = { ...user, roles: { ...user.roles, [right]: !user.roles[right] }}
|
||||
commit('SWAP_USER', updatedUser)
|
||||
},
|
||||
async DeleteUser({ commit, getters }, user) {
|
||||
await deleteUser(user.nickname, getters.token)
|
||||
const updatedUser = { ...user, deactivated: true }
|
||||
commit('SWAP_USER', updatedUser)
|
||||
},
|
||||
async ToggleTag({ commit, getters }, { user, tag }) {
|
||||
if (user.tags.includes(tag)) {
|
||||
await untagUser(user.nickname, tag, getters.token)
|
||||
const updatedUser = { ...user, tags: user.tags.filter(userTag => userTag !== tag) }
|
||||
commit('SWAP_USER', updatedUser)
|
||||
} else {
|
||||
await tagUser(user.nickname, tag, getters.token)
|
||||
const updatedUser = { ...user, tags: [...user.tags, tag] }
|
||||
commit('SWAP_USER', updatedUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,41 +10,8 @@ const service = axios.create({
|
|||
// response interceptor
|
||||
service.interceptors.response.use(
|
||||
response => response,
|
||||
/**
|
||||
* 下面的注释为通过在response里,自定义code来标示请求状态
|
||||
* 当code返回如下情况则说明权限有问题,登出并返回到登录页
|
||||
* 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中
|
||||
* 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
|
||||
*/
|
||||
// response => {
|
||||
// const res = response.data
|
||||
// if (res.code !== 20000) {
|
||||
// Message({
|
||||
// message: res.message,
|
||||
// type: 'error',
|
||||
// duration: 5 * 1000
|
||||
// })
|
||||
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
|
||||
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
|
||||
// // 请自行在引入 MessageBox
|
||||
// // import { Message, MessageBox } from 'element-ui'
|
||||
// MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
|
||||
// confirmButtonText: '重新登录',
|
||||
// cancelButtonText: '取消',
|
||||
// type: 'warning'
|
||||
// }).then(() => {
|
||||
// store.dispatch('FedLogOut').then(() => {
|
||||
// location.reload() // 为了重新实例化vue-router对象 避免bug
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
// return Promise.reject('error')
|
||||
// } else {
|
||||
// return response.data
|
||||
// }
|
||||
// },
|
||||
error => {
|
||||
console.log('err' + error) // for debug
|
||||
console.log('err' + error)
|
||||
Message({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
|
|
|
@ -7,24 +7,74 @@
|
|||
</div>
|
||||
<el-table v-loading="loading" :data="users" style="width: 100%">
|
||||
<el-table-column :min-width="width" prop="id" label="ID"/>
|
||||
<el-table-column prop="nickname" label="Name"/>
|
||||
<el-table-column prop="nickname" label="Name">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.nickname }}
|
||||
<el-tag v-if="isDesktop" type="info" size="mini">
|
||||
<span>{{ scope.row.local ? 'local' : 'external' }}</span>
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :min-width="width" label="Status">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.deactivated ? 'danger' : 'success'">
|
||||
<span v-if="isDesktop">{{ scope.row.deactivated ? 'deactivated' : 'active' }}</span>
|
||||
<i v-else :class="activationIcon(scope.row.deactivated)"/>
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.roles.admin">
|
||||
<span>{{ isDesktop ? 'admin' : 'A' }}</span>
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.roles.moderator">
|
||||
<span>{{ isDesktop ? 'moderator' : 'M' }}</span>
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="Actions">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
v-if="showDeactivatedButton(scope.row.id)"
|
||||
class="toggle-activation"
|
||||
type="text"
|
||||
size="small"
|
||||
@click="handleDeactivate(scope.row)"
|
||||
>{{ scope.row.deactivated ? 'Activate' : 'Deactivate' }}</el-button>
|
||||
<el-dropdown size="small">
|
||||
<span class="el-dropdown-link">
|
||||
Moderation
|
||||
<i v-if="isDesktop" class="el-icon-arrow-down el-icon--right"/>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item v-if="showAdminAction(scope.row)" @click.native="toggleUserRight(scope.row, 'admin')">
|
||||
{{ scope.row.roles.admin ? 'Revoke Admin' : 'Grant Admin' }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="showAdminAction(scope.row)" @click.native="toggleUserRight(scope.row, 'moderator')">
|
||||
{{ scope.row.roles.moderator ? 'Revoke Moderator' : 'Grant Moderator' }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="showDeactivatedButton(scope.row.id)" :divided="showAdminAction(scope.row)" @click.native="handleDeactivation(scope.row)">
|
||||
{{ scope.row.deactivated ? 'Activate account' : 'Deactivate account' }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="showDeactivatedButton(scope.row.id)" @click.native="handleDeletion(scope.row)">
|
||||
Delete Account
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :divided="showAdminAction(scope.row)" @click.native="toggleTag(scope.row, 'force_nsfw')">
|
||||
Force posts to be NSFW
|
||||
<i v-if="scope.row.tags.includes('force_nsfw')" class="el-icon-circle-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="toggleTag(scope.row, 'strip_media')">
|
||||
Force posts not to have media
|
||||
<i v-if="scope.row.tags.includes('strip_media')" class="el-icon-circle-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="toggleTag(scope.row, 'force_unlisted')">
|
||||
Force posts to be unlisted
|
||||
<i v-if="scope.row.tags.includes('force_unlisted')" class="el-icon-circle-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="toggleTag(scope.row, 'sandbox')">
|
||||
Force posts to be followers-only
|
||||
<i v-if="scope.row.tags.includes('sandbox')" class="el-icon-circle-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="scope.row.local" @click.native="toggleTag(scope.row, 'disable_remote_subscription')">
|
||||
Disallow following user from remote instances
|
||||
<i v-if="scope.row.tags.includes('disable_remote_subscription')" class="el-icon-circle-check"/>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="scope.row.local" @click.native="toggleTag(scope.row, 'disable_any_subscription')">
|
||||
Disallow following user at all
|
||||
<i v-if="scope.row.tags.includes('disable_any_subscription')" class="el-icon-circle-check"/>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -72,12 +122,7 @@ export default {
|
|||
return this.$store.state.app.device === 'mobile'
|
||||
},
|
||||
width() {
|
||||
return this.isMobile ? 60 : false
|
||||
},
|
||||
rowStyle(id) {
|
||||
return {
|
||||
'data-user-id': id
|
||||
}
|
||||
return this.isMobile ? 55 : false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -89,7 +134,7 @@ export default {
|
|||
this.$store.dispatch('FetchUsers', { page: 1 })
|
||||
},
|
||||
methods: {
|
||||
handleDeactivate({ nickname }) {
|
||||
handleDeactivation({ nickname }) {
|
||||
this.$store.dispatch('ToggleUserActivation', nickname)
|
||||
},
|
||||
handlePageChange(page) {
|
||||
|
@ -103,11 +148,23 @@ export default {
|
|||
showDeactivatedButton(id) {
|
||||
return this.$store.state.user.id !== id
|
||||
},
|
||||
showAdminAction({ local, id }) {
|
||||
return local && this.showDeactivatedButton(id)
|
||||
},
|
||||
handleLocalUsersCheckbox(e) {
|
||||
this.$store.dispatch('ToggleLocalUsersFilter', e)
|
||||
},
|
||||
activationIcon(status) {
|
||||
return status ? 'el-icon-error' : 'el-icon-success'
|
||||
},
|
||||
toggleUserRight(user, right) {
|
||||
this.$store.dispatch('ToggleRight', { user, right })
|
||||
},
|
||||
handleDeletion(user) {
|
||||
this.$store.dispatch('DeleteUser', user)
|
||||
},
|
||||
toggleTag(user, tag) {
|
||||
this.$store.dispatch('ToggleTag', { user, tag })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +201,13 @@ only screen and (max-width: 760px),
|
|||
h1 {
|
||||
margin-left: 7px;
|
||||
}
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
}
|
||||
.el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
.search {
|
||||
width: 50%;
|
||||
margin-bottom: 21.5px;
|
||||
|
@ -156,6 +220,18 @@ only screen and (max-width: 760px),
|
|||
align-items: baseline;
|
||||
margin-left: 7px;
|
||||
}
|
||||
.el-tag {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
margin-bottom: 4px;
|
||||
font-weight: bold;
|
||||
&.el-tag--success {
|
||||
padding-left: 8px;
|
||||
}
|
||||
&.el-tag--danger {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,7 +11,7 @@ localVue.use(Element)
|
|||
|
||||
jest.mock('@/api/users')
|
||||
|
||||
describe('Users', () => {
|
||||
describe('Search and filter users', () => {
|
||||
let store
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -29,24 +29,6 @@ describe('Users', () => {
|
|||
done()
|
||||
})
|
||||
|
||||
it('toggles activation status on button click', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const user = store.state.users.fetchedUsers[1]
|
||||
expect(user.deactivated).toBe(false)
|
||||
|
||||
wrapper.find('.el-table__fixed-body-wrapper table tr:nth-child(2) button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const updatedUser = store.state.users.fetchedUsers[1]
|
||||
expect(updatedUser.deactivated).toBe(true)
|
||||
done()
|
||||
})
|
||||
|
||||
it('starts a search on input change', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
|
@ -95,7 +77,7 @@ describe('Users', () => {
|
|||
done()
|
||||
})
|
||||
|
||||
it('shows local users with query search', async (done) => {
|
||||
it('shows local users with search query', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
|
@ -134,3 +116,164 @@ describe('Users', () => {
|
|||
done()
|
||||
})
|
||||
})
|
||||
|
||||
describe('Users actions', () => {
|
||||
let store
|
||||
const htmlElement = (trChild, liChild) =>
|
||||
`.el-table__fixed-body-wrapper table tr:nth-child(${trChild}) ul.el-dropdown-menu li:nth-child(${liChild})`
|
||||
|
||||
beforeEach(() => {
|
||||
store = new Vuex.Store(cloneDeep(storeConfig))
|
||||
})
|
||||
|
||||
it('grants admin and moderator rights to a local user', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const user = store.state.users.fetchedUsers[2]
|
||||
expect(user.roles.admin).toBe(false)
|
||||
expect(user.roles.moderator).toBe(false)
|
||||
|
||||
wrapper.find(htmlElement(3, 1)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
wrapper.find(htmlElement(3, 2)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const updatedUser = store.state.users.fetchedUsers[2]
|
||||
expect(updatedUser.roles.admin).toBe(true)
|
||||
expect(updatedUser.roles.moderator).toBe(true)
|
||||
done()
|
||||
})
|
||||
|
||||
it('does not show actions that grant admin and moderator rights to external users', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const dropdownMenuItem = wrapper.find(htmlElement(2, 1))
|
||||
expect(dropdownMenuItem.text()).toBe('Deactivate account')
|
||||
done()
|
||||
})
|
||||
|
||||
it('toggles activation status', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const user = store.state.users.fetchedUsers[1]
|
||||
expect(user.deactivated).toBe(false)
|
||||
|
||||
wrapper.find(htmlElement(2, 1)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const updatedUser = store.state.users.fetchedUsers[1]
|
||||
expect(updatedUser.deactivated).toBe(true)
|
||||
done()
|
||||
})
|
||||
|
||||
it('deactivates user when Delete action is called', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const user = store.state.users.fetchedUsers[1]
|
||||
expect(user.deactivated).toBe(false)
|
||||
|
||||
wrapper.find(htmlElement(2, 2)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const updatedUser = store.state.users.fetchedUsers[1]
|
||||
expect(updatedUser.deactivated).toBe(true)
|
||||
done()
|
||||
})
|
||||
|
||||
it('adds tags', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const user1 = store.state.users.fetchedUsers[0]
|
||||
const user2 = store.state.users.fetchedUsers[1]
|
||||
expect(user1.tags.length).toBe(0)
|
||||
expect(user2.tags.length).toBe(1)
|
||||
|
||||
wrapper.find(htmlElement(1, 5)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
wrapper.find(htmlElement(2, 5)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const updatedUser1 = store.state.users.fetchedUsers[0]
|
||||
const updatedUser2 = store.state.users.fetchedUsers[1]
|
||||
expect(updatedUser1.tags.length).toBe(1)
|
||||
expect(updatedUser2.tags.length).toBe(2)
|
||||
done()
|
||||
})
|
||||
|
||||
it('deletes tags', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const user = store.state.users.fetchedUsers[1]
|
||||
expect(user.tags.length).toBe(1)
|
||||
|
||||
wrapper.find(htmlElement(2, 6)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const updatedUser = store.state.users.fetchedUsers[1]
|
||||
expect(updatedUser.tags.length).toBe(0)
|
||||
done()
|
||||
})
|
||||
|
||||
it('shows check icon when tag is added', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.find(`${htmlElement(1, 5)} i`).exists()).toBe(false)
|
||||
|
||||
wrapper.find(htmlElement(1, 5)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.find(`${htmlElement(1, 5)} i`).exists()).toBe(true)
|
||||
done()
|
||||
})
|
||||
|
||||
it('does not change user index in array when tag is added', async (done) => {
|
||||
const wrapper = mount(Users, {
|
||||
store,
|
||||
localVue
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const firstUserNickname = store.state.users.fetchedUsers[0].nickname
|
||||
const secondUserNickname = store.state.users.fetchedUsers[1].nickname
|
||||
expect(firstUserNickname).toBe('allis')
|
||||
expect(secondUserNickname).toBe('bob')
|
||||
|
||||
wrapper.find(htmlElement(2, 5)).trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const firstUserNicknameAfterToggle = store.state.users.fetchedUsers[0].nickname
|
||||
const secondUserNicknameAfterToggle = store.state.users.fetchedUsers[1].nickname
|
||||
|
||||
expect(firstUserNicknameAfterToggle).toEqual('allis')
|
||||
expect(secondUserNicknameAfterToggle).toEqual('bob')
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue