Refactor ReportModal

This commit is contained in:
Robert Schäfer 2019-03-10 15:14:58 +01:00
parent b7ca8a426b
commit bc2471c5df
6 changed files with 184 additions and 170 deletions

View File

@ -9,7 +9,7 @@
<template slot="footer">
<ds-button
class="cancel"
@click.prevent="$emit('close')"
@click="$emit('close')"
>
{{ $t('disable.cancel') }}
</ds-button>

View File

@ -0,0 +1,150 @@
import { shallowMount, render, mount, createLocalVue } from '@vue/test-utils'
import ReportModal from './ReportModal.vue'
import Vue from 'vue'
import Vuex from 'vuex'
import Styleguide from '@human-connection/styleguide'
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Styleguide)
describe('ReportModal.vue', () => {
let wrapper
let Wrapper
let propsData
let mocks
beforeEach(() => {
propsData = {}
mocks = {
$t: jest.fn(),
$filters: {
truncate: a => a
},
$toast: {
success: () => {},
error: () => {}
},
$apollo: {
mutate: jest.fn().mockResolvedValue()
}
}
})
describe('shallowMount', () => {
const Wrapper = () => {
return shallowMount(ReportModal, { propsData, mocks, localVue })
}
describe('defaults', () => {
it('isOpen false', () => {
expect(Wrapper().vm.isOpen).toBe(false)
})
it('success false', () => {
expect(Wrapper().vm.success).toBe(false)
})
it('loading false', () => {
expect(Wrapper().vm.loading).toBe(false)
})
it('disabled true', () => {
expect(Wrapper().vm.disabled).toBe(true)
})
})
describe('given a user', () => {
beforeEach(() => {
propsData = {
resource: {
type: 'user',
name: 'Bob Ross'
}
}
})
it('mentions user name', () => {
Wrapper()
const calls = mocks.$t.mock.calls
const expected = [['report.user.message', { name: 'Bob Ross' }]]
expect(calls).toEqual(expect.arrayContaining(expected))
})
})
})
describe('mount', () => {
const Wrapper = () => {
return mount(ReportModal, { propsData, mocks, localVue })
}
it('renders', () => {
expect(Wrapper().is('div')).toBe(true)
})
describe('given id and opened', () => {
beforeEach(() => {
propsData = {
isOpen: true,
resource: {
id: 4711
}
}
wrapper = Wrapper()
})
it('is enabled', async () => {
expect(wrapper.vm.disabled).toBe(false)
})
describe('click cancel button', () => {
beforeEach(async () => {
wrapper = Wrapper()
await wrapper.find('button.cancel').trigger('click')
})
it('emits close', () => {
expect(wrapper.emitted().close).toBeTruthy()
})
it('does not call mutation', () => {
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
})
describe('click confirm button', () => {
beforeEach(async () => {
jest.useFakeTimers()
await wrapper.find('button.confirm').trigger('click')
})
it('calls report mutation', async () => {
expect(mocks.$apollo.mutate).toHaveBeenCalled()
})
it('gets disabled', async () => {
expect(wrapper.vm.disabled).toBe(true)
})
it('sets success', async () => {
expect(wrapper.vm.success).toBe(true)
})
it('displays a success message', async () => {
const calls = mocks.$t.mock.calls
const expected = [['report.success']]
expect(calls).toEqual(expect.arrayContaining(expected))
})
describe('after timeout', () => {
beforeEach(jest.runAllTimers)
it('emits close', () => {
expect(wrapper.emitted().close).toBeTruthy()
})
})
})
})
})
})

View File

@ -2,11 +2,7 @@
<ds-modal
:title="title"
:is-open="isOpen"
:confirm-label="$t('report.submit')"
:cancel-label="$t('report.cancel')"
confirm-icon="warning"
@confirm="report"
@cancel="close"
>
<transition name="ds-transition-fade">
<ds-flex
@ -23,24 +19,25 @@
<template
slot="footer"
slot-scope="{ cancel, confirm, cancelLabel, confirmLabel }"
>
<ds-button
ghost
class="cancel"
icon="close"
:disabled="disabled || loading"
@click.prevent="cancel('cancel')"
@click="$emit('close')"
>
{{ cancelLabel }}
{{ $t('report.cancel') }}
</ds-button>
<ds-button
danger
class="confirm"
icon="exclamation-circle"
:loading="loading"
:disabled="disabled || loading"
@click.prevent="confirm('confirm')"
@click="confirm"
>
{{ confirmLabel }}
{{ $t('report.submit') }}
</ds-button>
</template>
</ds-modal>
@ -55,65 +52,54 @@ export default {
components: {
SweetalertIcon
},
props: {
isOpen: {
type: Boolean,
default: false
},
resource: {
type: Object,
default() {
return { id: null, type: 'contribution', name: '' }
}
}
},
data() {
return {
success: false,
loading: false,
disabled: false
disabled: !this.isOpen
}
},
computed: {
data() {
return this.$store.getters['modal/data'] || {}
},
title() {
if (!this.data.context) return ''
return this.$t(`report.${this.data.context}.title`)
return this.$t(`report.${this.resource.type}.title`)
},
message() {
if (!this.data.context) return ''
return this.$t(`report.${this.data.context}.message`, { name: this.name })
},
name() {
return this.$filters.truncate(this.data.name, 30)
},
isOpen() {
return this.$store.getters['modal/open'] === 'report'
}
},
watch: {
isOpen(open) {
if (open) {
this.success = false
this.disabled = false
this.loading = false
}
const name = this.$filters.truncate(this.resource.name, 30)
return this.$t(`report.${this.resource.type}.message`, { name })
}
},
methods: {
close() {
this.$store.commit('modal/SET_OPEN', {})
},
async report() {
async confirm() {
this.loading = true
this.disabled = true
try {
await this.$apollo.mutate({
mutation: gql`
mutation($id: ID!, $description: String) {
report(id: $id, description: $description) {
mutation($id: ID!) {
report(id: $id) {
id
}
}
`,
variables: {
id: this.data.id,
description: '-'
}
variables: { id: this.resource.id }
})
this.success = true
this.$toast.success('Thanks for reporting!')
setTimeout(this.close, 1500)
this.$toast.success(this.$t('report.success'))
setTimeout(() => {
this.$emit('close')
}, 1500)
} catch (err) {
this.$toast.error(err.message)
this.disabled = false

View File

@ -1,124 +0,0 @@
import { shallowMount, render, mount, createLocalVue } from '@vue/test-utils'
import ReportModal from './ReportModal.vue'
import Vue from 'vue'
import Vuex from 'vuex'
import { getters, mutations } from '../store/modal'
import Styleguide from '@human-connection/styleguide'
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Styleguide)
describe('ReportModal.vue', () => {
let Wrapper
let store
let state
let mocks
let $apollo
beforeEach(() => {
$apollo = {
mutate: jest.fn().mockResolvedValue(null)
}
state = {
open: 'report',
data: {}
}
})
describe('mount', () => {
const Wrapper = () => {
mocks = {
$t: () => {},
$toast: {
success: () => {},
error: () => {}
},
$apollo
}
store = new Vuex.Store({
state,
getters: {
'modal/open': getters.open,
'modal/data': getters.data
},
mutations: {
'modal/SET_OPEN': mutations.SET_OPEN
}
})
return mount(ReportModal, { store, mocks, localVue })
}
it('renders', () => {
expect(Wrapper().is('div')).toBe(true)
})
describe('modal visible', () => {
describe('shows a report', () => {
let wrapper
beforeEach(() => {
state = {
open: 'report',
data: {}
}
wrapper = Wrapper()
})
describe('click confirm button', () => {
const clickAction = async () => {
const confirmButton = wrapper.find('.ds-button-danger')
await confirmButton.trigger('click')
}
it('calls report mutation', async () => {
await clickAction()
expect($apollo.mutate).toHaveBeenCalled()
})
it('hides modal', async () => {
expect(wrapper.find('.ds-modal-wrapper').isEmpty()).toEqual(false)
await clickAction()
expect(wrapper.find('.ds-modal-wrapper').isEmpty()).toEqual(true)
})
it('disables buttons', async () => {
const expected = { disabled: 'disabled' }
let cancelButton = wrapper.findAll('footer button').at(0)
let confirmButton = wrapper.findAll('footer button').at(1)
expect(cancelButton.attributes()).toEqual(
expect.not.objectContaining(expected)
)
expect(confirmButton.attributes()).toEqual(
expect.not.objectContaining(expected)
)
await clickAction()
expect(cancelButton.attributes()).toEqual(
expect.objectContaining(expected)
)
expect(confirmButton.attributes()).toEqual(
expect.objectContaining(expected)
)
})
})
})
})
})
describe('shallowMount', () => {
const Wrapper = () => {
mocks = {
$t: () => {},
$apollo
}
store = new Vuex.Store({})
return shallowMount(ReportModal, { store, mocks, localVue })
}
describe('isOpen', () => {
it('defaults to false', () => {
expect(Wrapper().vm.isOpen).toBe(false)
})
})
})
})

View File

@ -159,6 +159,7 @@
"report": {
"submit": "Meldung senden",
"cancel": "Abbrechen",
"success": "Vielen Dank für das Melden!",
"user": {
"title": "Nutzer melden",
"type": "Nutzer",

View File

@ -159,6 +159,7 @@
"report": {
"submit": "Send Report",
"cancel": "Cancel",
"success": "Thanks for reporting!",
"user": {
"title": "Report User",
"type": "User",