mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 14:21:46 +00:00
Derive client domain types from the shared schema contracts
Add entity/response Zod schemas to @trek/shared (place, trip, assignment, day, budget, packing, reservation), each matched against the producing server service, and re-export them from client types.ts instead of the hand-written duplicates that had drifted (name/title, amount/total_price, owner_id/user_id, cover_url/cover_image, ...). Updates the call sites and test fixtures the corrected types surfaced; type-only, no runtime behaviour change.
This commit is contained in:
@@ -43,7 +43,7 @@ describe('budgetSlice', () => {
|
||||
const existing = buildBudgetItem({ trip_id: 1 });
|
||||
seedStore(useTripStore, { budgetItems: [existing] });
|
||||
|
||||
const result = await useTripStore.getState().addBudgetItem(1, { name: 'Hotel', amount: 200 });
|
||||
const result = await useTripStore.getState().addBudgetItem(1, { name: 'Hotel', total_price: 200 });
|
||||
|
||||
expect(result.name).toBe('Hotel');
|
||||
expect(useTripStore.getState().budgetItems).toHaveLength(2);
|
||||
@@ -64,7 +64,7 @@ describe('budgetSlice', () => {
|
||||
|
||||
describe('updateBudgetItem', () => {
|
||||
it('FE-BUDGET-004: updateBudgetItem replaces item in array', async () => {
|
||||
const item = buildBudgetItem({ id: 10, trip_id: 1, name: 'Old', amount: 100 });
|
||||
const item = buildBudgetItem({ id: 10, trip_id: 1, name: 'Old', total_price: 100 });
|
||||
seedStore(useTripStore, { budgetItems: [item] });
|
||||
|
||||
server.use(
|
||||
@@ -74,16 +74,16 @@ describe('budgetSlice', () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await useTripStore.getState().updateBudgetItem(1, 10, { name: 'Updated', amount: 150 });
|
||||
const result = await useTripStore.getState().updateBudgetItem(1, 10, { name: 'Updated', total_price: 150 });
|
||||
|
||||
expect(result.name).toBe('Updated');
|
||||
expect(useTripStore.getState().budgetItems[0].name).toBe('Updated');
|
||||
});
|
||||
|
||||
it('FE-BUDGET-005: updateBudgetItem with total_price triggers loadReservations when reservation_id present', async () => {
|
||||
const item = buildBudgetItem({ id: 10, trip_id: 1, amount: 100 });
|
||||
const item = buildBudgetItem({ id: 10, trip_id: 1, total_price: 100 });
|
||||
const initialReservation = buildReservation({ trip_id: 1 });
|
||||
const newReservation = buildReservation({ trip_id: 1, name: 'Refreshed Reservation' });
|
||||
const newReservation = buildReservation({ trip_id: 1, title: 'Refreshed Reservation' });
|
||||
seedStore(useTripStore, {
|
||||
budgetItems: [item],
|
||||
reservations: [initialReservation],
|
||||
@@ -106,7 +106,7 @@ describe('budgetSlice', () => {
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
|
||||
expect(useTripStore.getState().reservations).toHaveLength(1);
|
||||
expect(useTripStore.getState().reservations[0].name).toBe('Refreshed Reservation');
|
||||
expect(useTripStore.getState().reservations[0].title).toBe('Refreshed Reservation');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -162,7 +162,7 @@ describe('budgetSlice', () => {
|
||||
|
||||
describe('toggleBudgetMemberPaid', () => {
|
||||
it('FE-BUDGET-008: toggleBudgetMemberPaid updates paid status after API success', async () => {
|
||||
const member = { user_id: 5, paid: false };
|
||||
const member = { user_id: 5, paid: 0, username: 'dave' };
|
||||
const item = buildBudgetItem({ id: 10, trip_id: 1, members: [member] });
|
||||
seedStore(useTripStore, { budgetItems: [item] });
|
||||
|
||||
|
||||
@@ -42,20 +42,20 @@ describe('reservationsSlice', () => {
|
||||
|
||||
describe('addReservation', () => {
|
||||
it('FE-RESERV-002: addReservation prepends to reservations array', async () => {
|
||||
const existing = buildReservation({ trip_id: 1, name: 'Existing' });
|
||||
const existing = buildReservation({ trip_id: 1, title: 'Existing' });
|
||||
seedStore(useTripStore, { reservations: [existing] });
|
||||
|
||||
const result = await useTripStore.getState().addReservation(1, {
|
||||
name: 'New Hotel',
|
||||
title: 'New Hotel',
|
||||
type: 'hotel',
|
||||
status: 'pending',
|
||||
});
|
||||
|
||||
expect(result.name).toBe('New Hotel');
|
||||
expect(result.title).toBe('New Hotel');
|
||||
const reservations = useTripStore.getState().reservations;
|
||||
expect(reservations).toHaveLength(2);
|
||||
// addReservation prepends
|
||||
expect(reservations[0].name).toBe('New Hotel');
|
||||
expect(reservations[0].title).toBe('New Hotel');
|
||||
});
|
||||
|
||||
it('FE-RESERV-003: addReservation on failure throws', async () => {
|
||||
@@ -66,14 +66,14 @@ describe('reservationsSlice', () => {
|
||||
);
|
||||
|
||||
await expect(
|
||||
useTripStore.getState().addReservation(1, { name: 'Fail' })
|
||||
useTripStore.getState().addReservation(1, { title: 'Fail' })
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateReservation', () => {
|
||||
it('FE-RESERV-004: updateReservation replaces item in array by id', async () => {
|
||||
const reservation = buildReservation({ id: 10, trip_id: 1, name: 'Old', status: 'pending' });
|
||||
const reservation = buildReservation({ id: 10, trip_id: 1, title: 'Old', status: 'pending' });
|
||||
seedStore(useTripStore, { reservations: [reservation] });
|
||||
|
||||
server.use(
|
||||
@@ -83,10 +83,10 @@ describe('reservationsSlice', () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await useTripStore.getState().updateReservation(1, 10, { name: 'Updated Hotel' });
|
||||
const result = await useTripStore.getState().updateReservation(1, 10, { title: 'Updated Hotel' });
|
||||
|
||||
expect(result.name).toBe('Updated Hotel');
|
||||
expect(useTripStore.getState().reservations[0].name).toBe('Updated Hotel');
|
||||
expect(result.title).toBe('Updated Hotel');
|
||||
expect(useTripStore.getState().reservations[0].title).toBe('Updated Hotel');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user