59dac9be56
TDD: spec (3 tests) first, then component. ImportView.vue: upload form + polling + history table + unknown-statuses banner. Uses api/imports (uploadImport/listImports/getImport/getUnknownStatuses). setInterval callback wrapped in named async fn (pollOnce) — no eslint-disable needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { mount, flushPromises } from '@vue/test-utils';
|
|
import { createVuetify } from 'vuetify';
|
|
import * as components from 'vuetify/components';
|
|
import * as directives from 'vuetify/directives';
|
|
|
|
vi.mock('../../resources/js/api/imports', async (importOriginal) => {
|
|
const orig = await importOriginal<typeof import('../../resources/js/api/imports')>();
|
|
return { ...orig };
|
|
});
|
|
|
|
const importsApi = await import('../../resources/js/api/imports');
|
|
const ImportView = (await import('../../resources/js/views/ImportView.vue')).default;
|
|
|
|
const vuetify = createVuetify({ components, directives });
|
|
|
|
function mountView() {
|
|
return mount(ImportView, {
|
|
global: {
|
|
plugins: [vuetify],
|
|
stubs: { UnknownStatusesDialog: true },
|
|
},
|
|
});
|
|
}
|
|
|
|
describe('ImportView', () => {
|
|
beforeEach(() => {
|
|
vi.restoreAllMocks();
|
|
vi.spyOn(importsApi, 'listImports').mockResolvedValue([]);
|
|
vi.spyOn(importsApi, 'getUnknownStatuses').mockResolvedValue([]);
|
|
});
|
|
|
|
it('грузит историю импортов при монтировании', async () => {
|
|
const spy = vi.spyOn(importsApi, 'listImports').mockResolvedValue([
|
|
{
|
|
id: 1,
|
|
filename: 'leads.csv',
|
|
status: 'done',
|
|
rows_total: 5,
|
|
rows_added: 5,
|
|
rows_updated: 0,
|
|
rows_skipped: 0,
|
|
unknown_statuses_count: 0,
|
|
dry_run: false,
|
|
error_message: null,
|
|
started_at: null,
|
|
finished_at: null,
|
|
},
|
|
]);
|
|
const wrapper = mountView();
|
|
await flushPromises();
|
|
|
|
expect(spy).toHaveBeenCalled();
|
|
expect(wrapper.text()).toContain('leads.csv');
|
|
});
|
|
|
|
it('кнопка загрузки заблокирована без выбранного файла', async () => {
|
|
const wrapper = mountView();
|
|
await flushPromises();
|
|
|
|
const uploadBtn = wrapper.find('[data-test="upload-btn"]');
|
|
expect(uploadBtn.attributes('disabled')).toBeDefined();
|
|
});
|
|
|
|
it('показывает баннер о неизвестных статусах', async () => {
|
|
vi.spyOn(importsApi, 'getUnknownStatuses').mockResolvedValue([
|
|
{ id: 1, status_ru: 'Архив', occurrences: 3 },
|
|
]);
|
|
const wrapper = mountView();
|
|
await flushPromises();
|
|
|
|
expect(wrapper.find('[data-test="unknown-banner"]').exists()).toBe(true);
|
|
});
|
|
});
|