kin: KIN-078 Канбан доска не отображается в в полную ширину экрана. Проверить был ли вызван хук перезагрузки после выполнения задачи.
This commit is contained in:
parent
c14c0b7832
commit
cc592bfbbc
2 changed files with 153 additions and 2 deletions
|
|
@ -646,3 +646,153 @@ describe('KIN-075: канбан — кнопки управления', () => {
|
|||
expect(wrapper.text()).toContain('Add Task')
|
||||
})
|
||||
})
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// KIN-078: полная ширина канбан-доски (нет max-w ограничений)
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
describe('KIN-078: канбан — flex layout без ограничений ширины', () => {
|
||||
it('Flex-контейнер колонок имеет класс w-full', async () => {
|
||||
const wrapper = await mountOnKanban()
|
||||
|
||||
const flexContainer = wrapper.find('.flex.gap-3.w-full')
|
||||
expect(flexContainer.exists(), 'flex gap-3 w-full контейнер должен существовать').toBe(true)
|
||||
expect(flexContainer.classes()).toContain('w-full')
|
||||
})
|
||||
|
||||
it('Flex-контейнер колонок не содержит inline style min-width: max-content', async () => {
|
||||
const wrapper = await mountOnKanban()
|
||||
|
||||
const flexContainer = wrapper.find('.flex.gap-3.w-full')
|
||||
const style = flexContainer.element.getAttribute('style')
|
||||
expect(style ?? '').not.toContain('min-width')
|
||||
})
|
||||
|
||||
it('Каждая из 5 колонок имеет flex-1 (растягивается), а не фиксированный w-64', async () => {
|
||||
const wrapper = await mountOnKanban()
|
||||
|
||||
// KANBAN_COLUMNS — 5 колонок, все должны иметь flex-1
|
||||
const allFlex1 = wrapper.findAll('div').filter(d => d.classes().includes('flex-1') && d.classes().includes('flex-col'))
|
||||
expect(allFlex1.length, '5 колонок с flex-1 flex-col должны быть').toBe(5)
|
||||
|
||||
for (const col of allFlex1) {
|
||||
expect(col.classes(), 'Колонка не должна иметь фиксированный w-64').not.toContain('w-64')
|
||||
}
|
||||
})
|
||||
|
||||
it('Каждая из 5 колонок имеет min-w-[12rem] (минимальная ширина)', async () => {
|
||||
const wrapper = await mountOnKanban()
|
||||
|
||||
const columns = wrapper.findAll('div').filter(d =>
|
||||
d.classes().includes('flex-1') && d.classes().includes('flex-col')
|
||||
)
|
||||
expect(columns.length).toBe(5)
|
||||
|
||||
for (const col of columns) {
|
||||
expect(col.classes(), 'Колонка должна иметь min-w-[12rem]').toContain('min-w-[12rem]')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// KIN-078: runTask → запуск polling на kanban-вкладке
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
describe('KIN-078: runTask → polling на kanban-вкладке', () => {
|
||||
it('runTask запускает polling если пользователь переключился на kanban пока задача выполнялась', async () => {
|
||||
vi.useFakeTimers()
|
||||
|
||||
// Изначально нет in_progress задач → переключение на kanban не запускает polling
|
||||
const projectNoPending = {
|
||||
...MOCK_PROJECT,
|
||||
tasks: MOCK_PROJECT.tasks.filter(t => t.status !== 'in_progress'),
|
||||
}
|
||||
vi.mocked(api.project).mockResolvedValue(projectNoPending as any)
|
||||
|
||||
// Откладываем api.runTask — имитируем задержку
|
||||
let resolveRun!: () => void
|
||||
vi.mocked(api.runTask).mockReturnValue(new Promise<void>(res => { resolveRun = () => res() }) as any)
|
||||
vi.spyOn(window, 'confirm').mockReturnValue(true)
|
||||
|
||||
const router = makeRouter()
|
||||
await router.push('/project/KIN')
|
||||
const wrapper = mount(ProjectView, {
|
||||
props: { id: 'KIN' },
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
await flushPromises()
|
||||
|
||||
// Кликаем ▶ для KIN-001 (pending) на вкладке Tasks — runTask подвисает на await api.runTask
|
||||
const runBtn = wrapper.find('button[title="Run pipeline"]')
|
||||
expect(runBtn.exists(), '▶ кнопка должна быть на Tasks вкладке').toBe(true)
|
||||
await runBtn.trigger('click')
|
||||
|
||||
// Пока runTask ждёт — переключаемся на kanban (нет in_progress → polling не стартует)
|
||||
const kanbanTab = wrapper.findAll('button').find(b =>
|
||||
b.classes().includes('border-b-2') && b.text().includes('Kanban')
|
||||
)!
|
||||
await kanbanTab.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
// Убеждаемся что polling не запустился (нет in_progress задач)
|
||||
await vi.advanceTimersByTimeAsync(5000)
|
||||
await flushPromises()
|
||||
const callsBefore = vi.mocked(api.project).mock.calls.length
|
||||
|
||||
// Настраиваем следующий load() чтобы вернуть проект с in_progress задачами
|
||||
vi.mocked(api.project).mockResolvedValue(MOCK_PROJECT as any)
|
||||
|
||||
// Завершаем api.runTask → runTask продолжает: load() → checkAndPollKanban()
|
||||
resolveRun()
|
||||
await flushPromises()
|
||||
|
||||
const callsAfterLoad = vi.mocked(api.project).mock.calls.length
|
||||
expect(callsAfterLoad, 'load() должен вызвать api.project').toBeGreaterThan(callsBefore)
|
||||
|
||||
// Продвигаем время на 5с → polling-тик должен сработать
|
||||
await vi.advanceTimersByTimeAsync(5000)
|
||||
await flushPromises()
|
||||
|
||||
expect(
|
||||
vi.mocked(api.project).mock.calls.length,
|
||||
'Polling должен запуститься после runTask когда activeTab === kanban',
|
||||
).toBeGreaterThan(callsAfterLoad)
|
||||
})
|
||||
|
||||
it('runTask не запускает polling если activeTab !== kanban в момент завершения', async () => {
|
||||
vi.useFakeTimers()
|
||||
vi.mocked(api.runTask).mockResolvedValue(undefined as any)
|
||||
vi.spyOn(window, 'confirm').mockReturnValue(true)
|
||||
|
||||
// Нет in_progress задач → ни через watcher, ни через runTask polling не стартует
|
||||
const projectNoPending = {
|
||||
...MOCK_PROJECT,
|
||||
tasks: MOCK_PROJECT.tasks.filter(t => t.status !== 'in_progress'),
|
||||
}
|
||||
vi.mocked(api.project).mockResolvedValue(projectNoPending as any)
|
||||
|
||||
const router = makeRouter()
|
||||
await router.push('/project/KIN')
|
||||
const wrapper = mount(ProjectView, {
|
||||
props: { id: 'KIN' },
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
await flushPromises()
|
||||
|
||||
// Остаёмся на Tasks вкладке (activeTab === 'tasks') и кликаем ▶
|
||||
const runBtn = wrapper.find('button[title="Run pipeline"]')
|
||||
await runBtn.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
const callsAfterRun = vi.mocked(api.project).mock.calls.length
|
||||
|
||||
// Продвигаем время — polling не должен запуститься (мы на tasks, нет in_progress)
|
||||
await vi.advanceTimersByTimeAsync(5000)
|
||||
await flushPromises()
|
||||
|
||||
expect(
|
||||
vi.mocked(api.project).mock.calls.length,
|
||||
'Polling не должен запуститься когда activeTab !== kanban',
|
||||
).toBe(callsAfterRun)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue