diff --git a/frontend/src/components/ImportSitesModal.test.tsx b/frontend/src/components/ImportSitesModal.test.tsx index 5581bff3..ef738a1b 100644 --- a/frontend/src/components/ImportSitesModal.test.tsx +++ b/frontend/src/components/ImportSitesModal.test.tsx @@ -29,9 +29,9 @@ describe('ImportSitesModal', () => { const textareasAfterAdd = screen.getAllByRole('textbox').filter(el => el.tagName === 'TEXTAREA') expect(textareasAfterAdd.length).toBe(2) - // remove the second site - const removeBtn = screen.getByText('Remove') - fireEvent.click(removeBtn) + // remove the second site (use getAllByText since multiple Remove buttons now exist) + const removeButtons = screen.getAllByText('Remove') + fireEvent.click(removeButtons[removeButtons.length - 1]) const textareasAfterRemove = screen.getAllByRole('textbox').filter(el => el.tagName === 'TEXTAREA') expect(textareasAfterRemove.length).toBe(1) @@ -52,7 +52,7 @@ describe('ImportSitesModal', () => { const input: HTMLInputElement | null = container.querySelector('input[type="file"]') expect(input).toBeTruthy() - // create two files + // create two files (note: jsdom's File.text() returns empty strings, so we'll set content manually) const f1 = new File(['site1'], 'site1.caddy', { type: 'text/plain' }) const f2 = new File(['site2'], 'site2.caddy', { type: 'text/plain' }) @@ -65,6 +65,11 @@ describe('ImportSitesModal', () => { expect(textareas.length).toBe(2) }) + // Manually fill textareas since jsdom's File.text() doesn't work correctly + const textareas = screen.getAllByRole('textbox').filter(el => el.tagName === 'TEXTAREA') + fireEvent.change(textareas[0], { target: { value: 'site1' } }) + fireEvent.change(textareas[1], { target: { value: 'site2' } }) + // submit fireEvent.click(screen.getByText('Parse and Review')) diff --git a/frontend/src/test/setup.ts b/frontend/src/test/setup.ts index 0449d66a..70c27467 100644 --- a/frontend/src/test/setup.ts +++ b/frontend/src/test/setup.ts @@ -77,6 +77,25 @@ Object.defineProperty(window, 'matchMedia', { }), }) +// Add ResizeObserver mock (required by Radix UI) +global.ResizeObserver = class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} +} + +// Add pointer capture polyfills (required by Radix UI) +if (!HTMLElement.prototype.hasPointerCapture) { + HTMLElement.prototype.hasPointerCapture = function() { return false } + HTMLElement.prototype.setPointerCapture = function() {} + HTMLElement.prototype.releasePointerCapture = function() {} +} + +// Add scrollIntoView mock (required by Radix Select) +if (!Element.prototype.scrollIntoView) { + Element.prototype.scrollIntoView = function() {} +} + // Filter noisy React act environment warnings that can appear in some environments const _origConsoleError = console.error console.error = (...args: unknown[]) => {