From 93130193f4db81bc9671ac2f88385a2644180a95 Mon Sep 17 00:00:00 2001 From: Maxim Kolyubyakin Date: Tue, 11 Apr 2023 18:41:43 +0200 Subject: [PATCH] LITE-27142 ActivateDialog and DeleteDialog unit tests --- ui/app/views/ActivateDialog.spec.js | 242 ++++++++++++++++++++++++++++ ui/app/views/ActivateDialog.vue | 3 - ui/app/views/DeleteDialog.spec.js | 133 +++++++++++++++ ui/app/views/ItemDetails.spec.js | 18 +++ 4 files changed, 393 insertions(+), 3 deletions(-) create mode 100644 ui/app/views/ActivateDialog.spec.js create mode 100644 ui/app/views/DeleteDialog.spec.js diff --git a/ui/app/views/ActivateDialog.spec.js b/ui/app/views/ActivateDialog.spec.js new file mode 100644 index 0000000..3530b27 --- /dev/null +++ b/ui/app/views/ActivateDialog.spec.js @@ -0,0 +1,242 @@ +import ActivateDialog from './ActivateDialog.vue'; + +import databases from '~api/databases'; + + +jest.mock('~api/databases', () => ({ + activate: jest.fn((id, obj) => ({ id, ...obj })), +})); + +describe('ActivateDialog', () => { + let cmp; + let context; + + beforeEach(() => { + cmp = ActivateDialog; + }); + + describe('#data', () => { + it('should provide initial data', () => { + expect(cmp.data()).toEqual({ + dialogOpened: false, + saving: false, + form: { + credentials: { + name: '', + host: '', + username: '', + password: '', + }, + workload: 'small', + }, + }); + }); + }); + + describe('#computed', () => { + describe('#allowSaving', () => { + it.each([ + [ + true, + { + credentials: { + username: 'username', + password: 'password', + host: 'host', + }, + }, + ], + [ + false, + { + credentials: { + username: '', + password: '', + host: '', + name: 'DB', + }, + }, + ], + ])('returns %s', (expected, form) => { + expect(cmp.computed.allowSaving({ form })).toBe(expected); + }); + }); + }); + + describe('#methods', () => { + describe('#close()', () => { + beforeEach(() => { + context = { + dialogOpened: true, + form: {}, + $emit: jest.fn(), + }; + + cmp.methods.close.call(context); + }); + + it('marks dialog as closed', () => { + expect(context.dialogOpened).toBe(false); + }); + + it('emits `closed` signal', () => { + expect(context.$emit).toHaveBeenCalledWith('closed'); + }); + + it('reinitializes the form', () => { + expect(context.form).toEqual({ + credentials: { + name: '', + host: '', + username: '', + password: '', + }, + workload: 'small', + }); + }); + }); + + describe('#save()', () => { + beforeEach(async () => { + context = { + $emit: jest.fn(), + close: jest.fn(), + saving: true, + + item: { + id: 'DB-123', + }, + + form: { + id: '...', + name: 'some DB', + workload: 'large', + credentials: { 1: 2 }, + }, + }; + + await cmp.methods.save.call(context); + }); + + it('should call activate api', () => { + expect(databases.activate).toHaveBeenCalledWith( + 'DB-123', + { + workload: 'large', + credentials: { 1: 2 }, + }, + ); + }); + + it('should emit `saved` event', () => { + expect(context.$emit).toHaveBeenCalledWith('saved'); + }); + + it('should call #close', () => { + expect(context.close).toHaveBeenCalled(); + }); + + it('should set saving to false', () => { + expect(context.saving).toBe(false); + }); + }); + }); + + describe('#watch', () => { + describe('#value()', () => { + it.each([true, false])('should set dialogOpen value to %s', (value) => { + context = { + dialogOpened: false, + item: {}, + }; + + cmp.watch.value.handler.call(context, value); + + expect(context.dialogOpened).toBe(value); + }); + + it.each([ + [ + { + id: 'DB-1', + workload: 'large', + }, + { + id: 'DB-1', + workload: 'large', + credentials: { + name: '', + host: '', + username: '', + password: '', + }, + }, + ], + [ + { + name: 'db', + credentials: { + random: 'stuff', + }, + }, + { + name: 'db', + credentials: { + random: 'stuff', + }, + }, + ], + ])('should set dialogOpen value', (item, form) => { + context = { + dialogOpened: false, + form: null, + item, + }; + + cmp.watch.value.handler.call(context, true); + + expect(context.form).toEqual(form); + }); + }); + + describe('#dialogOpened()', () => { + let setContext; + let call; + + beforeEach(() => { + setContext = (value) => { + context = { + value, + + $emit: jest.fn(), + }; + }; + + call = (...args) => (cmp.watch.dialogOpened).call(context, ...args); + }); + + it.each([ + ['foo', 'bar', ['$emit', 'toHaveBeenCalledWith', ['input', 'foo']]], + ['foo', 'foo', ['$emit', 'not.toHaveBeenCalledWith']], + ])( + 'When argument=%j and value=%j should "%j"', + (arg, value, spec) => { + /* eslint-disable-next-line prefer-const */ + let [property, satisfies, condition = undefined] = spec; + + setContext(value); + call(arg); + + let assertion = expect(context[property]); + + if (/^not\./.test(satisfies)) { + assertion = assertion.not; + satisfies = satisfies.replace('not.', ''); + } + + assertion[satisfies](...(condition || [])); + }, + ); + }); + }); +}); diff --git a/ui/app/views/ActivateDialog.vue b/ui/app/views/ActivateDialog.vue index 70e9032..1366418 100644 --- a/ui/app/views/ActivateDialog.vue +++ b/ui/app/views/ActivateDialog.vue @@ -113,7 +113,6 @@ export default { }), computed: { - isEdit: ({ item }) => Boolean(item), allowSaving: ({ form }) => Boolean(( form.credentials.username && form.credentials.password @@ -128,8 +127,6 @@ export default { this.dialogOpened = false; this.$emit('closed'); this.form = initialForm(); - this.users = []; - this.regions = []; }, async save() { diff --git a/ui/app/views/DeleteDialog.spec.js b/ui/app/views/DeleteDialog.spec.js new file mode 100644 index 0000000..f59d765 --- /dev/null +++ b/ui/app/views/DeleteDialog.spec.js @@ -0,0 +1,133 @@ +import DeleteDialog from './DeleteDialog.vue'; + +import databases from '~api/databases'; + + +jest.mock('~api/databases', () => ({ + delete: jest.fn(), +})); + +describe('DeleteDialog', () => { + let cmp; + let context; + + beforeEach(() => { + cmp = DeleteDialog; + }); + + describe('#data', () => { + it('should provide initial data', () => { + expect(cmp.data()).toEqual({ + dialogOpened: false, + saving: false, + }); + }); + }); + + describe('#methods', () => { + describe('#close()', () => { + beforeEach(() => { + context = { + dialogOpened: true, + $emit: jest.fn(), + }; + + cmp.methods.close.call(context); + }); + + it('marks dialog as closed', () => { + expect(context.dialogOpened).toBe(false); + }); + + it('emits `closed` signal', () => { + expect(context.$emit).toHaveBeenCalledWith('closed'); + }); + }); + + describe('#save()', () => { + beforeEach(async () => { + context = { + $emit: jest.fn(), + close: jest.fn(), + saving: true, + + item: { + id: 'DB-456', + }, + }; + + await cmp.methods.save.call(context); + }); + + it('should call delete api', () => { + expect(databases.delete).toHaveBeenCalledWith('DB-456'); + }); + + it('should emit `saved` event', () => { + expect(context.$emit).toHaveBeenCalledWith('saved'); + }); + + it('should call #close', () => { + expect(context.close).toHaveBeenCalled(); + }); + + it('should set saving to false', () => { + expect(context.saving).toBe(false); + }); + }); + }); + + describe('#watch', () => { + describe('#value()', () => { + it.each([true, false])('should set dialogOpen value to %s', (value) => { + context = { + dialogOpened: false, + }; + + cmp.watch.value.handler.call(context, value); + + expect(context.dialogOpened).toBe(value); + }); + }); + + describe('#dialogOpened()', () => { + let setContext; + let call; + + beforeEach(() => { + setContext = (value) => { + context = { + value, + + $emit: jest.fn(), + }; + }; + + call = (...args) => (cmp.watch.dialogOpened).call(context, ...args); + }); + + it.each([ + ['foo', 'bar', ['$emit', 'toHaveBeenCalledWith', ['input', 'foo']]], + ['foo', 'foo', ['$emit', 'not.toHaveBeenCalledWith']], + ])( + 'When argument=%j and value=%j should "%j"', + (arg, value, spec) => { + /* eslint-disable-next-line prefer-const */ + let [property, satisfies, condition = undefined] = spec; + + setContext(value); + call(arg); + + let assertion = expect(context[property]); + + if (/^not\./.test(satisfies)) { + assertion = assertion.not; + satisfies = satisfies.replace('not.', ''); + } + + assertion[satisfies](...(condition || [])); + }, + ); + }); + }); +}); diff --git a/ui/app/views/ItemDetails.spec.js b/ui/app/views/ItemDetails.spec.js index dbc3322..1da9bf4 100644 --- a/ui/app/views/ItemDetails.spec.js +++ b/ui/app/views/ItemDetails.spec.js @@ -46,6 +46,24 @@ describe('ItemDetails', () => { }); }); + describe('openActivateDialog', () => { + it('should set isActivateDialogOpened to true', () => { + context = { isActivateDialogOpened: false }; + cmp.methods.openActivateDialog.call(context); + + expect(context.isActivateDialogOpened).toBe(true); + }); + }); + + describe('openDeleteDialog', () => { + it('should set isDeleteDialogOpened to true', () => { + context = { isDeleteDialogOpened: false }; + cmp.methods.openDeleteDialog.call(context); + + expect(context.isDeleteDialogOpened).toBe(true); + }); + }); + describe('#openEditDialog()', () => { it('should set isDialogOpened to true', () => { context = { isDialogOpened: false };