88import { describe , it , expect , beforeEach , vi } from 'vitest' ;
99import { CostService } from '../cashflow-cost.service' ;
1010import { CostType } from '../../../../middle-layer/types/CostType' ;
11+ import { Frequency } from '../../../../middle-layer/types/Frequency' ;
1112import { CashflowCost } from '../../../../middle-layer/types/CashflowCost' ;
1213import { TDateISO } from '../../utils/date' ;
1314
@@ -170,6 +171,7 @@ describe('CostService', () => {
170171 name : ' Food ' ,
171172 amount : 200 ,
172173 type : CostType . MealsFood ,
174+ frequency : Frequency . Yearly ,
173175 date : '2026-03-22' as TDateISO ,
174176 } ;
175177
@@ -179,6 +181,7 @@ describe('CostService', () => {
179181 name : 'Food' ,
180182 amount : 200 ,
181183 type : CostType . MealsFood ,
184+ frequency : Frequency . Yearly ,
182185 date : '2026-03-22' ,
183186 } ) ;
184187 expect ( mockPut ) . toHaveBeenCalledWith ( {
@@ -187,6 +190,7 @@ describe('CostService', () => {
187190 name : 'Food' ,
188191 amount : 200 ,
189192 type : CostType . MealsFood ,
193+ frequency : Frequency . Yearly ,
190194 date : '2026-03-22' ,
191195 } ,
192196 ConditionExpression : 'attribute_not_exists(#name)' ,
@@ -202,6 +206,7 @@ describe('CostService', () => {
202206 name : 'Food' ,
203207 amount : 0 ,
204208 type : CostType . MealsFood ,
209+ frequency : Frequency . Yearly ,
205210 date : '2026-03-22' as TDateISO ,
206211 } ) ,
207212 ) . rejects . toThrow ( BadRequestException ) ;
@@ -210,6 +215,7 @@ describe('CostService', () => {
210215 name : 'Food' ,
211216 amount : 0 ,
212217 type : CostType . MealsFood ,
218+ frequency : Frequency . Yearly ,
213219 date : '2026-03-22' as TDateISO ,
214220 } ) ,
215221 ) . rejects . toThrow ( 'amount must be a finite positive number' ) ;
@@ -221,6 +227,19 @@ describe('CostService', () => {
221227 name : 'Food' ,
222228 amount : 100 ,
223229 type : 'INVALID' as unknown as CostType ,
230+ frequency : Frequency . Yearly ,
231+ date : '2026-03-22' as TDateISO ,
232+ } ) ,
233+ ) . rejects . toThrow ( BadRequestException ) ;
234+ } ) ;
235+
236+ it ( 'throws BadRequestException for invalid frequency' , async ( ) => {
237+ await expect (
238+ service . createCost ( {
239+ name : 'Food' ,
240+ amount : 100 ,
241+ type : CostType . MealsFood ,
242+ frequency : 'INVALID' as unknown as Frequency ,
224243 date : '2026-03-22' as TDateISO ,
225244 } ) ,
226245 ) . rejects . toThrow ( BadRequestException ) ;
@@ -232,6 +251,7 @@ describe('CostService', () => {
232251 name : ' ' ,
233252 amount : 100 ,
234253 type : CostType . MealsFood ,
254+ frequency : Frequency . Yearly ,
235255 date : '2026-03-22' as TDateISO ,
236256 } ) ,
237257 ) . rejects . toThrow ( BadRequestException ) ;
@@ -240,6 +260,7 @@ describe('CostService', () => {
240260 name : ' ' ,
241261 amount : 100 ,
242262 type : CostType . MealsFood ,
263+ frequency : Frequency . Yearly ,
243264 date : '2026-03-22' as TDateISO ,
244265 } ) ,
245266 ) . rejects . toThrow ( 'name must be a non-empty string' ) ;
@@ -253,6 +274,7 @@ describe('CostService', () => {
253274 name : 'Food' ,
254275 amount : 100 ,
255276 type : CostType . MealsFood ,
277+ frequency : Frequency . Yearly ,
256278 date : '2026-03-22' as TDateISO ,
257279 } ) ,
258280 ) . rejects . toThrow ( ConflictException ) ;
@@ -261,6 +283,7 @@ describe('CostService', () => {
261283 name : 'Food' ,
262284 amount : 100 ,
263285 type : CostType . MealsFood ,
286+ frequency : Frequency . Yearly ,
264287 date : '2026-03-22' as TDateISO ,
265288 } ) ,
266289 ) . rejects . toThrow ( 'Cost with name Food already exists' ) ;
@@ -274,6 +297,7 @@ describe('CostService', () => {
274297 name : 'Food' ,
275298 amount : 100 ,
276299 type : CostType . MealsFood ,
300+ frequency : Frequency . Yearly ,
277301 date : '2026-03-22' as TDateISO ,
278302 } ) ,
279303 ) . rejects . toThrow ( InternalServerErrorException ) ;
@@ -287,6 +311,7 @@ describe('CostService', () => {
287311 name : 'Food' ,
288312 amount : 100 ,
289313 type : CostType . MealsFood ,
314+ frequency : Frequency . Yearly ,
290315 date : '2026-03-22' as TDateISO ,
291316 } ) ,
292317 ) . rejects . toThrow ( InternalServerErrorException ) ;
@@ -295,6 +320,7 @@ describe('CostService', () => {
295320 name : 'Food' ,
296321 amount : 100 ,
297322 type : CostType . MealsFood ,
323+ frequency : Frequency . Yearly ,
298324 date : '2026-03-22' as TDateISO ,
299325 } ) ,
300326 ) . rejects . toThrow ( 'Failed to create cost' ) ;
@@ -308,6 +334,7 @@ describe('CostService', () => {
308334 name : 'Food' ,
309335 amount : 200 ,
310336 type : CostType . MealsFood ,
337+ frequency : Frequency . Yearly ,
311338 date : '2026-03-22' ,
312339 } ,
313340 } ) ;
@@ -318,6 +345,7 @@ describe('CostService', () => {
318345 name : 'Food' ,
319346 amount : 300 ,
320347 type : CostType . Services ,
348+ frequency : Frequency . OneTime ,
321349 date : '2026-03-22' as TDateISO ,
322350 } ;
323351 mockPutPromise . mockResolvedValue ( { } ) ;
@@ -326,6 +354,7 @@ describe('CostService', () => {
326354 name : 'Food' ,
327355 amount : 300 ,
328356 type : CostType . Services ,
357+ frequency : Frequency . OneTime ,
329358 date : '2026-03-22' as TDateISO ,
330359 } ) ;
331360
@@ -340,6 +369,7 @@ describe('CostService', () => {
340369 name : 'Food' ,
341370 amount : 300 ,
342371 type : CostType . Services ,
372+ frequency : Frequency . OneTime ,
343373 date : '2026-03-22' ,
344374 } ,
345375 ConditionExpression : 'attribute_exists(#name)' ,
@@ -354,13 +384,15 @@ describe('CostService', () => {
354384 name : 'Food' ,
355385 amount : 200 ,
356386 type : CostType . MealsFood ,
387+ frequency : Frequency . Yearly ,
357388 date : '2026-03-22' as TDateISO ,
358389 } ) ;
359390
360391 expect ( result ) . toEqual ( {
361392 name : 'Food' ,
362393 amount : 200 ,
363394 type : CostType . MealsFood ,
395+ frequency : Frequency . Yearly ,
364396 date : '2026-03-22' ,
365397 } ) ;
366398 expect ( mockPut ) . not . toHaveBeenCalled ( ) ;
@@ -373,6 +405,7 @@ describe('CostService', () => {
373405 name : 'Food' ,
374406 amount : Number . NaN ,
375407 type : CostType . MealsFood ,
408+ frequency : Frequency . Yearly ,
376409 date : '2026-03-22' as TDateISO ,
377410 } ) ,
378411 ) . rejects . toThrow ( BadRequestException ) ;
@@ -384,6 +417,19 @@ describe('CostService', () => {
384417 name : 'Food' ,
385418 amount : 250 ,
386419 type : 'INVALID' as unknown as CostType ,
420+ frequency : Frequency . Yearly ,
421+ date : '2026-03-22' as TDateISO ,
422+ } ) ,
423+ ) . rejects . toThrow ( BadRequestException ) ;
424+ } ) ;
425+
426+ it ( 'throws BadRequestException for invalid frequency' , async ( ) => {
427+ await expect (
428+ service . updateCost ( 'Food' , {
429+ name : 'Food' ,
430+ amount : 250 ,
431+ type : CostType . MealsFood ,
432+ frequency : 'INVALID' as unknown as Frequency ,
387433 date : '2026-03-22' as TDateISO ,
388434 } ) ,
389435 ) . rejects . toThrow ( BadRequestException ) ;
@@ -395,6 +441,7 @@ describe('CostService', () => {
395441 name : 'Food' ,
396442 amount : 250 ,
397443 type : CostType . MealsFood ,
444+ frequency : Frequency . Yearly ,
398445 date : 'not-a-date' as unknown as TDateISO ,
399446 } ) ,
400447 ) . rejects . toThrow ( BadRequestException ) ;
@@ -403,6 +450,7 @@ describe('CostService', () => {
403450 name : 'Food' ,
404451 amount : 250 ,
405452 type : CostType . MealsFood ,
453+ frequency : Frequency . Yearly ,
406454 date : 'not-a-date' as unknown as TDateISO ,
407455 } ) ,
408456 ) . rejects . toThrow ( 'date must be a valid ISO 8601 format string' ) ;
@@ -416,6 +464,7 @@ describe('CostService', () => {
416464 name : 'Food' ,
417465 amount : 250 ,
418466 type : CostType . MealsFood ,
467+ frequency : Frequency . Yearly ,
419468 date : '2026-03-22' as TDateISO ,
420469 } ) ,
421470 ) . rejects . toThrow ( NotFoundException ) ;
@@ -424,6 +473,7 @@ describe('CostService', () => {
424473 name : 'Food' ,
425474 amount : 250 ,
426475 type : CostType . MealsFood ,
476+ frequency : Frequency . Yearly ,
427477 date : '2026-03-22' as TDateISO ,
428478 } ) ,
429479 ) . rejects . toThrow ( 'Cost with name Food not found' ) ;
@@ -438,6 +488,7 @@ describe('CostService', () => {
438488 name : 'Food' ,
439489 amount : 250 ,
440490 type : CostType . MealsFood ,
491+ frequency : Frequency . Yearly ,
441492 date : '2026-03-22' as TDateISO ,
442493 } ) ,
443494 ) . rejects . toThrow ( InternalServerErrorException ) ;
@@ -446,6 +497,7 @@ describe('CostService', () => {
446497 name : 'Food' ,
447498 amount : 250 ,
448499 type : CostType . MealsFood ,
500+ frequency : Frequency . Yearly ,
449501 date : '2026-03-22' as TDateISO ,
450502 } ) ,
451503 ) . rejects . toThrow ( 'Failed to update cost Food' ) ;
@@ -461,13 +513,15 @@ describe('CostService', () => {
461513 name : 'Meals' ,
462514 amount : 300 ,
463515 type : CostType . MealsFood ,
516+ frequency : Frequency . Yearly ,
464517 date : '2026-03-22' as TDateISO ,
465518 } ) ;
466519
467520 expect ( result ) . toEqual ( {
468521 name : 'Meals' ,
469522 amount : 300 ,
470523 type : CostType . MealsFood ,
524+ frequency : Frequency . Yearly ,
471525 date : '2026-03-22' ,
472526 } ) ;
473527 expect ( mockGet ) . toHaveBeenCalledWith ( {
@@ -483,6 +537,7 @@ describe('CostService', () => {
483537 name : 'Meals' ,
484538 amount : 300 ,
485539 type : CostType . MealsFood ,
540+ frequency : Frequency . Yearly ,
486541 date : '2026-03-22' ,
487542 } ,
488543 ConditionExpression : 'attribute_not_exists(#name)' ,
@@ -515,13 +570,15 @@ describe('CostService', () => {
515570 name : 'Meals' ,
516571 amount : 300 ,
517572 type : CostType . MealsFood ,
573+ frequency : Frequency . Yearly ,
518574 date : '2026-03-22' as TDateISO ,
519575 } ) ;
520576
521577 expect ( result ) . toEqual ( {
522578 name : 'Meals' ,
523579 amount : 300 ,
524580 type : CostType . MealsFood ,
581+ frequency : Frequency . Yearly ,
525582 date : '2026-03-22' ,
526583 } ) ;
527584 } ) ;
@@ -534,6 +591,7 @@ describe('CostService', () => {
534591 name : 'Meals' ,
535592 amount : 300 ,
536593 type : CostType . MealsFood ,
594+ frequency : Frequency . Yearly ,
537595 date : '2026-03-22' as TDateISO ,
538596 } ) ,
539597 ) . rejects . toThrow ( NotFoundException ) ;
@@ -542,6 +600,7 @@ describe('CostService', () => {
542600 name : 'Meals' ,
543601 amount : 300 ,
544602 type : CostType . MealsFood ,
603+ frequency : Frequency . Yearly ,
545604 date : '2026-03-22' as TDateISO ,
546605 } ) ,
547606 ) . rejects . toThrow ( 'Cost with name Food not found' ) ;
@@ -560,6 +619,7 @@ describe('CostService', () => {
560619 name : 'Meals' ,
561620 amount : 300 ,
562621 type : CostType . MealsFood ,
622+ frequency : Frequency . Yearly ,
563623 date : '2026-03-22' as TDateISO ,
564624 } ) ,
565625 ) . rejects . toThrow ( ConflictException ) ;
@@ -568,6 +628,7 @@ describe('CostService', () => {
568628 name : 'Meals' ,
569629 amount : 300 ,
570630 type : CostType . MealsFood ,
631+ frequency : Frequency . Yearly ,
571632 date : '2026-03-22' as TDateISO ,
572633 } ) ,
573634 ) . rejects . toThrow ( 'Cost with name Meals already exists' ) ;
@@ -584,6 +645,7 @@ describe('CostService', () => {
584645 name : 'Meals' ,
585646 amount : 300 ,
586647 type : CostType . MealsFood ,
648+ frequency : Frequency . Yearly ,
587649 date : '2026-03-22' as TDateISO ,
588650 } ) ,
589651 ) . rejects . toThrow ( InternalServerErrorException ) ;
@@ -592,6 +654,7 @@ describe('CostService', () => {
592654 name : 'Meals' ,
593655 amount : 300 ,
594656 type : CostType . MealsFood ,
657+ frequency : Frequency . Yearly ,
595658 date : '2026-03-22' as TDateISO ,
596659 } ) ,
597660 ) . rejects . toThrow ( 'Failed to update cost Food' ) ;
@@ -605,6 +668,7 @@ describe('CostService', () => {
605668 name : 'Food' ,
606669 amount : 200 ,
607670 type : CostType . MealsFood ,
671+ frequency : Frequency . Yearly ,
608672 date : '2026-03-22' as TDateISO ,
609673 } ) ,
610674 ) . rejects . toThrow ( InternalServerErrorException ) ;
0 commit comments