test: add tracking entry vitest and e2e tests, fix pre-existing flaky tests

- AdminDashboard.spec.ts (+6 tests):
  - tracking input and save button visible in expanded row
  - PostNord link visible when trackingId is set
  - PostNord link hidden when trackingId is null
  - save button fires PATCH to correct URL
  - tracking error shown on failed save
- admin-dashboard.spec.ts (+4 tests):
  - tracking input and save button visible after row expand
  - PostNord link with postnord href visible for orders with tracking
  - PostNord link hidden for orders without tracking
  - fix row selector to use .last() for deterministic tracking check
    (compose test creates extra ABC123 order that shifts row order)
- compose.spec.ts: fix strict mode violation — getByText('ABC123')
  resolved to 2 elements (strong + preview paragraph) after admin
  test expanded an ABC123 row; use .first()
- order-history.spec.ts: fix strict mode violations — ABC123 and
  Levererat resolve to 2 elements due to compose test creating
  an extra ABC123 order with status changed to delivered; use
  .first() on affected assertions
This commit is contained in:
Joakim Mörling 2026-05-15 19:59:00 +02:00
parent dcc466439e
commit 0f34d29a2a
4 changed files with 120 additions and 4 deletions

View file

@ -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()
})
})

View file

@ -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()
})

View file

@ -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 }) => {

View file

@ -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')
})
})