diff --git a/web/frontend/src/views/ProjectView.vue b/web/frontend/src/views/ProjectView.vue
index 3613496..5f13d48 100644
--- a/web/frontend/src/views/ProjectView.vue
+++ b/web/frontend/src/views/ProjectView.vue
@@ -1098,7 +1098,6 @@ async function addDecision() {
diff --git a/web/frontend/src/views/__tests__/date-filter.test.ts b/web/frontend/src/views/__tests__/date-filter.test.ts
deleted file mode 100644
index 201d875..0000000
--- a/web/frontend/src/views/__tests__/date-filter.test.ts
+++ /dev/null
@@ -1,225 +0,0 @@
-/**
- * KIN-UI-016: Тесты фильтра дат для завершённых задач
- *
- * Проверяет:
- * 1. Блок фильтра дат виден при статусе 'done' в selectedStatuses
- * 2. Блок фильтра дат скрыт при отсутствии 'done' в selectedStatuses
- * 3. Инпуты date-from и date-to присутствуют в блоке фильтра
- * 4. Кнопка сброса скрыта, если dateFrom и dateTo не заданы
- * 5. Кнопка сброса появляется при заполнении dateFrom
- * 6. Кнопка сброса появляется при заполнении dateTo
- * 7. Кнопка сброса имеет data-testid='date-reset-btn' (не хрупкий текстовый селектор)
- * 8. Клик по кнопке сброса очищает оба поля dateFrom и dateTo
- */
-
-import { describe, it, expect, vi, beforeEach } from 'vitest'
-import { mount, flushPromises } from '@vue/test-utils'
-import { createRouter, createMemoryHistory } from 'vue-router'
-import ProjectView from '../ProjectView.vue'
-
-vi.mock('../../api', async (importOriginal) => {
- const actual = await importOriginal()
- return {
- ...actual,
- api: {
- project: vi.fn(),
- projects: vi.fn(),
- getPhases: vi.fn(),
- environments: vi.fn(),
- projectLinks: vi.fn(),
- patchProject: vi.fn(),
- syncObsidian: vi.fn(),
- },
- }
-})
-
-import { api } from '../../api'
-
-const localStorageMock = (() => {
- let store: Record = {}
- return {
- getItem: (k: string) => store[k] ?? null,
- setItem: (k: string, v: string) => { store[k] = v },
- removeItem: (k: string) => { delete store[k] },
- clear: () => { store = {} },
- }
-})()
-Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock, configurable: true })
-
-const BASE_PROJECT_DETAIL = {
- id: 'proj-1',
- name: 'Test Project',
- path: '/projects/test',
- status: 'active',
- priority: 5,
- tech_stack: ['python'],
- execution_mode: 'review',
- autocommit_enabled: 0,
- auto_test_enabled: 0,
- worktrees_enabled: 0,
- obsidian_vault_path: '',
- deploy_command: '',
- test_command: '',
- deploy_host: '',
- deploy_path: '',
- deploy_runtime: '',
- deploy_restart_cmd: '',
- created_at: '2024-01-01',
- total_tasks: 0,
- done_tasks: 0,
- active_tasks: 0,
- blocked_tasks: 0,
- review_tasks: 0,
- project_type: 'development',
- ssh_host: '',
- ssh_user: '',
- ssh_key_path: '',
- ssh_proxy_jump: '',
- description: null,
- tasks: [],
- modules: [],
- decisions: [],
-}
-
-function makeRouter() {
- return createRouter({
- history: createMemoryHistory(),
- routes: [
- { path: '/project/:id', component: ProjectView, props: true },
- ],
- })
-}
-
-beforeEach(() => {
- localStorageMock.clear()
- vi.clearAllMocks()
- vi.mocked(api.project).mockResolvedValue(BASE_PROJECT_DETAIL as any)
- vi.mocked(api.projects).mockResolvedValue([])
- vi.mocked(api.getPhases).mockResolvedValue([])
- vi.mocked(api.environments).mockResolvedValue([])
- vi.mocked(api.projectLinks).mockResolvedValue([])
- vi.mocked(api.patchProject).mockResolvedValue(BASE_PROJECT_DETAIL as any)
-})
-
-describe('ProjectView — фильтр дат завершённых задач', () => {
- it('блок фильтра дат виден когда выбран статус done', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=done')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- const dateFromInput = wrapper.find('[data-testid="date-from"]')
- expect(dateFromInput.exists()).toBe(true)
- })
-
- it('блок фильтра дат скрыт когда done не выбран', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=pending')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- const dateFromInput = wrapper.find('[data-testid="date-from"]')
- expect(dateFromInput.exists()).toBe(false)
- })
-
- it('инпут date-from присутствует в блоке фильтра при статусе done', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=done')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- expect(wrapper.find('[data-testid="date-from"]').exists()).toBe(true)
- })
-
- it('инпут date-to присутствует в блоке фильтра при статусе done', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=done')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- expect(wrapper.find('[data-testid="date-to"]').exists()).toBe(true)
- })
-
- it('кнопка сброса скрыта когда dateFrom и dateTo не заданы', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=done')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- expect(wrapper.find('[data-testid="date-reset-btn"]').exists()).toBe(false)
- })
-
- it('кнопка сброса появляется после ввода значения в dateFrom', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=done')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- const dateFrom = wrapper.find('[data-testid="date-from"]')
- await dateFrom.setValue('2024-01-01')
- await wrapper.vm.$nextTick()
-
- expect(wrapper.find('[data-testid="date-reset-btn"]').exists()).toBe(true)
- })
-
- it('кнопка сброса имеет data-testid="date-reset-btn" (не хрупкий текстовый селектор)', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=done')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- const dateTo = wrapper.find('[data-testid="date-to"]')
- await dateTo.setValue('2024-12-31')
- await wrapper.vm.$nextTick()
-
- const resetBtn = wrapper.find('[data-testid="date-reset-btn"]')
- expect(resetBtn.exists()).toBe(true)
- expect(resetBtn.attributes('data-testid')).toBe('date-reset-btn')
- })
-
- it('клик по кнопке сброса очищает dateFrom и dateTo', async () => {
- const router = makeRouter()
- await router.push('/project/proj-1?status=done')
- const wrapper = mount(ProjectView, {
- props: { id: 'proj-1' },
- global: { plugins: [router] },
- })
- await flushPromises()
-
- const dateFrom = wrapper.find('[data-testid="date-from"]')
- const dateTo = wrapper.find('[data-testid="date-to"]')
- await dateFrom.setValue('2024-01-01')
- await dateTo.setValue('2024-12-31')
- await wrapper.vm.$nextTick()
-
- const resetBtn = wrapper.find('[data-testid="date-reset-btn"]')
- expect(resetBtn.exists()).toBe(true)
- await resetBtn.trigger('click')
- await wrapper.vm.$nextTick()
-
- expect((dateFrom.element as HTMLInputElement).value).toBe('')
- expect((dateTo.element as HTMLInputElement).value).toBe('')
- expect(wrapper.find('[data-testid="date-reset-btn"]').exists()).toBe(false)
- })
-})