fix: update tests for naver always-on and reservations redesign

- Remove server test for naver addon disabled (addon check removed)
- Update PlacesSidebar tests: "Google List" → "Import List" (both
  providers always shown)
- Update ReservationsPanel tests: status is always a span (no toggle),
  remove click-to-toggle test, update summary test
This commit is contained in:
Maurice
2026-04-16 00:04:14 +02:00
parent 7befb7d555
commit 975846c236
3 changed files with 11 additions and 39 deletions
@@ -473,14 +473,14 @@ describe('Google Maps list import', () => {
it('FE-PLANNER-SIDEBAR-040: "Google List" button opens the URL dialog', async () => { it('FE-PLANNER-SIDEBAR-040: "Google List" button opens the URL dialog', async () => {
const user = userEvent.setup(); const user = userEvent.setup();
render(<PlacesSidebar {...defaultProps} />); render(<PlacesSidebar {...defaultProps} />);
await user.click(screen.getByText(/Google List/i)); await user.click(screen.getByText(/Import List/i));
expect(await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i)).toBeInTheDocument(); expect(await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i)).toBeInTheDocument();
}); });
it('FE-PLANNER-SIDEBAR-041: import button disabled when URL input is empty', async () => { it('FE-PLANNER-SIDEBAR-041: import button disabled when URL input is empty', async () => {
const user = userEvent.setup(); const user = userEvent.setup();
render(<PlacesSidebar {...defaultProps} />); render(<PlacesSidebar {...defaultProps} />);
await user.click(screen.getByText(/Google List/i)); await user.click(screen.getByText(/Import List/i));
await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i); await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i);
const importBtn = screen.getByRole('button', { name: /^Import$/i }); const importBtn = screen.getByRole('button', { name: /^Import$/i });
expect(importBtn).toBeDisabled(); expect(importBtn).toBeDisabled();
@@ -498,7 +498,7 @@ describe('Google Maps list import', () => {
(window as any).__addToast = addToast; (window as any).__addToast = addToast;
const user = userEvent.setup(); const user = userEvent.setup();
render(<PlacesSidebar {...defaultProps} pushUndo={vi.fn()} />); render(<PlacesSidebar {...defaultProps} pushUndo={vi.fn()} />);
await user.click(screen.getByText(/Google List/i)); await user.click(screen.getByText(/Import List/i));
const urlInput = await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i); const urlInput = await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i);
await user.type(urlInput, 'https://maps.app.goo.gl/abc123'); await user.type(urlInput, 'https://maps.app.goo.gl/abc123');
await user.click(screen.getByRole('button', { name: /^Import$/i })); await user.click(screen.getByRole('button', { name: /^Import$/i }));
@@ -527,7 +527,7 @@ describe('Google Maps list import', () => {
(window as any).__addToast = addToast; (window as any).__addToast = addToast;
const user = userEvent.setup(); const user = userEvent.setup();
render(<PlacesSidebar {...defaultProps} pushUndo={vi.fn()} />); render(<PlacesSidebar {...defaultProps} pushUndo={vi.fn()} />);
await user.click(screen.getByText(/Google List/i)); await user.click(screen.getByText(/Import List/i));
const urlInput = await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i); const urlInput = await screen.findByPlaceholderText(/maps\.app\.goo\.gl/i);
await user.type(urlInput, 'https://maps.app.goo.gl/xyz{Enter}'); await user.type(urlInput, 'https://maps.app.goo.gl/xyz{Enter}');
await waitFor(() => { await waitFor(() => {
@@ -91,12 +91,12 @@ describe('ReservationsPanel', () => {
expect(els.length).toBeGreaterThan(0); expect(els.length).toBeGreaterThan(0);
}); });
it('FE-COMP-RES-010: shows summary text with confirmed and pending counts', () => { it('FE-COMP-RES-010: shows reservations title and cards', () => {
const r1 = buildReservation({ title: 'Flight', type: 'flight', status: 'confirmed' }); const r1 = buildReservation({ title: 'Flight', type: 'flight', status: 'confirmed' });
const r2 = buildReservation({ title: 'Hotel', type: 'hotel', status: 'pending' }); const r2 = buildReservation({ title: 'Hotel', type: 'hotel', status: 'pending' });
render(<ReservationsPanel {...defaultProps} reservations={[r1, r2]} />); render(<ReservationsPanel {...defaultProps} reservations={[r1, r2]} />);
// reservations.summary = "{confirmed} confirmed, {pending} pending" expect(screen.getByText('Flight')).toBeInTheDocument();
expect(screen.getByText(/1 confirmed, 1 pending/i)).toBeInTheDocument(); expect(screen.getByText('Hotel')).toBeInTheDocument();
}); });
it('FE-COMP-RES-011: hotel reservation renders', () => { it('FE-COMP-RES-011: hotel reservation renders', () => {
@@ -288,27 +288,14 @@ describe('ReservationsPanel', () => {
// ── Status toggle (canEdit=true) ──────────────────────────────────────────── // ── Status toggle (canEdit=true) ────────────────────────────────────────────
it('FE-PLANNER-RESP-030: status label is a button when canEdit=true', () => { it('FE-PLANNER-RESP-030: status label is always a span (not clickable)', () => {
// Default: permissions empty → canEdit=true
const res = buildReservation({ title: 'My Booking', status: 'pending' }); const res = buildReservation({ title: 'My Booking', status: 'pending' });
render(<ReservationsPanel {...defaultProps} reservations={[res]} />); render(<ReservationsPanel {...defaultProps} reservations={[res]} />);
// Status badge in card header is a button
const pendingEls = screen.getAllByText('Pending'); const pendingEls = screen.getAllByText('Pending');
const statusSpan = pendingEls.find(el => el.tagName === 'SPAN');
expect(statusSpan).toBeDefined();
const statusBtn = pendingEls.find(el => el.tagName === 'BUTTON'); const statusBtn = pendingEls.find(el => el.tagName === 'BUTTON');
expect(statusBtn).toBeDefined(); expect(statusBtn).toBeUndefined();
});
it('FE-PLANNER-RESP-031: clicking status button calls toggleReservationStatus', async () => {
const user = userEvent.setup();
const toggleReservationStatus = vi.fn().mockResolvedValue(undefined);
// Seed the store with a mock toggleReservationStatus function
useTripStore.setState({ toggleReservationStatus } as any);
const res = buildReservation({ id: 42, title: 'Toggle Me', status: 'pending' });
render(<ReservationsPanel {...defaultProps} tripId={1} reservations={[res]} />);
const pendingEls = screen.getAllByText('Pending');
const statusBtn = pendingEls.find(el => el.tagName === 'BUTTON');
await user.click(statusBtn!);
await waitFor(() => expect(toggleReservationStatus).toHaveBeenCalledWith(1, 42));
}); });
// ── Status (canEdit=false) ────────────────────────────────────────────────── // ── Status (canEdit=false) ──────────────────────────────────────────────────
-15
View File
@@ -525,21 +525,6 @@ describe('Naver list import', () => {
vi.unstubAllGlobals(); vi.unstubAllGlobals();
}); });
it('POST /import/naver-list returns 403 when addon is disabled', async () => {
const { user } = createUser(testDb);
const trip = createTrip(testDb, user.id);
testDb.prepare("UPDATE addons SET enabled = 0 WHERE id = 'naver_list_import'").run();
const res = await request(app)
.post(`/api/trips/${trip.id}/places/import/naver-list`)
.set('Cookie', authCookie(user.id))
.send({ url: 'https://naver.me/GYDpx3Wv' });
expect(res.status).toBe(403);
expect(res.body.error).toContain('addon is disabled');
});
it('POST /import/naver-list resolves shortlink, paginates, and creates places', async () => { it('POST /import/naver-list resolves shortlink, paginates, and creates places', async () => {
const { user } = createUser(testDb); const { user } = createUser(testDb);
const trip = createTrip(testDb, user.id); const trip = createTrip(testDb, user.id);