Adds backend endpoints and frontend edit page so pending orders can be updated or soft-cancelled without admin intervention. Co-authored-by: Cursor <cursoragent@cursor.com>
149 lines
4.2 KiB
TypeScript
149 lines
4.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import { mount } from '@vue/test-utils'
|
|
import { createPinia, setActivePinia } from 'pinia'
|
|
import { createRouter, createMemoryHistory } from 'vue-router'
|
|
import EditOrderPage from '@/pages/EditOrderPage.vue'
|
|
import PaymentRedirect from '@/pages/PaymentRedirect.vue'
|
|
|
|
vi.mock('@/api/orders', () => ({
|
|
fetchOrder: vi.fn(),
|
|
updateOrder: vi.fn(),
|
|
}))
|
|
|
|
import { fetchOrder, updateOrder } from '@/api/orders'
|
|
|
|
const mockFetchOrder = vi.mocked(fetchOrder)
|
|
const mockUpdateOrder = vi.mocked(updateOrder)
|
|
|
|
const pendingOrder = {
|
|
id: 'c2eebc99-9c0b-4ef8-bb6d-6bb9bd380a12',
|
|
plate: 'DEF456',
|
|
letterText: 'Vill köpa din bil.',
|
|
status: 'pending_payment',
|
|
trackingId: null,
|
|
amountPaid: null,
|
|
createdAt: '2026-05-14T13:00:00Z',
|
|
}
|
|
|
|
function createTestRouter() {
|
|
return createRouter({
|
|
history: createMemoryHistory(),
|
|
routes: [
|
|
{
|
|
path: '/orders',
|
|
name: 'orders',
|
|
component: { template: '<div>Orders</div>' },
|
|
},
|
|
{
|
|
path: '/bestallning/:orderId/redigera',
|
|
name: 'edit-order',
|
|
component: EditOrderPage,
|
|
},
|
|
{
|
|
path: '/betalning/:orderId',
|
|
name: 'payment',
|
|
component: PaymentRedirect,
|
|
},
|
|
],
|
|
})
|
|
}
|
|
|
|
async function mountPage(orderId = pendingOrder.id) {
|
|
const pinia = createPinia()
|
|
setActivePinia(pinia)
|
|
|
|
const router = createTestRouter()
|
|
await router.push({ name: 'edit-order', params: { orderId } })
|
|
await router.isReady()
|
|
|
|
const wrapper = mount(EditOrderPage, {
|
|
global: {
|
|
plugins: [router, pinia],
|
|
},
|
|
})
|
|
|
|
return { wrapper, router }
|
|
}
|
|
|
|
describe('EditOrderPage', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
mockFetchOrder.mockResolvedValue(pendingOrder)
|
|
mockUpdateOrder.mockResolvedValue(pendingOrder)
|
|
})
|
|
|
|
it('shows loading state while fetching', async () => {
|
|
mockFetchOrder.mockImplementation(() => new Promise(() => {}))
|
|
const { wrapper } = await mountPage()
|
|
expect(wrapper.text()).toContain('Laddar beställning...')
|
|
})
|
|
|
|
it('loads order and pre-fills textarea', async () => {
|
|
const { wrapper } = await mountPage()
|
|
await vi.waitFor(() => {
|
|
expect(mockFetchOrder).toHaveBeenCalledWith(pendingOrder.id)
|
|
})
|
|
|
|
const textarea = wrapper.find('textarea')
|
|
expect(textarea.element.value).toBe('Vill köpa din bil.')
|
|
expect(wrapper.text()).toContain('DEF456')
|
|
expect(wrapper.text()).toContain('Redigera brev')
|
|
})
|
|
|
|
it('shows error when order is not pending_payment', async () => {
|
|
mockFetchOrder.mockResolvedValue({
|
|
...pendingOrder,
|
|
status: 'sent',
|
|
})
|
|
|
|
const { wrapper } = await mountPage()
|
|
await vi.waitFor(() => {
|
|
expect(wrapper.text()).toContain(
|
|
'Den här beställningen kan inte redigeras',
|
|
)
|
|
})
|
|
|
|
expect(wrapper.find('textarea').exists()).toBe(false)
|
|
expect(wrapper.text()).toContain('Tillbaka till beställningar')
|
|
})
|
|
|
|
it('submit calls updateOrder and navigates to payment', async () => {
|
|
const { wrapper, router } = await mountPage()
|
|
await vi.waitFor(() => {
|
|
expect(wrapper.find('textarea').exists()).toBe(true)
|
|
})
|
|
|
|
const textarea = wrapper.find('textarea')
|
|
await textarea.setValue('Uppdaterat meddelande')
|
|
const button = wrapper.find('button[type="submit"]')
|
|
await button.trigger('submit')
|
|
|
|
await vi.waitFor(() => {
|
|
expect(mockUpdateOrder).toHaveBeenCalledWith(
|
|
pendingOrder.id,
|
|
'Uppdaterat meddelande',
|
|
)
|
|
expect(router.currentRoute.value.name).toBe('payment')
|
|
expect(router.currentRoute.value.params.orderId).toBe(pendingOrder.id)
|
|
expect(router.currentRoute.value.query.plate).toBe('DEF456')
|
|
})
|
|
})
|
|
|
|
it('shows error message on update failure', async () => {
|
|
mockUpdateOrder.mockRejectedValue(new Error('Network error'))
|
|
|
|
const { wrapper } = await mountPage()
|
|
await vi.waitFor(() => {
|
|
expect(wrapper.find('textarea').exists()).toBe(true)
|
|
})
|
|
|
|
const textarea = wrapper.find('textarea')
|
|
await textarea.setValue('Uppdaterat meddelande')
|
|
const button = wrapper.find('button[type="submit"]')
|
|
await button.trigger('submit')
|
|
|
|
await vi.waitFor(() => {
|
|
expect(wrapper.text()).toContain('Kunde inte spara ändringarna')
|
|
})
|
|
})
|
|
})
|