File size: 3,777 Bytes
79ed62f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { describe, it, expect, beforeEach } from 'vitest';
import { useTripStore } from '../../../src/store/tripStore';
import { resetAllStores } from '../../helpers/store';
import { buildBudgetItem } from '../../helpers/factories';
import type { BudgetItemMember } from '../../../src/types';

beforeEach(() => {
  resetAllStores();
});

describe('remoteEventHandler > budget', () => {
  const member1: BudgetItemMember = { user_id: 5, paid: 0, username: 'eve' };
  const member2: BudgetItemMember = { user_id: 6, paid: 1, username: 'frank' };

  const seedData = () => {
    useTripStore.setState({
      budgetItems: [
        buildBudgetItem({ id: 1, persons: 1, members: [{ ...member1 }] }),
        buildBudgetItem({ id: 2, persons: 2, members: [{ ...member2 }] }),
      ],
    });
  };

  it('FE-WSEVT-BUDGET-001: budget:created adds item to budgetItems', () => {
    seedData();
    const newItem = buildBudgetItem({ id: 99, name: 'Hotel' });
    useTripStore.getState().handleRemoteEvent({ type: 'budget:created', item: newItem });
    const { budgetItems } = useTripStore.getState();
    expect(budgetItems).toHaveLength(3);
    expect(budgetItems.find(i => i.id === 99)).toBeDefined();
  });

  it('FE-WSEVT-BUDGET-002: budget:created is idempotent — no duplicate if same ID', () => {
    seedData();
    const duplicate = buildBudgetItem({ id: 1, name: 'Duplicate' });
    useTripStore.getState().handleRemoteEvent({ type: 'budget:created', item: duplicate });
    const { budgetItems } = useTripStore.getState();
    expect(budgetItems).toHaveLength(2);
  });

  it('FE-WSEVT-BUDGET-003: budget:updated replaces item in array', () => {
    seedData();
    const updated = buildBudgetItem({ id: 1, name: 'Updated Hotel', total_price: 500 });
    useTripStore.getState().handleRemoteEvent({ type: 'budget:updated', item: updated });
    const { budgetItems } = useTripStore.getState();
    const item = budgetItems.find(i => i.id === 1);
    expect(item?.name).toBe('Updated Hotel');
    expect(item?.total_price).toBe(500);
  });

  it('FE-WSEVT-BUDGET-004: budget:deleted removes item by ID', () => {
    seedData();
    useTripStore.getState().handleRemoteEvent({ type: 'budget:deleted', itemId: 1 });
    const { budgetItems } = useTripStore.getState();
    expect(budgetItems).toHaveLength(1);
    expect(budgetItems.find(i => i.id === 1)).toBeUndefined();
  });

  it('FE-WSEVT-BUDGET-005: budget:members-updated replaces entire members array and persons count', () => {
    seedData();
    const newMembers: BudgetItemMember[] = [{ user_id: 7, paid: 1, username: 'grace' }, { user_id: 8, paid: 0, username: 'heidi' }];
    useTripStore.getState().handleRemoteEvent({
      type: 'budget:members-updated',
      itemId: 1,
      members: newMembers,
      persons: 3,
    });
    const { budgetItems } = useTripStore.getState();
    const item = budgetItems.find(i => i.id === 1);
    expect(item?.members).toEqual(newMembers);
    expect(item?.persons).toBe(3);
    // Other item should be unchanged
    const item2 = budgetItems.find(i => i.id === 2);
    expect(item2?.members).toEqual([{ ...member2 }]);
  });

  it('FE-WSEVT-BUDGET-006: budget:member-paid-updated toggles specific member paid status', () => {
    seedData();
    useTripStore.getState().handleRemoteEvent({
      type: 'budget:member-paid-updated',
      itemId: 1,
      userId: 5,
      paid: true,
    });
    const { budgetItems } = useTripStore.getState();
    const item = budgetItems.find(i => i.id === 1);
    const m = item?.members?.find(m => m.user_id === 5);
    expect(m?.paid).toBe(true);
    // Other item members unchanged (member2 keeps its seeded paid value)
    const item2 = budgetItems.find(i => i.id === 2);
    expect(item2?.members?.[0].paid).toBe(1);
  });
});