Skip to content

Commit e0f4ead

Browse files
committed
Add unit tests for useExpenseForm, useToast, and router
Introduces comprehensive unit tests for the useExpenseForm and useToast composables, covering state management, workflows, and multi-instance behavior. Also adds basic structural tests for the router configuration.
1 parent 4cc37e6 commit e0f4ead

3 files changed

Lines changed: 609 additions & 0 deletions

File tree

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
import { describe, it, expect, beforeEach } from 'vitest'
2+
import { useExpenseForm } from './useExpenseForm'
3+
import type { Expense } from '../types'
4+
5+
describe('useExpenseForm', () => {
6+
beforeEach(() => {
7+
// Reset form state before each test
8+
const { closeForm } = useExpenseForm()
9+
closeForm()
10+
})
11+
12+
describe('Initial state', () => {
13+
it('should have form closed initially', () => {
14+
const { showForm } = useExpenseForm()
15+
16+
expect(showForm.value).toBe(false)
17+
})
18+
19+
it('should have no editing expense initially', () => {
20+
const { editingExpense } = useExpenseForm()
21+
22+
expect(editingExpense.value).toBeNull()
23+
})
24+
})
25+
26+
describe('openFormForNew', () => {
27+
it('should open form', () => {
28+
const { openFormForNew, showForm } = useExpenseForm()
29+
30+
openFormForNew()
31+
32+
expect(showForm.value).toBe(true)
33+
})
34+
35+
it('should clear editing expense', () => {
36+
const { openFormForNew, editingExpense } = useExpenseForm()
37+
38+
openFormForNew()
39+
40+
expect(editingExpense.value).toBeNull()
41+
})
42+
43+
it('should clear previous editing expense when opening for new', () => {
44+
const { openFormForEdit, openFormForNew, editingExpense } = useExpenseForm()
45+
46+
const expense: Expense = {
47+
id: '123',
48+
amount: 100,
49+
categoryId: 'cat-1',
50+
date: '2025-10-13',
51+
note: 'Test'
52+
}
53+
54+
openFormForEdit(expense)
55+
expect(editingExpense.value).not.toBeNull()
56+
57+
openFormForNew()
58+
expect(editingExpense.value).toBeNull()
59+
})
60+
})
61+
62+
describe('openFormForEdit', () => {
63+
it('should open form', () => {
64+
const { openFormForEdit, showForm } = useExpenseForm()
65+
66+
const expense: Expense = {
67+
id: '123',
68+
amount: 100,
69+
categoryId: 'cat-1',
70+
date: '2025-10-13'
71+
}
72+
73+
openFormForEdit(expense)
74+
75+
expect(showForm.value).toBe(true)
76+
})
77+
78+
it('should set editing expense', () => {
79+
const { openFormForEdit, editingExpense } = useExpenseForm()
80+
81+
const expense: Expense = {
82+
id: '123',
83+
amount: 100,
84+
categoryId: 'cat-1',
85+
date: '2025-10-13',
86+
note: 'Test expense'
87+
}
88+
89+
openFormForEdit(expense)
90+
91+
expect(editingExpense.value).toEqual(expense)
92+
})
93+
94+
it('should handle expense with all optional fields', () => {
95+
const { openFormForEdit, editingExpense } = useExpenseForm()
96+
97+
const expense: Expense = {
98+
id: '123',
99+
amount: 100,
100+
categoryId: 'cat-1',
101+
categoryName: 'Food',
102+
categoryDisplayName: '食物',
103+
categoryColor: 'red',
104+
date: '2025-10-13',
105+
note: 'Lunch',
106+
userId: 'user-1',
107+
createdAt: '2025-10-13T10:00:00Z',
108+
updatedAt: '2025-10-13T10:00:00Z'
109+
}
110+
111+
openFormForEdit(expense)
112+
113+
expect(editingExpense.value).toEqual(expense)
114+
})
115+
116+
it('should replace previous editing expense', () => {
117+
const { openFormForEdit, editingExpense } = useExpenseForm()
118+
119+
const expense1: Expense = {
120+
id: '123',
121+
amount: 100,
122+
categoryId: 'cat-1',
123+
date: '2025-10-13'
124+
}
125+
126+
const expense2: Expense = {
127+
id: '456',
128+
amount: 200,
129+
categoryId: 'cat-2',
130+
date: '2025-10-14'
131+
}
132+
133+
openFormForEdit(expense1)
134+
expect(editingExpense.value?.id).toBe('123')
135+
136+
openFormForEdit(expense2)
137+
expect(editingExpense.value?.id).toBe('456')
138+
})
139+
})
140+
141+
describe('closeForm', () => {
142+
it('should close form', () => {
143+
const { openFormForNew, closeForm, showForm } = useExpenseForm()
144+
145+
openFormForNew()
146+
expect(showForm.value).toBe(true)
147+
148+
closeForm()
149+
150+
expect(showForm.value).toBe(false)
151+
})
152+
153+
it('should clear editing expense', () => {
154+
const { openFormForEdit, closeForm, editingExpense } = useExpenseForm()
155+
156+
const expense: Expense = {
157+
id: '123',
158+
amount: 100,
159+
categoryId: 'cat-1',
160+
date: '2025-10-13'
161+
}
162+
163+
openFormForEdit(expense)
164+
expect(editingExpense.value).not.toBeNull()
165+
166+
closeForm()
167+
168+
expect(editingExpense.value).toBeNull()
169+
})
170+
171+
it('should handle closing already closed form', () => {
172+
const { closeForm, showForm } = useExpenseForm()
173+
174+
expect(() => closeForm()).not.toThrow()
175+
expect(showForm.value).toBe(false)
176+
})
177+
})
178+
179+
describe('Multiple instances', () => {
180+
it('should share state between multiple instances', () => {
181+
const instance1 = useExpenseForm()
182+
const instance2 = useExpenseForm()
183+
184+
instance1.openFormForNew()
185+
186+
expect(instance2.showForm.value).toBe(true)
187+
})
188+
189+
it('should share editing expense between instances', () => {
190+
const instance1 = useExpenseForm()
191+
const instance2 = useExpenseForm()
192+
193+
const expense: Expense = {
194+
id: '123',
195+
amount: 100,
196+
categoryId: 'cat-1',
197+
date: '2025-10-13'
198+
}
199+
200+
instance1.openFormForEdit(expense)
201+
202+
expect(instance2.editingExpense.value).toEqual(expense)
203+
})
204+
205+
it('should allow different instances to modify shared state', () => {
206+
const instance1 = useExpenseForm()
207+
const instance2 = useExpenseForm()
208+
209+
instance1.openFormForNew()
210+
instance2.closeForm()
211+
212+
expect(instance1.showForm.value).toBe(false)
213+
})
214+
})
215+
216+
describe('Workflow scenarios', () => {
217+
it('should support create -> close workflow', () => {
218+
const { openFormForNew, closeForm, showForm, editingExpense } = useExpenseForm()
219+
220+
openFormForNew()
221+
expect(showForm.value).toBe(true)
222+
expect(editingExpense.value).toBeNull()
223+
224+
closeForm()
225+
expect(showForm.value).toBe(false)
226+
expect(editingExpense.value).toBeNull()
227+
})
228+
229+
it('should support edit -> close workflow', () => {
230+
const { openFormForEdit, closeForm, showForm, editingExpense } = useExpenseForm()
231+
232+
const expense: Expense = {
233+
id: '123',
234+
amount: 100,
235+
categoryId: 'cat-1',
236+
date: '2025-10-13'
237+
}
238+
239+
openFormForEdit(expense)
240+
expect(showForm.value).toBe(true)
241+
expect(editingExpense.value).toEqual(expense)
242+
243+
closeForm()
244+
expect(showForm.value).toBe(false)
245+
expect(editingExpense.value).toBeNull()
246+
})
247+
248+
it('should support edit -> create workflow', () => {
249+
const { openFormForEdit, openFormForNew, showForm, editingExpense } = useExpenseForm()
250+
251+
const expense: Expense = {
252+
id: '123',
253+
amount: 100,
254+
categoryId: 'cat-1',
255+
date: '2025-10-13'
256+
}
257+
258+
openFormForEdit(expense)
259+
expect(editingExpense.value).not.toBeNull()
260+
261+
openFormForNew()
262+
expect(showForm.value).toBe(true)
263+
expect(editingExpense.value).toBeNull()
264+
})
265+
266+
it('should support multiple edit operations', () => {
267+
const { openFormForEdit, editingExpense } = useExpenseForm()
268+
269+
const expenses: Expense[] = [
270+
{ id: '1', amount: 100, categoryId: 'cat-1', date: '2025-10-13' },
271+
{ id: '2', amount: 200, categoryId: 'cat-2', date: '2025-10-14' },
272+
{ id: '3', amount: 300, categoryId: 'cat-3', date: '2025-10-15' }
273+
]
274+
275+
expenses.forEach(expense => {
276+
openFormForEdit(expense)
277+
expect(editingExpense.value).toEqual(expense)
278+
})
279+
})
280+
})
281+
})

0 commit comments

Comments
 (0)