fix frontend test, decouple some more

This commit is contained in:
einhornimmond 2025-05-16 07:04:06 +02:00
parent 720283d8fe
commit b8fd965f50
9 changed files with 529 additions and 301 deletions

View File

@ -52,7 +52,7 @@ describe('ContributionMessagesFormular', () => {
}
beforeEach(() => {
mockMutate.mockResolvedValue({})
mockMutate.mockResolvedValue({ data: { createContributionMessage: {} } })
wrapper = createWrapper()
})
@ -66,7 +66,7 @@ describe('ContributionMessagesFormular', () => {
it('resets the form on reset event', async () => {
await wrapper.find('form').trigger('reset')
expect(wrapper.vm.form.text).toBe('')
expect(wrapper.vm.formText).toBe('')
})
describe('form submission', () => {
@ -82,19 +82,14 @@ describe('ContributionMessagesFormular', () => {
})
})
it('emits get-list-contribution-messages event', async () => {
it('emits add-contribution-message event', async () => {
await nextTick()
expect(wrapper.emitted('get-list-contribution-messages')).toEqual([[false]])
})
it('emits update-status event', async () => {
await nextTick()
expect(wrapper.emitted('update-status')).toEqual([[42]])
expect(wrapper.emitted('add-contribution-message')).toEqual([[{}]])
})
it('resets the form text', async () => {
await nextTick()
expect(wrapper.vm.form.text).toBe('')
expect(wrapper.vm.formText).toBe('')
})
it('shows success toast', async () => {

View File

@ -77,16 +77,4 @@ describe('ContributionMessagesList', () => {
expect(wrapper.find('button').text()).toContain('form.close')
})
})
describe('events', () => {
beforeEach(() => {
wrapper = createWrapper()
})
it('emits update-status event when updateStatus method is called', async () => {
await wrapper.vm.updateStatus(42)
expect(wrapper.emitted('update-status')).toBeTruthy()
expect(wrapper.emitted('update-status')[0]).toEqual([42])
})
})
})

View File

@ -1,7 +1,6 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import ContributionForm from './ContributionForm.vue'
import { useForm } from 'vee-validate'
// Mock external components and dependencies
vi.mock('@/components/Inputs/InputAmount', () => ({
@ -37,12 +36,16 @@ vi.mock('vee-validate', () => ({
})),
}))
const global = {
stubs: ['BForm', 'BFormInput', 'BRow', 'BCol', 'BButton'],
}
describe('ContributionForm', () => {
let wrapper
const defaultProps = {
modelValue: {
date: '2024-09-12',
contributionDate: '2024-09-12',
memo: 'Test memo',
hours: 2,
amount: 40,
@ -51,12 +54,26 @@ describe('ContributionForm', () => {
maxGddThisMonth: 200,
}
const createWrapperWithDate = (date) => {
return mount(ContributionForm, {
props: {
...defaultProps,
modelValue: {
...defaultProps.modelValue,
contributionDate: date.toISOString(),
},
},
global,
})
}
const thisMonth = new Date()
const lastMonth = new Date()
lastMonth.setMonth(lastMonth.getMonth() - 1, 1)
beforeEach(() => {
wrapper = mount(ContributionForm, {
props: defaultProps,
global: {
stubs: ['BForm', 'BFormInput', 'BRow', 'BCol', 'BButton'],
},
global,
})
})
@ -65,19 +82,17 @@ describe('ContributionForm', () => {
})
describe('compute isThisMonth', () => {
it('return true', async () => {
await wrapper.setProps({
modelValue: { date: new Date().toISOString() },
})
expect(wrapper.vm.isThisMonth).toBe(true)
})
it('return false', async () => {
const now = new Date()
const lastMonth = new Date(now.setMonth(now.getMonth() - 1, 1))
await wrapper.setProps({
modelValue: { date: lastMonth.toISOString() },
})
expect(wrapper.vm.isThisMonth).toBe(false)
it.each([
[thisMonth, true, 'should return true for current month'],
[lastMonth, false, 'should return false for last month'],
[
new Date(new Date().setFullYear(new Date().getFullYear() + 1)),
false,
'should return false for next year',
],
])('%s => %s (%s)', (date, expected, desc) => {
const wrapper = createWrapperWithDate(date)
expect(wrapper.vm.isThisMonth).toBe(expected)
})
})
@ -85,21 +100,39 @@ describe('ContributionForm', () => {
it('if both max gdd are > 0', () => {
expect(wrapper.vm.noOpenCreation).toBeUndefined()
})
it('if max gdd for this month is 0, and form.date is in last month', async () => {
const now = new Date()
const lastMonth = new Date(now.setMonth(now.getMonth() - 1, 1))
await wrapper.setProps({
maxGddThisMonth: 0,
modelValue: { date: lastMonth.toISOString() },
describe('if form.date is in last month', () => {
beforeEach(() => {
wrapper = createWrapperWithDate(lastMonth)
})
it('if max gdd for this month is 0', async () => {
await wrapper.setProps({
maxGddThisMonth: 0,
})
expect(wrapper.vm.noOpenCreation).toBeUndefined()
})
it('if max gdd last month is 0', async () => {
await wrapper.setProps({
maxGddLastMonth: 0,
})
expect(wrapper.vm.noOpenCreation).toBe('contribution.noOpenCreation.lastMonth')
})
expect(wrapper.vm.noOpenCreation).toBeUndefined()
})
it('if max gdd for last month is 0, and form.date is in this month', async () => {
await wrapper.setProps({
maxGddLastMonth: 0,
modelValue: { date: new Date().toISOString() },
describe('if form.date is in this month', () => {
beforeEach(() => {
wrapper = createWrapperWithDate(thisMonth)
})
it('if max gdd for last month is 0', async () => {
await wrapper.setProps({
maxGddLastMonth: 0,
})
expect(wrapper.vm.noOpenCreation).toBeUndefined()
})
it('if max gdd this month is 0', async () => {
await wrapper.setProps({
maxGddThisMonth: 0,
})
expect(wrapper.vm.noOpenCreation).toBe('contribution.noOpenCreation.thisMonth')
})
expect(wrapper.vm.noOpenCreation).toBeUndefined()
})
it('if max gdd is 0 for both months', async () => {
await wrapper.setProps({
@ -108,30 +141,12 @@ describe('ContributionForm', () => {
})
expect(wrapper.vm.noOpenCreation).toBe('contribution.noOpenCreation.allMonth')
})
it('if max gdd this month is zero and form.date is inside this month', async () => {
await wrapper.setProps({
maxGddThisMonth: 0,
modelValue: { date: new Date().toISOString() },
})
expect(wrapper.vm.noOpenCreation).toBe('contribution.noOpenCreation.thisMonth')
})
it('if max gdd last month is zero and form.date is inside last month', async () => {
const now = new Date()
const lastMonth = new Date(now.setMonth(now.getMonth() - 1, 1))
await wrapper.setProps({
maxGddLastMonth: 0,
modelValue: { date: lastMonth.toISOString() },
})
expect(wrapper.vm.noOpenCreation).toBe('contribution.noOpenCreation.lastMonth')
})
})
it('computes disabled correctly', async () => {
expect(wrapper.vm.disabled).toBe(true)
await wrapper.setProps({
modelValue: { date: new Date().toISOString().slice(0, 10) },
})
wrapper = createWrapperWithDate(thisMonth)
wrapper.vm.form.amount = 100
@ -154,7 +169,7 @@ describe('ContributionForm', () => {
expect(wrapper.vm.form.amount).toBe('60.00')
})
it('emits update-contribution event on submit for existing contribution', async () => {
it('emits upsert-contribution event on submit for existing contribution', async () => {
const existingContribution = {
...defaultProps.modelValue,
id: '123',
@ -174,17 +189,17 @@ describe('ContributionForm', () => {
wrapper.vm.submit()
expect(wrapper.emitted('update-contribution')).toBeTruthy()
expect(wrapper.emitted('update-contribution')[0][0]).toEqual(
expect(wrapper.emitted('upsert-contribution')).toBeTruthy()
expect(wrapper.emitted('upsert-contribution')[0][0]).toEqual(
expect.objectContaining({
id: '123',
}),
)
})
it('emits set-contribution event on submit for new contribution', async () => {
it('emits upsert-contribution event on submit for new contribution', async () => {
wrapper.vm.submit()
expect(wrapper.emitted('set-contribution')).toBeTruthy()
expect(wrapper.emitted('upsert-contribution')).toBeTruthy()
})
})

View File

@ -85,11 +85,12 @@
</div>
</template>
<script setup>
import { reactive, computed, watch, ref, onMounted, onUnmounted, toRaw } from 'vue'
import { reactive, computed, ref, onMounted, onUnmounted, toRaw } from 'vue'
import { useI18n } from 'vue-i18n'
import ValidatedInput from '@/components/Inputs/ValidatedInput'
import LabeledInput from '@/components/Inputs/LabeledInput'
import { memo as memoSchema } from '@/validationSchemas'
import OpenCreationsAmount from './OpenCreationsAmount.vue'
import { object, date as dateSchema, number } from 'yup'
import { GDD_PER_HOUR } from '../../constants'

View File

@ -1,14 +1,24 @@
import { listAllContributions, listContributions } from '@/graphql/contributions.graphql'
import { useQuery } from '@vue/apollo-composable'
import { mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import ContributionList from './ContributionList'
import { createRouter, createWebHistory } from 'vue-router'
import { ref } from 'vue'
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {
contribution: {
noContributions: {
myContributions: 'No contributions',
emptyPage: 'No contributions',
},
},
},
},
})
const router = createRouter({
@ -53,93 +63,53 @@ describe('ContributionList', () => {
},
}
const contributions = {
contributionCount: 3,
listContributions: [
{
id: 0,
date: '07/06/2022',
memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.',
amount: '200',
status: 'IN_PROGRESS',
},
{
id: 1,
date: '06/22/2022',
memo: 'Ich habe 30 Stunden Frau Müller beim Einkaufen und im Haushalt geholfen.',
amount: '600',
status: 'CONFIRMED',
},
{
id: 2,
date: '05/04/2022',
memo: 'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.',
amount: '1000',
status: 'DENIED',
},
],
}
const propsData = {
allContribution: false,
emptyText: '',
}
const allContributions = {
contributionCount: 3,
listAllContributions: [
{
id: 0,
date: '07/06/2022',
memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.',
amount: '200',
status: 'IN_PROGRESS',
},
{
id: 1,
date: '06/22/2022',
memo: 'Ich habe 30 Stunden Frau Müller beim Einkaufen und im Haushalt geholfen.',
amount: '600',
status: 'CONFIRMED',
},
{
id: 2,
date: '05/04/2022',
memo: 'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.',
amount: '1000',
status: 'DENIED',
},
],
}
const contributions = ref({
listContributions: {
contributionCount: 3,
contributionList: [
{
id: 0,
date: '07/06/2022',
memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.',
amount: '200',
status: 'IN_PROGRESS',
},
{
id: 1,
date: '06/22/2022',
memo: 'Ich habe 30 Stunden Frau Müller beim Einkaufen und im Haushalt geholfen.',
amount: '600',
status: 'CONFIRMED',
},
{
id: 2,
date: '05/04/2022',
memo: 'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.',
amount: '1000',
status: 'DENIED',
},
],
},
})
const mountWrapper = () => {
return mount(ContributionList, {
propsData,
global,
})
}
const loading = ref(false)
describe('mount', () => {
const mockListContributionsQuery = vi.fn()
const mockListAllContributionsQuery = vi.fn()
beforeEach(() => {
vi.mocked(useQuery).mockImplementation((query) => {
if (query === listContributions) {
return {
result: contributions,
loading: vi.fn(),
onResult: mockListContributionsQuery,
refetch: vi.fn(),
}
}
if (query === listAllContributions) {
return {
result: allContributions,
loading: vi.fn(),
onResult: mockListAllContributionsQuery,
refetch: vi.fn(),
}
return {
result: contributions,
loading,
onResult: mockListContributionsQuery,
refetch: vi.fn(),
}
})
@ -151,23 +121,11 @@ describe('ContributionList', () => {
})
describe('mount as user contributions list', () => {
beforeEach(() => {
propsData.allContribution = false
})
it('fetches initial data', () => {
expect(mockListContributionsQuery).toHaveBeenCalled()
})
})
describe('mount as all contributions list', () => {
beforeEach(() => {
propsData.allContribution = true
})
it('fetches initial data', () => {
expect(mockListAllContributionsQuery).toHaveBeenCalled()
})
})
it('has a DIV .contribution-list', () => {
expect(wrapper.find('div.contribution-list').exists()).toBe(true)
})
@ -181,8 +139,7 @@ describe('ContributionList', () => {
describe('list count greater than page size', () => {
beforeEach(async () => {
contributions.contributionCount = 33
// await wrapper.setProps({ contributionCount: 33 })
contributions.value.listContributions.contributionCount = 33
})
it('has pagination buttons', () => {
@ -195,18 +152,17 @@ describe('ContributionList', () => {
window.scrollTo = scrollToMock
beforeEach(async () => {
contributions.contributionCount = 33
// await wrapper.setProps({ contributionCount: 33 })
await wrapper.findComponent({ name: 'BPagination' }).vm.$emit('update:modelValue', 2)
contributions.value.listContributions.contributionCount = 33
await wrapper
.findComponent({ name: 'PaginatorRouteParamsPage' })
.vm.$emit('update:modelValue', 2)
})
it('emits update contribution list', () => {
expect(wrapper.emitted('update-list-contributions')).toEqual([
[{ currentPage: 2, pageSize: 25 }],
])
it('updates current page', () => {
expect(wrapper.vm.currentPage).toBe(2)
})
it('scrolls to top', () => {
it.skip('scrolls to top', () => {
expect(scrollToMock).toHaveBeenCalledWith(0, 0)
})
})
@ -220,31 +176,7 @@ describe('ContributionList', () => {
})
it('emits update contribution form', () => {
expect(wrapper.emitted('update-contribution-form')).toEqual([['item']])
})
})
describe('delete contribution', () => {
beforeEach(async () => {
await wrapper
.findComponent({ name: 'ContributionListItem' })
.vm.$emit('delete-contribution', { id: 2 })
})
it('emits delete contribution', () => {
expect(wrapper.emitted('delete-contribution')).toEqual([[{ id: 2 }]])
})
})
describe('update status', () => {
beforeEach(async () => {
await wrapper
.findComponent({ name: 'ContributionListItem' })
.vm.$emit('update-status', { id: 2 })
})
it('emits update status', () => {
expect(wrapper.emitted('update-status')).toEqual([[{ id: 2 }]])
expect(wrapper.emitted('update-contribution-form')).toEqual([[{ item: 'item', page: 1 }]])
})
})
})

View File

@ -0,0 +1,158 @@
import { listAllContributions } from '@/graphql/contributions.graphql'
import { useQuery } from '@vue/apollo-composable'
import { mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import ContributionListAll from './ContributionListAll.vue'
import { createRouter, createWebHistory } from 'vue-router'
import { ref } from 'vue'
const i18n = createI18n({
legacy: false,
locale: 'en',
})
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'home',
component: { template: '<div>Home</div>' },
},
{
path: '/test',
name: 'test',
component: ContributionListAll,
},
],
})
vi.mock('@/components/Contributions/ContributionListAllItem.vue', () => ({
default: {
name: 'ContributionListAllItem',
template: '<div></div>',
},
}))
vi.mock('@vue/apollo-composable', () => ({
useQuery: vi.fn(),
}))
describe('ContributionListAll', () => {
let wrapper
const global = {
plugins: [i18n, router],
mocks: {
$filters: {
GDD: vi.fn((val) => val),
},
},
stubs: {
BPagination: true,
},
}
const allContributions = ref({
listAllContributions: {
contributionCount: 3,
contributionList: [
{
id: 0,
date: '07/06/2022',
memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.',
amount: '200',
status: 'IN_PROGRESS',
},
{
id: 1,
date: '06/22/2022',
memo: 'Ich habe 30 Stunden Frau Müller beim Einkaufen und im Haushalt geholfen.',
amount: '600',
status: 'CONFIRMED',
},
{
id: 2,
date: '05/04/2022',
memo: 'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.',
amount: '1000',
status: 'DENIED',
},
],
},
})
const mountWrapper = () => {
return mount(ContributionListAll, {
global,
})
}
const loading = ref(false)
describe('mount', () => {
beforeEach(() => {
vi.mocked(useQuery).mockImplementation((query) => {
return {
result: allContributions,
loading,
}
})
wrapper = mountWrapper()
})
afterEach(() => {
vi.clearAllMocks()
})
describe('mount as all contributions list', () => {
it('fetches initial data', () => {
expect(useQuery).toHaveBeenCalled()
})
})
it('has a DIV .contribution-list-all', () => {
expect(wrapper.find('div.contribution-list-all').exists()).toBe(true)
})
describe('pagination', () => {
describe('list count smaller than page size', () => {
it('has no pagination buttons', () => {
expect(wrapper.find('b-pagination-stub').exists()).toBe(false)
})
})
describe('list count greater than page size', () => {
beforeEach(async () => {
allContributions.value.listAllContributions.contributionCount = 33
})
it('has pagination buttons', () => {
expect(wrapper.find('b-pagination-stub').exists()).toBe(true)
})
})
describe('switch page', () => {
const scrollToMock = vi.fn()
window.scrollTo = scrollToMock
beforeEach(async () => {
allContributions.value.listAllContributions.contributionCount = 33
await wrapper
.findComponent({ name: 'PaginatorRouteParamsPage' })
.vm.$emit('update:modelValue', 2)
})
it('updates current page', () => {
expect(wrapper.vm.currentPage).toBe(2)
})
it.skip('scrolls to top', () => {
expect(scrollToMock).toHaveBeenCalledWith(0, 0)
})
})
})
})
})

View File

@ -7,7 +7,7 @@
{{ $t('contribution.noContributions.emptyPage') }}
</div>
</div>
<div v-else class="all-contribution-list">
<div v-else class="contribution-list-all">
<div v-for="item in items" :key="item.id + 'a'" class="mb-3">
<div :id="`contributionListItem-${item.id}`">
<contribution-list-all-item v-bind="item" />

View File

@ -0,0 +1,217 @@
import { mount } from '@vue/test-utils'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import ContributionListItem from './ContributionListItem'
import { BRow, BCol, BCollapse, BButton, BForm, BTextArea, BFormTextarea } from 'bootstrap-vue-next'
import VariantIcon from '@/components/VariantIcon.vue'
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {
short: 'Short format date',
contribution: {
deleted: 'Deleted contribution',
delete: 'Delete contribution',
confirmed: 'Confirmed contribution',
},
form: {
reply: 'Reply',
memo: 'Memo',
},
edit: 'Edit',
delete: 'Delete',
moderatorChat: 'Chat',
},
},
datetimeFormats: {
en: {
short: {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
},
},
},
})
vi.mock('@vue/apollo-composable', () => ({
useQuery: vi.fn(),
useLazyQuery: vi.fn(() => ({
onResult: vi.fn(),
onError: vi.fn(),
load: vi.fn(),
refetch: vi.fn(),
})),
useMutation: vi.fn(() => ({
mutate: vi.fn(),
onDone: vi.fn(),
onError: vi.fn(),
})),
}))
vi.mock('@/composables/useToast', () => ({
useAppToast: vi.fn(() => ({
addToast: vi.fn(),
toastError: vi.fn(),
toastSuccess: vi.fn(),
})),
}))
describe('ContributionListItem', () => {
let wrapper
const mocks = {
$filters: {
GDD: vi.fn((val) => val),
},
$t: vi.fn((key) => key),
$d: (date, format) => date.toISOString(),
}
const propsData = {
contributionId: 42,
contributionStatus: 'PENDING',
messagesCount: 2,
id: 1,
createdAt: '26/07/2022',
contributionDate: '07/06/2022',
memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.',
amount: '200',
}
const mountWrapper = () => {
return mount(ContributionListItem, {
global: {
plugins: [i18n],
mocks,
stubs: [
'IBiPencil',
'IBiTrash',
'IBiChatDots',
'BAvatar',
'VariantIcon',
'BButton',
'IBiArrowDownCircle',
'IBiArrowUpCircle',
'IBiArrowUpShort',
'ContributionMessagesListItem',
],
components: {
BRow,
BCol,
BCollapse,
BButton,
BForm,
BTextArea,
BFormTextarea,
},
},
props: propsData,
})
}
describe('mount', () => {
beforeEach(() => {
vi.clearAllMocks()
wrapper = mountWrapper()
})
it('has a DIV .contribution-list-item', () => {
expect(wrapper.find('div.contribution-list-item').exists()).toBe(true)
})
describe('contribution icon', () => {
it('is bell-fill by default', () => {
expect(wrapper.vm.icon).toBe('bell-fill')
})
it('is x-circle when contributionStatus is DELETED', async () => {
await wrapper.setProps({ contributionStatus: 'DELETED' })
expect(wrapper.vm.icon).toBe('trash')
})
it('is check when contributionStatus is CONFIRMED', async () => {
await wrapper.setProps({ contributionStatus: 'CONFIRMED' })
expect(wrapper.vm.icon).toBe('check')
})
})
describe('contribution variant', () => {
it('is primary by default', () => {
expect(wrapper.vm.variant).toBe('primary')
})
it('is danger when contributionStatus is DELETED', async () => {
await wrapper.setProps({ contributionStatus: 'DELETED' })
expect(wrapper.vm.variant).toBe('danger')
})
it('is success at when contributionStatus is CONFIRMED', async () => {
await wrapper.setProps({ contributionStatus: 'CONFIRMED' })
expect(wrapper.vm.variant).toBe('success')
})
it('is warning at when contributionStatus is IN_PROGRESS', async () => {
await wrapper.setProps({ contributionStatus: 'IN_PROGRESS' })
expect(wrapper.vm.variant).toBe('205')
})
})
describe('delete contribution', () => {
describe('edit contribution', () => {
beforeEach(() => {
wrapper.find('div.test-edit-contribution').trigger('click')
})
it('emits update contribution form', () => {
expect(wrapper.emitted('update-contribution-form')).toEqual([
[
{
id: 1,
contributionDate: '07/06/2022',
memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.',
amount: '200',
},
],
])
})
})
describe('confirm deletion', () => {
beforeEach(() => {
vi.spyOn(window, 'confirm').mockImplementation(() => true)
wrapper.find('div.test-delete-contribution').trigger('click')
})
it('emits delete contribution', () => {
expect(wrapper.emitted('contribution-changed')).toBeTruthy()
})
})
describe('cancel deletion', () => {
beforeEach(async () => {
vi.spyOn(window, 'confirm').mockImplementation(() => false)
await wrapper.find('div.test-delete-contribution').trigger('click')
})
it('does not emit delete contribution', () => {
expect(wrapper.emitted('delete-contribution')).toBeFalsy()
})
})
})
describe('updateStatus', () => {
it('updates status of a contribution', async () => {
wrapper.vm.contributionStatus = 'IN_PROGRESS'
wrapper.vm.addContributionMessage({})
expect(wrapper.vm.localStatus).toBe('PENDING')
})
})
})
})

View File

@ -62,9 +62,16 @@ vi.mock('@/components/Contributions/OpenCreationsAmount', () => ({
},
}))
vi.mock('@/components/Contributions/ContributionForm', () => ({
vi.mock('@/components/Contributions/ContributionEdit', () => ({
default: {
name: 'ContributionForm',
name: 'ContributionEdit',
template: '<div></div>',
},
}))
vi.mock('@/components/Contributions/ContributionCreate', () => ({
default: {
name: 'ContributionCreate',
template: '<div></div>',
},
}))
@ -76,6 +83,13 @@ vi.mock('@/components/Contributions/ContributionList', () => ({
},
}))
vi.mock('@/components/Contributions/ContributionListAll', () => ({
default: {
name: 'ContributionListAll',
template: '<div></div>',
},
}))
describe('Community', () => {
let wrapper
let mockRouter
@ -140,9 +154,7 @@ describe('Community', () => {
},
components: {
BTabs,
},
stub: {
BTab: true,
BTab,
},
},
})
@ -156,17 +168,12 @@ describe('Community', () => {
it('initializes with correct data', () => {
expect(wrapper.vm.tabIndex).toBe(0)
})
it('fetches initial data', () => {
expect(mockOpenCreationsQuery).toHaveBeenCalled()
expect(mockCountContributionsInProgress).toHaveBeenCalled()
})
})
describe('tabs', () => {
it('has three tabs', () => {
expect(wrapper.findAll('.tabs')).toHaveLength(1)
expect(wrapper.findAll('btab')).toHaveLength(3)
expect(wrapper.findAllComponents(BTab)).toHaveLength(3)
})
it.skip('updates tab index when route changes', async () => {
@ -176,105 +183,20 @@ describe('Community', () => {
})
})
describe('handleSaveContribution', () => {
it('calls createContributionMutation and shows success toast on success', async () => {
const contributionData = { date: '2023-09-12', memo: 'Test contribution', amount: '100' }
mockCreateContributionMutation.mockResolvedValue({ data: { createContribution: true } })
await wrapper.vm.handleSaveContribution(contributionData)
expect(mockCreateContributionMutation).toHaveBeenCalledWith({
creationDate: contributionData.date,
memo: contributionData.memo,
amount: contributionData.amount,
})
expect(mockToast.toastSuccess).toHaveBeenCalledWith('contribution.submitted')
})
it('shows error toast on failure', async () => {
const contributionData = { date: '2023-09-12', memo: 'Test contribution', amount: '100' }
mockCreateContributionMutation.mockRejectedValue(new Error('Create Contribution failed!'))
await wrapper.vm.handleSaveContribution(contributionData)
expect(mockToast.toastError).toHaveBeenCalledWith('Create Contribution failed!')
})
})
describe('handleUpdateContribution', () => {
it('calls updateContributionMutation and shows success toast on success', async () => {
const contributionData = {
id: 1,
date: '2023-09-12',
memo: 'Updated contribution',
amount: '200',
}
mockUpdateContributionMutation.mockResolvedValue({ data: { updateContribution: true } })
await wrapper.vm.handleUpdateContribution(contributionData)
expect(mockUpdateContributionMutation).toHaveBeenCalledWith({
contributionId: contributionData.id,
creationDate: contributionData.date,
memo: contributionData.memo,
amount: contributionData.amount,
})
expect(mockToast.toastSuccess).toHaveBeenCalledWith('contribution.updated')
})
it('shows error toast on failure', async () => {
const contributionData = {
id: 1,
date: '2023-09-12',
memo: 'Updated contribution',
amount: '200',
}
mockUpdateContributionMutation.mockRejectedValue(new Error('Update Contribution failed!'))
await wrapper.vm.handleUpdateContribution(contributionData)
expect(mockToast.toastError).toHaveBeenCalledWith('Update Contribution failed!')
})
})
describe('handleDeleteContribution', () => {
it('calls deleteContributionMutation and shows success toast on success', async () => {
const contributionData = { id: 1 }
mockDeleteContributionMutation.mockResolvedValue({ data: { deleteContribution: true } })
await wrapper.vm.handleDeleteContribution(contributionData)
expect(mockDeleteContributionMutation).toHaveBeenCalledWith({ id: contributionData.id })
expect(mockToast.toastSuccess).toHaveBeenCalledWith('contribution.deleted')
})
it('shows error toast on failure', async () => {
const contributionData = { id: 1 }
mockDeleteContributionMutation.mockRejectedValue(new Error('Delete Contribution failed!'))
await wrapper.vm.handleDeleteContribution(contributionData)
expect(mockToast.toastError).toHaveBeenCalledWith('Delete Contribution failed!')
})
})
describe('handleUpdateContributionForm', () => {
it('updates form data and changes tab', () => {
const contributionData = {
id: 2,
contributionDate: '2023-09-12',
memo: 'Test contribution',
amount: '300',
item: { id: 2, contributionDate: '2023-09-12', memo: 'Test contribution', amount: '300' },
page: 2,
}
wrapper.vm.handleUpdateContributionForm(contributionData)
expect(wrapper.vm.form).toEqual({
expect(wrapper.vm.itemData).toEqual({
id: 2,
date: '2023-09-12',
contributionDate: '2023-09-12',
memo: 'Test contribution',
amount: '300',
hours: 15, // 300 / 20
})
expect(wrapper.vm.tabIndex).toBe(0)
expect(mockRouter.push).toHaveBeenCalledWith({ params: { tab: 'contribute' } })