From a7c701a932755809bbed0e02f48bf1b99a81558f Mon Sep 17 00:00:00 2001 From: Daniel Grijalva Date: Fri, 26 Apr 2019 14:03:22 -0700 Subject: [PATCH 1/5] Delete post feature -Create post deletion modal -Add post deletion locales (EN) -Add delete post option in menu --- webapp/components/ContentMenu.vue | 7 ++ webapp/components/Modal.vue | 11 +- webapp/components/Modal/DeleteModal.vue | 134 ++++++++++++++++++++++++ webapp/locales/en.json | 8 ++ 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 webapp/components/Modal/DeleteModal.vue diff --git a/webapp/components/ContentMenu.vue b/webapp/components/ContentMenu.vue index 5de2820da..29473d6b2 100644 --- a/webapp/components/ContentMenu.vue +++ b/webapp/components/ContentMenu.vue @@ -77,6 +77,13 @@ export default { }).href, icon: 'edit' }) + routes.push({ + name: this.$t(`post.delete.title`), + callback: () => { + this.openModal('delete') + }, + icon: 'trash' + }) } if (this.isOwner && this.resourceType === 'comment') { routes.push({ diff --git a/webapp/components/Modal.vue b/webapp/components/Modal.vue index 0507e5439..2ea482190 100644 --- a/webapp/components/Modal.vue +++ b/webapp/components/Modal.vue @@ -14,19 +14,28 @@ :name="name" @close="close" /> + + + diff --git a/webapp/locales/en.json b/webapp/locales/en.json index b0f06952b..e61d969d9 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -111,6 +111,14 @@ }, "takeAction": { "name": "Take action" + }, + "delete": { + "submit": "Delete", + "cancel": "Cancel", + "success": "Post deleted successfully", + "title": "Delete Post", + "type": "Contribution", + "message": "Do you really want to delete the post \"{name}\"?" } }, "quotes": { From 1f56ce69bf4317ab84ef52b8ce77a5fc0f482376 Mon Sep 17 00:00:00 2001 From: Daniel Grijalva Date: Fri, 26 Apr 2019 16:00:51 -0700 Subject: [PATCH 2/5] Spanish translation --- webapp/locales/es.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webapp/locales/es.json b/webapp/locales/es.json index ba46f9ec1..5beab2eef 100644 --- a/webapp/locales/es.json +++ b/webapp/locales/es.json @@ -88,6 +88,14 @@ }, "takeAction": { "name": "Tomar acción" + }, + "delete": { + "submit": "Borrar", + "cancel": "Cancelar", + "success": "Mensaje borrado satisfactoriamente", + "title": "Borrar mensaje", + "type": "Mensaje", + "message": "¿Realmente quieres borrar el mensaje \"{name}\"?" } }, "quotes": { From 6af29c6b8ea6bf27fe6a215cba33e920ccdb9718 Mon Sep 17 00:00:00 2001 From: Daniel Grijalva Date: Wed, 8 May 2019 12:15:48 -0700 Subject: [PATCH 3/5] DeleteModal tests --- webapp/components/Modal/DeleteModal.spec.js | 155 ++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 webapp/components/Modal/DeleteModal.spec.js diff --git a/webapp/components/Modal/DeleteModal.spec.js b/webapp/components/Modal/DeleteModal.spec.js new file mode 100644 index 000000000..9432115d2 --- /dev/null +++ b/webapp/components/Modal/DeleteModal.spec.js @@ -0,0 +1,155 @@ +import { shallowMount, mount, createLocalVue } from '@vue/test-utils' +import DeleteModal from './DeleteModal.vue' +import Vue from 'vue' +import Vuex from 'vuex' +import Styleguide from '@human-connection/styleguide' +import VueRouter from 'vue-router' + +const routes = [{ path: '/' }] +const router = new VueRouter({routes}) +const localVue = createLocalVue() + +localVue.use(Vuex) +localVue.use(Styleguide) +localVue.use(VueRouter) + +describe('DeleteModal.vue', () => { + let wrapper + let Wrapper + let propsData + let mocks + + beforeEach(() => { + propsData = { + type: 'contribution', + id: 'c300' + } + mocks = { + $t: jest.fn(), + $filters: { + truncate: a => a + }, + $toast: { + success: () => {}, + error: () => {} + }, + $apollo: { + mutate: jest.fn().mockResolvedValue() + } + } + }) + + describe('shallowMount', () => { + const Wrapper = () => { + return shallowMount(DeleteModal, { propsData, mocks, localVue, router }) + } + + describe('defaults', () => { + it('success false', () => { + expect(Wrapper().vm.success).toBe(false) + }) + + it('loading false', () => { + expect(Wrapper().vm.loading).toBe(false) + }) + }) + + describe('given a post', () => { + beforeEach(() => { + propsData = { + id: 'p23', + type: 'post', + name: 'It is a post' + } + }) + + it('mentions post title', () => { + Wrapper() + const calls = mocks.$t.mock.calls + const expected = [['post.delete.message', { name: 'It is a post' }]] + expect(calls).toEqual(expect.arrayContaining(expected)) + }) + }) + }) + + describe('mount', () => { + const Wrapper = () => { + return mount(DeleteModal, { propsData, mocks, localVue, router}) + } + + beforeEach(jest.useFakeTimers) + + it('renders', () => { + expect(Wrapper().is('div')).toBe(true) + }) + + describe('given id', () => { + beforeEach(() => { + propsData = { + type: 'user', + id: 'u3' + } + wrapper = Wrapper() + }) + + describe('click cancel button', () => { + beforeEach(() => { + wrapper = Wrapper() + wrapper.find('button.cancel').trigger('click') + }) + + describe('after timeout', () => { + beforeEach(jest.runAllTimers) + + it('fades away', () => { + expect(wrapper.vm.isOpen).toBe(false) + }) + + it('emits "close"', () => { + expect(wrapper.emitted().close).toBeTruthy() + }) + + it('does not call mutation', () => { + expect(mocks.$apollo.mutate).not.toHaveBeenCalled() + }) + }) + }) + + describe('click confirm button', () => { + beforeEach(() => { + wrapper.find('button.confirm').trigger('click') + }) + + it('calls delete mutation', () => { + expect(mocks.$apollo.mutate).toHaveBeenCalled() + }) + + it('sets success', () => { + expect(wrapper.vm.success).toBe(true) + }) + + it('displays a success message', () => { + const calls = mocks.$t.mock.calls + const expected = [['post.delete.success']] + expect(calls).toEqual(expect.arrayContaining(expected)) + }) + + describe('after timeout', () => { + beforeEach(jest.runAllTimers) + + it('fades away', () => { + expect(wrapper.vm.isOpen).toBe(false) + }) + + it('emits close', () => { + expect(wrapper.emitted().close).toBeTruthy() + }) + + it('resets success', () => { + expect(wrapper.vm.success).toBe(false) + }) + }) + }) + }) + }) +}) From 87c3f4619e79f618a316da145c92ea66a066e786 Mon Sep 17 00:00:00 2001 From: Daniel Grijalva Date: Wed, 8 May 2019 13:29:39 -0700 Subject: [PATCH 4/5] lint fix --- webapp/components/Modal/DeleteModal.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webapp/components/Modal/DeleteModal.spec.js b/webapp/components/Modal/DeleteModal.spec.js index 9432115d2..e52c252ca 100644 --- a/webapp/components/Modal/DeleteModal.spec.js +++ b/webapp/components/Modal/DeleteModal.spec.js @@ -6,7 +6,7 @@ import Styleguide from '@human-connection/styleguide' import VueRouter from 'vue-router' const routes = [{ path: '/' }] -const router = new VueRouter({routes}) +const router = new VueRouter({ routes }) const localVue = createLocalVue() localVue.use(Vuex) @@ -53,7 +53,7 @@ describe('DeleteModal.vue', () => { expect(Wrapper().vm.loading).toBe(false) }) }) - + describe('given a post', () => { beforeEach(() => { propsData = { @@ -74,7 +74,7 @@ describe('DeleteModal.vue', () => { describe('mount', () => { const Wrapper = () => { - return mount(DeleteModal, { propsData, mocks, localVue, router}) + return mount(DeleteModal, { propsData, mocks, localVue, router }) } beforeEach(jest.useFakeTimers) From 07bf1b4653a264e9e1a32b3ac8ba47b986b50058 Mon Sep 17 00:00:00 2001 From: Daniel Grijalva Date: Wed, 8 May 2019 13:57:47 -0700 Subject: [PATCH 5/5] comply with tests --- webapp/components/Modal/DeleteModal.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/webapp/components/Modal/DeleteModal.vue b/webapp/components/Modal/DeleteModal.vue index 740d59317..0f9fc0d7b 100644 --- a/webapp/components/Modal/DeleteModal.vue +++ b/webapp/components/Modal/DeleteModal.vue @@ -98,13 +98,13 @@ export default { setTimeout(() => { this.success = false this.$emit('close') - if (this.$router.history.current.name === 'post-id-slug'){ - // redirect to index - this.$router.history.push('/') + if (this.$router.history.current.name === 'post-id-slug') { + // redirect to index + this.$router.history.push('/') } else { - // reload the page (when deleting from profile or index) - this.$router.history.go() - } + // reload the page (when deleting from profile or index) + window.location.assign(window.location.href) + } }, 500) }, 1500) } catch (err) {