Merge branch 'KIN-UI-015-frontend_dev'
This commit is contained in:
commit
747625b05d
3 changed files with 12 additions and 71 deletions
|
|
@ -19,8 +19,7 @@ vi.mock('vue-router', () => ({
|
||||||
vi.mock('../api', () => ({
|
vi.mock('../api', () => ({
|
||||||
api: {
|
api: {
|
||||||
notifications: vi.fn(),
|
notifications: vi.fn(),
|
||||||
projects: vi.fn(),
|
listTasks: vi.fn(),
|
||||||
project: vi.fn(),
|
|
||||||
reviseTask: vi.fn(),
|
reviseTask: vi.fn(),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
@ -38,40 +37,6 @@ const localStorageMock = (() => {
|
||||||
})()
|
})()
|
||||||
Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock, configurable: true })
|
Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock, configurable: true })
|
||||||
|
|
||||||
function makeProject(id = 'proj-1', name = 'MyProject', doneCount = 1) {
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
path: '/projects/test',
|
|
||||||
status: 'active',
|
|
||||||
priority: 1,
|
|
||||||
tech_stack: ['python'],
|
|
||||||
execution_mode: null,
|
|
||||||
autocommit_enabled: null,
|
|
||||||
auto_test_enabled: null,
|
|
||||||
worktrees_enabled: null,
|
|
||||||
obsidian_vault_path: null,
|
|
||||||
deploy_command: null,
|
|
||||||
test_command: null,
|
|
||||||
deploy_host: null,
|
|
||||||
deploy_path: null,
|
|
||||||
deploy_runtime: null,
|
|
||||||
deploy_restart_cmd: null,
|
|
||||||
created_at: '2024-01-01',
|
|
||||||
total_tasks: doneCount,
|
|
||||||
done_tasks: doneCount,
|
|
||||||
active_tasks: 0,
|
|
||||||
blocked_tasks: 0,
|
|
||||||
review_tasks: 0,
|
|
||||||
project_type: null,
|
|
||||||
ssh_host: null,
|
|
||||||
ssh_user: null,
|
|
||||||
ssh_key_path: null,
|
|
||||||
ssh_proxy_jump: null,
|
|
||||||
description: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeCompletedTask(id = 'TSK-1', title = 'Test task') {
|
function makeCompletedTask(id = 'TSK-1', title = 'Test task') {
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
|
|
@ -93,21 +58,13 @@ function makeCompletedTask(id = 'TSK-1', title = 'Test task') {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeProjectDetail(
|
|
||||||
project: ReturnType<typeof makeProject>,
|
|
||||||
tasks: ReturnType<typeof makeCompletedTask>[],
|
|
||||||
) {
|
|
||||||
return { ...project, tasks, modules: [], decisions: [] }
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorageMock.clear()
|
localStorageMock.clear()
|
||||||
vi.clearAllMocks()
|
vi.clearAllMocks()
|
||||||
mockPush.mockClear()
|
mockPush.mockClear()
|
||||||
vi.useFakeTimers()
|
vi.useFakeTimers()
|
||||||
vi.mocked(api.notifications).mockResolvedValue([])
|
vi.mocked(api.notifications).mockResolvedValue([])
|
||||||
vi.mocked(api.projects).mockResolvedValue([])
|
vi.mocked(api.listTasks).mockResolvedValue([])
|
||||||
vi.mocked(api.project).mockResolvedValue(makeProjectDetail(makeProject(), []))
|
|
||||||
vi.mocked(api.reviseTask).mockResolvedValue({ status: 'ok', comment: '' })
|
vi.mocked(api.reviseTask).mockResolvedValue({ status: 'ok', comment: '' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -116,13 +73,8 @@ afterEach(() => {
|
||||||
vi.restoreAllMocks()
|
vi.restoreAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
async function mountWithCompleted(
|
async function mountWithCompleted(tasks = [makeCompletedTask()]) {
|
||||||
tasks = [makeCompletedTask()],
|
vi.mocked(api.listTasks).mockResolvedValue(tasks)
|
||||||
projectName = 'MyProject',
|
|
||||||
) {
|
|
||||||
const project = makeProject('proj-1', projectName)
|
|
||||||
vi.mocked(api.projects).mockResolvedValue([project])
|
|
||||||
vi.mocked(api.project).mockResolvedValue(makeProjectDetail(project, tasks))
|
|
||||||
const wrapper = mount(EscalationBanner)
|
const wrapper = mount(EscalationBanner)
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
@ -158,7 +110,7 @@ describe('KIN-125 AC1: завершённые задачи отображают
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Бейдж не отображается когда нет завершённых задач', async () => {
|
it('Бейдж не отображается когда нет завершённых задач', async () => {
|
||||||
vi.mocked(api.projects).mockResolvedValue([makeProject('proj-1', 'P', 0)])
|
vi.mocked(api.listTasks).mockResolvedValue([])
|
||||||
const wrapper = mount(EscalationBanner)
|
const wrapper = mount(EscalationBanner)
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
const badge = wrapper.findAll('button').find(b => b.text().includes('Completed'))
|
const badge = wrapper.findAll('button').find(b => b.text().includes('Completed'))
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,11 @@ export const api = {
|
||||||
deleteAttachment: (taskId: string, id: number) =>
|
deleteAttachment: (taskId: string, id: number) =>
|
||||||
del<void>(`/tasks/${taskId}/attachments/${id}`),
|
del<void>(`/tasks/${taskId}/attachments/${id}`),
|
||||||
attachmentUrl: (id: number) => `${BASE}/attachments/${id}/file`,
|
attachmentUrl: (id: number) => `${BASE}/attachments/${id}/file`,
|
||||||
|
listTasks: (status?: string, limit = 20, sort = 'updated_at') => {
|
||||||
|
const q = new URLSearchParams({ limit: String(limit), sort })
|
||||||
|
if (status) q.set('status', status)
|
||||||
|
return get<Task[]>(`/tasks?${q.toString()}`)
|
||||||
|
},
|
||||||
getPipelineLogs: (pipelineId: string, sinceId: number) =>
|
getPipelineLogs: (pipelineId: string, sinceId: number) =>
|
||||||
get<PipelineLog[]>(`/pipelines/${pipelineId}/logs?since_id=${sinceId}`),
|
get<PipelineLog[]>(`/pipelines/${pipelineId}/logs?since_id=${sinceId}`),
|
||||||
projectLinks: (projectId: string) =>
|
projectLinks: (projectId: string) =>
|
||||||
|
|
|
||||||
|
|
@ -148,24 +148,8 @@ const visibleCompleted = computed(() =>
|
||||||
|
|
||||||
async function loadCompletedTasks() {
|
async function loadCompletedTasks() {
|
||||||
try {
|
try {
|
||||||
const projects = await api.projects()
|
const tasks = await api.listTasks('completed', 20, 'updated_at')
|
||||||
const withCompleted = projects.filter(p => p.done_tasks > 0)
|
completedTasks.value = tasks.map(t => ({ ...t, project_name: t.project_id }))
|
||||||
if (withCompleted.length === 0) {
|
|
||||||
completedTasks.value = []
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const details = await Promise.all(withCompleted.map(p => api.project(p.id)))
|
|
||||||
const results: CompletedTaskItem[] = []
|
|
||||||
for (let i = 0; i < details.length; i++) {
|
|
||||||
const projectName = withCompleted[i].name
|
|
||||||
for (const task of details[i].tasks) {
|
|
||||||
if (task.status === 'completed') {
|
|
||||||
results.push({ ...task, project_name: projectName })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())
|
|
||||||
completedTasks.value = results.slice(0, 20)
|
|
||||||
} catch {
|
} catch {
|
||||||
// silent
|
// silent
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue