diff --git a/web/frontend/src/__tests__/task-tree.test.ts b/web/frontend/src/__tests__/task-tree.test.ts index 7adb841..1423a0b 100644 --- a/web/frontend/src/__tests__/task-tree.test.ts +++ b/web/frontend/src/__tests__/task-tree.test.ts @@ -320,13 +320,16 @@ describe('KIN-127: статус revising', () => { expect(wrapper.find('a[href="/task/KIN-001"]').exists()).toBe(true) }) - it('Badge для статуса revising отображается с orange цветом', async () => { + it('Badge для статуса revising присутствует в списке задач', async () => { const tasks = [makeTask('KIN-001', 'revising', null)] const wrapper = await mountTasks(tasks) // Badge с текстом revising должен присутствовать const text = wrapper.text() expect(text).toContain('revising') + // Badge должен иметь orange цвет + const orangeBadge = wrapper.find('.text-orange-400, .bg-orange-400, .bg-orange-500, .border-orange-400, .border-orange-500') + expect(orangeBadge.exists()).toBe(true) }) }) @@ -365,7 +368,7 @@ describe('KIN-127: i18n ключи', () => { // ───────────────────────────────────────────────────────────── describe('KIN-127: защита от циклических ссылок', () => { - it('Проект с циклическими parent_task_id рендерится без зависания', async () => { + it('Проект с циклическими parent_task_id рендерится без зависания и не показывает toggle', async () => { // Специально создаём циклическую ссылку: KIN-001 -> KIN-002 -> KIN-001 const tasks = [ { ...makeTask('KIN-001', 'pending', 'KIN-002') }, @@ -374,7 +377,11 @@ describe('KIN-127: защита от циклических ссылок', () => // Не должен зависнуть — задачи просто отобразятся как корневые const wrapper = await mountTasks(tasks) - // Достаточно что рендер завершился без ошибок + // Рендер завершился без ошибок expect(wrapper.exists()).toBe(true) + // При циклической ссылке ни одна задача не является «корневой» с дочерними — + // toggle кнопок быть не должно (дефолтное состояние: дети не показаны) + const toggleBtns = wrapper.findAll('[data-testid="task-toggle-children"]') + expect(toggleBtns.length).toBe(0) }) }) diff --git a/web/frontend/src/views/ProjectView.vue b/web/frontend/src/views/ProjectView.vue index 790c2bc..448bdc8 100644 --- a/web/frontend/src/views/ProjectView.vue +++ b/web/frontend/src/views/ProjectView.vue @@ -731,7 +731,10 @@ const rootFilteredTasks = computed(() => { const flattenedTasks = computed(() => { const result: Task[] = [] + const visitedInFlatten = new Set() function addWithChildren(task: Task) { + if (visitedInFlatten.has(task.id)) return + visitedInFlatten.add(task.id) result.push(task) if (expandedTasks.value.has(task.id)) { const children = childrenMap.value.get(task.id) || []