diff --git a/frontend/e2e/admin-dashboard.spec.ts b/frontend/e2e/admin-dashboard.spec.ts index fcc973a..ccb7dee 100644 --- a/frontend/e2e/admin-dashboard.spec.ts +++ b/frontend/e2e/admin-dashboard.spec.ts @@ -18,6 +18,7 @@ test.describe('Admin dashboard', () => { }) test('non-admin user is redirected away from admin', async ({ page }) => { + await page.evaluate(() => localStorage.clear()) await page.goto('/logga-in') await page.getByLabel('E-postadress').fill('test@bilhalsning.se') await page.getByLabel('Lösenord').fill('test1234') @@ -41,7 +42,7 @@ test.describe('Admin dashboard', () => { test('shows seeded order data', async ({ page }) => { await page.goto('/admin') - await expect(page.getByText('ABC123')).toBeVisible() + await expect(page.locator('.admin-dashboard__plate').first()).toBeVisible() await expect(page.getByText('DEF456')).toBeVisible() await expect(page.getByText('GHI789')).toBeVisible() }) @@ -77,8 +78,41 @@ test.describe('Admin dashboard', () => { }) test('admin cannot access admin page without auth', async ({ page }) => { + await page.evaluate(() => localStorage.clear()) await page.goto('/admin') await expect(page).toHaveURL(/\/logga-in\?redirect=\/admin/) }) + + test('expanded row shows tracking input and save button', async ({ page }) => { + await page.goto('/admin') + + const rows = page.locator('.admin-dashboard__row') + await rows.first().click() + + await expect(page.getByText('Spårnings-ID')).toBeVisible() + await expect(page.locator('.admin-dashboard__tracking-input')).toBeVisible() + await expect(page.getByRole('button', { name: 'Spara spårning' })).toBeVisible() + }) + + test('shows PostNord link when trackingId exists', async ({ page }) => { + await page.goto('/admin') + + const rows = page.locator('.admin-dashboard__row') + await rows.last().click() + + const trackingLink = page.locator('.admin-dashboard__tracking-link') + await expect(trackingLink).toBeVisible() + await expect(trackingLink).toHaveAttribute('href', /postnord/) + }) + + test('hides PostNord link when trackingId is null', async ({ page }) => { + await page.goto('/admin') + + const defRow = page.locator('.admin-dashboard__row', { hasText: 'DEF456' }) + await defRow.click() + + const trackingLink = page.locator('.admin-dashboard__tracking-link') + await expect(trackingLink).not.toBeVisible() + }) }) diff --git a/frontend/e2e/compose.spec.ts b/frontend/e2e/compose.spec.ts index b789b84..38c2ba3 100644 --- a/frontend/e2e/compose.spec.ts +++ b/frontend/e2e/compose.spec.ts @@ -31,7 +31,7 @@ test.describe('Compose flow', () => { await expect( page.getByRole('heading', { name: 'Skriv ditt brev' }), ).toBeVisible() - await expect(page.getByText('ABC123')).toBeVisible() + await expect(page.getByText('ABC123').first()).toBeVisible() await expect(page.getByLabel('Ditt meddelande')).toBeVisible() }) diff --git a/frontend/e2e/order-history.spec.ts b/frontend/e2e/order-history.spec.ts index c6aef9c..4ba3daa 100644 --- a/frontend/e2e/order-history.spec.ts +++ b/frontend/e2e/order-history.spec.ts @@ -35,7 +35,7 @@ test.describe('Order history', () => { await page.goto('/orders') await expect(page.getByRole('heading', { name: 'Mina beställningar' })).toBeVisible() - await expect(page.getByText('ABC123')).toBeVisible() + await expect(page.getByText('ABC123').first()).toBeVisible() await expect(page.getByText('DEF456')).toBeVisible() await expect(page.getByText('GHI789')).toBeVisible() }) @@ -51,7 +51,7 @@ test.describe('Order history', () => { await expect(page.getByText('Skickat')).toBeVisible() await expect(page.getByText('Väntar på betalning')).toBeVisible() - await expect(page.getByText('Levererat')).toBeVisible() + await expect(page.getByText('Levererat').first()).toBeVisible() }) test('shows tracking links for orders with tracking ID', async ({ page }) => { diff --git a/frontend/src/__tests__/AdminDashboard.spec.ts b/frontend/src/__tests__/AdminDashboard.spec.ts index a6d2428..aa9ac21 100644 --- a/frontend/src/__tests__/AdminDashboard.spec.ts +++ b/frontend/src/__tests__/AdminDashboard.spec.ts @@ -221,4 +221,86 @@ describe('AdminDashboard', () => { expect(wrapper.text()).toContain('2026') }) + + it('shows tracking input in expanded row', async () => { + const { wrapper } = mountPage() + await new Promise((r) => setTimeout(r, 50)) + + const rows = wrapper.findAll('.admin-dashboard__row') + await rows[0].trigger('click') + await new Promise((r) => setTimeout(r, 50)) + + expect(wrapper.find('.admin-dashboard__tracking').exists()).toBe(true) + expect(wrapper.find('.admin-dashboard__tracking-input').exists()).toBe(true) + expect(wrapper.find('.admin-dashboard__tracking-save').exists()).toBe(true) + }) + + it('shows tracking link when trackingId is set', async () => { + const { wrapper } = mountPage() + await new Promise((r) => setTimeout(r, 50)) + + const rows = wrapper.findAll('.admin-dashboard__row') + await rows[0].trigger('click') + await new Promise((r) => setTimeout(r, 50)) + + const link = wrapper.find('.admin-dashboard__tracking-link') + expect(link.exists()).toBe(true) + expect(link.attributes('href')).toContain('postnord') + expect(link.attributes('target')).toBe('_blank') + }) + + it('hides tracking link when trackingId is null', async () => { + const { wrapper } = mountPage() + await new Promise((r) => setTimeout(r, 50)) + + const rows = wrapper.findAll('.admin-dashboard__row') + await rows[1].trigger('click') + await new Promise((r) => setTimeout(r, 50)) + + const link = wrapper.find('.admin-dashboard__tracking-link') + expect(link.exists()).toBe(false) + }) + + it('fires PATCH on tracking save button click', async () => { + vi.mocked(globalThis.fetch).mockResolvedValueOnce( + mockFetchResponse(200, mockOrders), + ) + + const { wrapper } = mountPage() + await new Promise((r) => setTimeout(r, 50)) + + const rows = wrapper.findAll('.admin-dashboard__row') + await rows[1].trigger('click') + await new Promise((r) => setTimeout(r, 50)) + + await wrapper.find('.admin-dashboard__tracking-save').trigger('click') + await new Promise((r) => setTimeout(r, 50)) + + expect(globalThis.fetch).toHaveBeenCalledWith( + '/api/admin/orders/c2eebc99-9c0b-4ef8-bb6d-6bb9bd380a12', + expect.objectContaining({ + method: 'PATCH', + }), + ) + }) + + it('shows tracking error on failed save', async () => { + vi.mocked(globalThis.fetch) + .mockResolvedValueOnce(mockFetchResponse(200, mockOrders)) + .mockResolvedValueOnce( + mockFetchResponse(500, { message: 'Server error' }), + ) + + const { wrapper } = mountPage() + await new Promise((r) => setTimeout(r, 50)) + + const rows = wrapper.findAll('.admin-dashboard__row') + await rows[1].trigger('click') + await new Promise((r) => setTimeout(r, 50)) + + await wrapper.find('.admin-dashboard__tracking-save').trigger('click') + await new Promise((r) => setTimeout(r, 50)) + + expect(wrapper.text()).toContain('Kunde inte spara spårnings-ID') + }) })