175 lines
5 KiB
TypeScript
175 lines
5 KiB
TypeScript
import { beforeEach, describe, expect, it, mock, spyOn } from 'bun:test'
|
|
|
|
const successMock = mock(() => {})
|
|
const errorMock = mock(() => {})
|
|
|
|
globalThis.useNotificationStore = () => ({
|
|
add: () => 'test-id',
|
|
markRead: () => {},
|
|
}) as any
|
|
|
|
mock.module('~/composables/useNotification', () => ({
|
|
useNotification: () => ({ success: successMock, error: errorMock }),
|
|
default: () => ({ success: successMock, error: errorMock }),
|
|
}))
|
|
|
|
mock.module('~/stores/notification', () => ({
|
|
useNotificationStore: () => ({
|
|
add: () => 'test-id',
|
|
markRead: () => {},
|
|
}),
|
|
}))
|
|
|
|
// eslint-disable-next-line import/first
|
|
import * as utils from '~/utils/index'
|
|
// eslint-disable-next-line import/first
|
|
import { useTaskDefinitions } from '~/composables/useTaskDefinitions'
|
|
// eslint-disable-next-line import/first
|
|
import type { TaskDefinitionDetailed, TaskDefinitionSummary } from '~/types/task_definitions'
|
|
|
|
const summary: TaskDefinitionSummary = {
|
|
id: 1,
|
|
name: 'Test',
|
|
priority: 1,
|
|
updated_at: 123456,
|
|
}
|
|
|
|
const listPayload = (items: TaskDefinitionSummary[]) => ({
|
|
items,
|
|
pagination: {
|
|
page: 1,
|
|
per_page: 50,
|
|
total: items.length,
|
|
total_pages: 1,
|
|
has_next: false,
|
|
has_prev: false,
|
|
},
|
|
})
|
|
|
|
function createMockResponse({ ok, status, jsonData }: { ok: boolean, status: number, jsonData: any }) {
|
|
return {
|
|
ok,
|
|
status,
|
|
headers: new Headers(),
|
|
redirected: false,
|
|
statusText: '',
|
|
type: 'basic',
|
|
url: '',
|
|
body: null,
|
|
bodyUsed: false,
|
|
clone() { return this },
|
|
async json() { return jsonData },
|
|
text: async () => JSON.stringify(jsonData),
|
|
arrayBuffer: async () => new ArrayBuffer(0),
|
|
blob: async () => new Blob(),
|
|
formData: async () => new FormData(),
|
|
} as Response
|
|
}
|
|
|
|
describe('useTaskDefinitions', () => {
|
|
beforeEach(() => {
|
|
successMock.mockClear()
|
|
errorMock.mockClear()
|
|
})
|
|
|
|
it('sorts definitions by priority then name', async () => {
|
|
const items = [
|
|
{ id: 1, name: 'B', priority: 2, updated_at: 1 },
|
|
{ id: 2, name: 'A', priority: 2, updated_at: 2 },
|
|
{ id: 3, name: 'C', priority: 1, updated_at: 3 },
|
|
]
|
|
const requestSpy = spyOn(utils, 'request')
|
|
requestSpy.mockResolvedValueOnce(createMockResponse({
|
|
ok: true,
|
|
status: 200,
|
|
jsonData: listPayload(items),
|
|
}))
|
|
const defs = useTaskDefinitions()
|
|
await defs.loadDefinitions()
|
|
expect(defs.definitions.value.map(d => d.id)).toEqual([3, 2, 1])
|
|
requestSpy.mockRestore()
|
|
})
|
|
|
|
it('handles empty payload', async () => {
|
|
const requestSpy = spyOn(utils, 'request')
|
|
requestSpy.mockResolvedValueOnce(createMockResponse({
|
|
ok: true,
|
|
status: 200,
|
|
jsonData: listPayload([]),
|
|
}))
|
|
const defs = useTaskDefinitions()
|
|
await defs.loadDefinitions()
|
|
expect(defs.definitions.value).toEqual([])
|
|
expect(defs.lastError.value).toBeNull()
|
|
requestSpy.mockRestore()
|
|
})
|
|
|
|
it('throws loadDefinitions error when throwInstead is true', async () => {
|
|
const requestSpy = spyOn(utils, 'request')
|
|
requestSpy.mockResolvedValueOnce(createMockResponse({
|
|
ok: false,
|
|
status: 500,
|
|
jsonData: { error: 'Server error' },
|
|
}))
|
|
const defs = useTaskDefinitions()
|
|
defs.throwInstead.value = true
|
|
await expect(defs.loadDefinitions()).rejects.toThrow('Server error')
|
|
requestSpy.mockRestore()
|
|
})
|
|
|
|
it('returns null on getDefinition error', async () => {
|
|
const requestSpy = spyOn(utils, 'request')
|
|
requestSpy.mockResolvedValueOnce(createMockResponse({
|
|
ok: false,
|
|
status: 404,
|
|
jsonData: { error: 'Not Found' },
|
|
}))
|
|
const defs = useTaskDefinitions()
|
|
defs.throwInstead.value = false
|
|
const result = await defs.getDefinition(123)
|
|
expect(result).toBeNull()
|
|
expect(defs.lastError.value).toBe('Not Found')
|
|
requestSpy.mockRestore()
|
|
})
|
|
|
|
it('creates definition successfully', async () => {
|
|
const payload: TaskDefinitionDetailed = {
|
|
id: 2,
|
|
name: 'New',
|
|
priority: 0,
|
|
updated_at: 999,
|
|
definition: { name: 'New', match: ['https://example.com'], parse: { link: { type: 'css', expression: 'a' } } },
|
|
}
|
|
const requestSpy = spyOn(utils, 'request')
|
|
requestSpy.mockResolvedValueOnce(createMockResponse({
|
|
ok: true,
|
|
status: 200,
|
|
jsonData: payload,
|
|
}))
|
|
const defs = useTaskDefinitions()
|
|
await defs.createDefinition(payload.definition)
|
|
expect(defs.definitions.value.some(item => item.id === payload.id)).toBe(true)
|
|
requestSpy.mockRestore()
|
|
})
|
|
|
|
it('removes definition on deleteDefinition', async () => {
|
|
const requestSpy = spyOn(utils, 'request')
|
|
requestSpy.mockResolvedValueOnce(createMockResponse({
|
|
ok: true,
|
|
status: 200,
|
|
jsonData: listPayload([summary]),
|
|
}))
|
|
const defs = useTaskDefinitions()
|
|
await defs.loadDefinitions()
|
|
|
|
requestSpy.mockResolvedValueOnce(createMockResponse({
|
|
ok: true,
|
|
status: 200,
|
|
jsonData: { status: 'deleted' },
|
|
}))
|
|
const result = await defs.deleteDefinition(summary.id)
|
|
expect(result).toBe(true)
|
|
expect(defs.definitions.value).toEqual([])
|
|
requestSpy.mockRestore()
|
|
})
|
|
})
|