diff --git a/admin/src/components/ChangeUserRoleFormular.spec.js b/admin/src/components/ChangeUserRoleFormular.spec.js new file mode 100644 index 000000000..8bcd4d8e5 --- /dev/null +++ b/admin/src/components/ChangeUserRoleFormular.spec.js @@ -0,0 +1,254 @@ +import { mount } from '@vue/test-utils' +import ChangeUserRoleFormular from './ChangeUserRoleFormular.vue' +import { setUserRole } from '../graphql/setUserRole' +import { toastSuccessSpy, toastErrorSpy } from '../../test/testSetup' + +const localVue = global.localVue + +const apolloMutateMock = jest.fn().mockResolvedValue({ + data: { + setUserRole: null, + }, +}) + +const mocks = { + $t: jest.fn((t) => t), + $apollo: { + mutate: apolloMutateMock, + }, + $store: { + state: { + moderator: { + id: 0, + name: 'test moderator', + }, + }, + }, +} + +let propsData +let wrapper + +describe('ChangeUserRoleFormular', () => { + const Wrapper = () => { + return mount(ChangeUserRoleFormular, { localVue, mocks, propsData }) + } + + describe('mount', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + describe('DOM has', () => { + beforeEach(() => { + propsData = { + item: { + userId: 1, + isAdmin: null, + }, + } + wrapper = Wrapper() + }) + + it('has a DIV element with the class.delete-user-formular', () => { + expect(wrapper.find('.change-user-role-formular').exists()).toBe(true) + }) + }) + + describe('change own role', () => { + beforeEach(() => { + propsData = { + item: { + userId: 0, + isAdmin: null, + }, + } + wrapper = Wrapper() + }) + + it('has the text that you cannot change own role', () => { + expect(wrapper.text()).toContain('userRole.notChangeYourSelf') + }) + + it('has role select disabled', () => { + expect(wrapper.find('select[disabled="disabled"]').exists()).toBe(true) + }) + }) + + describe('change others role', () => { + let rolesToSelect + + describe('general', () => { + beforeEach(() => { + propsData = { + item: { + userId: 1, + isAdmin: null, + }, + } + wrapper = Wrapper() + rolesToSelect = wrapper.find('select.role-select').findAll('option') + }) + + it('has no text that you cannot change own role', () => { + expect(wrapper.text()).not.toContain('userRole.notChangeYourSelf') + }) + + it('has the select label', () => { + expect(wrapper.text()).toContain('userRole.selectLabel') + }) + + it('has a select', () => { + expect(wrapper.find('select.role-select').exists()).toBe(true) + }) + + it('has role select enabled', () => { + expect(wrapper.find('select.role-select[disabled="disabled"]').exists()).toBe(false) + }) + + describe('on API error', () => { + beforeEach(() => { + apolloMutateMock.mockRejectedValue({ message: 'Oh no!' }) + rolesToSelect.at(1).setSelected() + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith('Oh no!') + }) + }) + }) + + describe('user is usual user', () => { + beforeEach(() => { + apolloMutateMock.mockResolvedValue({ + data: { + setUserRole: new Date(), + }, + }) + propsData = { + item: { + userId: 1, + isAdmin: null, + }, + } + wrapper = Wrapper() + rolesToSelect = wrapper.find('select.role-select').findAll('option') + }) + + it('has selected option set to "usual user"', () => { + expect(wrapper.find('select.role-select').element.value).toBe('user') + }) + + describe('change select to', () => { + describe('same role', () => { + it('does not call the API', () => { + rolesToSelect.at(0).setSelected() + expect(apolloMutateMock).not.toHaveBeenCalled() + }) + }) + + describe('new role', () => { + beforeEach(() => { + rolesToSelect.at(1).setSelected() + }) + + it('calls the API', () => { + expect(apolloMutateMock).toBeCalledWith( + expect.objectContaining({ + mutation: setUserRole, + variables: { + userId: 1, + isAdmin: true, + }, + }), + ) + }) + + it('emits "updateIsAdmin"', () => { + expect(wrapper.emitted('updateIsAdmin')).toEqual( + expect.arrayContaining([ + expect.arrayContaining([ + { + userId: 1, + isAdmin: expect.any(Date), + }, + ]), + ]), + ) + }) + + it('toasts success message', () => { + expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo') + }) + }) + }) + }) + + describe('user is admin', () => { + beforeEach(() => { + apolloMutateMock.mockResolvedValue({ + data: { + setUserRole: null, + }, + }) + propsData = { + item: { + userId: 1, + isAdmin: new Date(), + }, + } + wrapper = Wrapper() + rolesToSelect = wrapper.find('select.role-select').findAll('option') + }) + + it('has selected option set to "admin"', () => { + expect(wrapper.find('select.role-select').element.value).toBe('admin') + }) + + describe('change select to', () => { + describe('same role', () => { + it('does not call the API', () => { + rolesToSelect.at(1).setSelected() + expect(apolloMutateMock).not.toHaveBeenCalled() + }) + }) + + describe('new role', () => { + beforeEach(() => { + rolesToSelect.at(0).setSelected() + }) + + it('calls the API', () => { + expect(apolloMutateMock).toBeCalledWith( + expect.objectContaining({ + mutation: setUserRole, + variables: { + userId: 1, + isAdmin: false, + }, + }), + ) + }) + + it('emits "updateIsAdmin"', () => { + expect(wrapper.emitted('updateIsAdmin')).toEqual( + expect.arrayContaining([ + expect.arrayContaining([ + { + userId: 1, + isAdmin: null, + }, + ]), + ]), + ) + }) + + it('toasts success message', () => { + expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo') + }) + }) + }) + }) + }) + }) +}) diff --git a/admin/src/components/ChangeUserRoleFormular.vue b/admin/src/components/ChangeUserRoleFormular.vue new file mode 100644 index 000000000..1217ce7f0 --- /dev/null +++ b/admin/src/components/ChangeUserRoleFormular.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/admin/src/components/DeletedUserFormular.spec.js b/admin/src/components/DeletedUserFormular.spec.js index 5c41831e5..e6a2c94a6 100644 --- a/admin/src/components/DeletedUserFormular.spec.js +++ b/admin/src/components/DeletedUserFormular.spec.js @@ -47,200 +47,200 @@ describe('DeletedUserFormular', () => { }) it('has a DIV element with the class.delete-user-formular', () => { - expect(wrapper.find('.deleted-user-formular').exists()).toBeTruthy() - }) - }) - - describe('delete self', () => { - beforeEach(() => { - wrapper.setProps({ - item: { - userId: 0, - }, - }) + expect(wrapper.find('.deleted-user-formular').exists()).toBe(true) }) - it('shows a text that you cannot delete yourself', () => { - expect(wrapper.text()).toBe('removeNotSelf') - }) - }) - - describe('delete other user', () => { - beforeEach(() => { - wrapper.setProps({ - item: { - userId: 1, - deletedAt: null, - }, - }) - }) - - it('has a checkbox', () => { - expect(wrapper.find('input[type="checkbox"]').exists()).toBeTruthy() - }) - - it('shows the text "delete_user"', () => { - expect(wrapper.text()).toBe('delete_user') - }) - - describe('click on checkbox', () => { - beforeEach(async () => { - await wrapper.find('input[type="checkbox"]').setChecked() - }) - - it('has a confirmation button', () => { - expect(wrapper.find('button').exists()).toBeTruthy() - }) - - it('has the button text "delete_user"', () => { - expect(wrapper.find('button').text()).toBe('delete_user') - }) - - describe('confirm delete with success', () => { - beforeEach(async () => { - await wrapper.find('button').trigger('click') - }) - - it('calls the API', () => { - expect(apolloMutateMock).toBeCalledWith( - expect.objectContaining({ - mutation: deleteUser, - variables: { - userId: 1, - }, - }), - ) - }) - - it('emits update deleted At', () => { - expect(wrapper.emitted('updateDeletedAt')).toEqual( - expect.arrayContaining([ - expect.arrayContaining([ - { - userId: 1, - deletedAt: date, - }, - ]), - ]), - ) - }) - - it('unchecks the checkbox', () => { - expect(wrapper.find('input').attributes('checked')).toBe(undefined) - }) - }) - - describe('confirm delete with error', () => { - beforeEach(async () => { - apolloMutateMock.mockRejectedValue({ message: 'Oh no!' }) - await wrapper.find('button').trigger('click') - }) - - it('toasts an error message', () => { - expect(toastErrorSpy).toBeCalledWith('Oh no!') - }) - }) - - describe('click on checkbox again', () => { - beforeEach(async () => { - await wrapper.find('input[type="checkbox"]').setChecked(false) - }) - - it('has no confirmation button anymore', () => { - expect(wrapper.find('button').exists()).toBeFalsy() - }) - }) - }) - }) - - describe('recover user', () => { - beforeEach(() => { - wrapper.setProps({ - item: { - userId: 1, - deletedAt: date, - }, - }) - }) - - it('has a checkbox', () => { - expect(wrapper.find('input[type="checkbox"]').exists()).toBeTruthy() - }) - - it('shows the text "undelete_user"', () => { - expect(wrapper.text()).toBe('undelete_user') - }) - - describe('click on checkbox', () => { - beforeEach(async () => { - apolloMutateMock.mockResolvedValue({ - data: { - unDeleteUser: null, + describe('delete self', () => { + beforeEach(() => { + wrapper.setProps({ + item: { + userId: 0, }, }) - await wrapper.find('input[type="checkbox"]').setChecked() }) - it('has a confirmation button', () => { - expect(wrapper.find('button').exists()).toBeTruthy() + it('shows a text that you cannot delete yourself', () => { + expect(wrapper.text()).toBe('removeNotSelf') + }) + }) + + describe('delete other user', () => { + beforeEach(() => { + wrapper.setProps({ + item: { + userId: 1, + deletedAt: null, + }, + }) }) - it('has the button text "undelete_user"', () => { - expect(wrapper.find('button').text()).toBe('undelete_user') + it('has a checkbox', () => { + expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true) }) - describe('confirm recover with success', () => { + it('shows the text "delete_user"', () => { + expect(wrapper.text()).toBe('delete_user') + }) + + describe('click on checkbox', () => { beforeEach(async () => { - await wrapper.find('button').trigger('click') + await wrapper.find('input[type="checkbox"]').setChecked() }) - it('calls the API', () => { - expect(apolloMutateMock).toBeCalledWith( - expect.objectContaining({ - mutation: unDeleteUser, - variables: { - userId: 1, - }, - }), - ) + it('has a confirmation button', () => { + expect(wrapper.find('button').exists()).toBe(true) }) - it('emits update deleted At', () => { - expect(wrapper.emitted('updateDeletedAt')).toEqual( - expect.arrayContaining([ - expect.arrayContaining([ - { + it('has the button text "delete_user"', () => { + expect(wrapper.find('button').text()).toBe('delete_user') + }) + + describe('confirm delete with success', () => { + beforeEach(async () => { + await wrapper.find('button').trigger('click') + }) + + it('calls the API', () => { + expect(apolloMutateMock).toBeCalledWith( + expect.objectContaining({ + mutation: deleteUser, + variables: { userId: 1, - deletedAt: null, }, + }), + ) + }) + + it('emits update deleted At', () => { + expect(wrapper.emitted('updateDeletedAt')).toEqual( + expect.arrayContaining([ + expect.arrayContaining([ + { + userId: 1, + deletedAt: date, + }, + ]), ]), - ]), - ) + ) + }) + + it('unchecks the checkbox', () => { + expect(wrapper.find('input').attributes('checked')).toBe(undefined) + }) }) - it('unchecks the checkbox', () => { - expect(wrapper.find('input').attributes('checked')).toBe(undefined) + describe('confirm delete with error', () => { + beforeEach(async () => { + apolloMutateMock.mockRejectedValue({ message: 'Oh no!' }) + await wrapper.find('button').trigger('click') + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith('Oh no!') + }) + }) + + describe('click on checkbox again', () => { + beforeEach(async () => { + await wrapper.find('input[type="checkbox"]').setChecked(false) + }) + + it('has no confirmation button anymore', () => { + expect(wrapper.find('button').exists()).toBe(false) + }) + }) + }) + }) + + describe('recover user', () => { + beforeEach(() => { + wrapper.setProps({ + item: { + userId: 1, + deletedAt: date, + }, }) }) - describe('confirm recover with error', () => { - beforeEach(async () => { - apolloMutateMock.mockRejectedValue({ message: 'Oh no!' }) - await wrapper.find('button').trigger('click') - }) - - it('toasts an error message', () => { - expect(toastErrorSpy).toBeCalledWith('Oh no!') - }) + it('has a checkbox', () => { + expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true) }) - describe('click on checkbox again', () => { + it('shows the text "undelete_user"', () => { + expect(wrapper.text()).toBe('undelete_user') + }) + + describe('click on checkbox', () => { beforeEach(async () => { - await wrapper.find('input[type="checkbox"]').setChecked(false) + apolloMutateMock.mockResolvedValue({ + data: { + unDeleteUser: null, + }, + }) + await wrapper.find('input[type="checkbox"]').setChecked() }) - it('has no confirmation button anymore', () => { - expect(wrapper.find('button').exists()).toBeFalsy() + it('has a confirmation button', () => { + expect(wrapper.find('button').exists()).toBe(true) + }) + + it('has the button text "undelete_user"', () => { + expect(wrapper.find('button').text()).toBe('undelete_user') + }) + + describe('confirm recover with success', () => { + beforeEach(async () => { + await wrapper.find('button').trigger('click') + }) + + it('calls the API', () => { + expect(apolloMutateMock).toBeCalledWith( + expect.objectContaining({ + mutation: unDeleteUser, + variables: { + userId: 1, + }, + }), + ) + }) + + it('emits update deleted At', () => { + expect(wrapper.emitted('updateDeletedAt')).toEqual( + expect.arrayContaining([ + expect.arrayContaining([ + { + userId: 1, + deletedAt: null, + }, + ]), + ]), + ) + }) + + it('unchecks the checkbox', () => { + expect(wrapper.find('input').attributes('checked')).toBe(undefined) + }) + }) + + describe('confirm recover with error', () => { + beforeEach(async () => { + apolloMutateMock.mockRejectedValue({ message: 'Oh no!' }) + await wrapper.find('button').trigger('click') + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith('Oh no!') + }) + }) + + describe('click on checkbox again', () => { + beforeEach(async () => { + await wrapper.find('input[type="checkbox"]').setChecked(false) + }) + + it('has no confirmation button anymore', () => { + expect(wrapper.find('button').exists()).toBe(false) + }) }) }) }) diff --git a/admin/src/components/DeletedUserFormular.vue b/admin/src/components/DeletedUserFormular.vue index 03359d9f9..43a353ef4 100644 --- a/admin/src/components/DeletedUserFormular.vue +++ b/admin/src/components/DeletedUserFormular.vue @@ -28,6 +28,7 @@ export default { props: { item: { type: Object, + required: true, }, }, data() { diff --git a/admin/src/components/Tables/SearchUserTable.spec.js b/admin/src/components/Tables/SearchUserTable.spec.js index eb87357cc..e9072e54b 100644 --- a/admin/src/components/Tables/SearchUserTable.spec.js +++ b/admin/src/components/Tables/SearchUserTable.spec.js @@ -1,8 +1,6 @@ import { mount } from '@vue/test-utils' import SearchUserTable from './SearchUserTable.vue' -const date = new Date() - const localVue = global.localVue const apolloMutateMock = jest.fn().mockResolvedValue({}) @@ -96,16 +94,29 @@ describe('SearchUserTable', () => { await wrapper.findAll('tbody > tr').at(1).trigger('click') }) + describe('isAdmin', () => { + beforeEach(async () => { + await wrapper.find('div.change-user-role-formular').vm.$emit('updateIsAdmin', { + userId: 1, + isAdmin: new Date(), + }) + }) + + it('emits updateIsAdmin', () => { + expect(wrapper.emitted('updateIsAdmin')).toEqual([[1, expect.any(Date)]]) + }) + }) + describe('deleted at', () => { beforeEach(async () => { await wrapper.find('div.deleted-user-formular').vm.$emit('updateDeletedAt', { userId: 1, - deletedAt: date, + deletedAt: new Date(), }) }) it('emits updateDeletedAt', () => { - expect(wrapper.emitted('updateDeletedAt')).toEqual([[1, date]]) + expect(wrapper.emitted('updateDeletedAt')).toEqual([[1, expect.any(Date)]]) }) }) diff --git a/admin/src/components/Tables/SearchUserTable.vue b/admin/src/components/Tables/SearchUserTable.vue index 0be24a099..772160202 100644 --- a/admin/src/components/Tables/SearchUserTable.vue +++ b/admin/src/components/Tables/SearchUserTable.vue @@ -18,7 +18,7 @@