Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/features/banners/pages/banners.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ describe('배너', () => {
await userEvent.click(screen.getByRole('button', { name: '가을 한정 삭제' }));
await userEvent.click(await screen.findByRole('button', { name: '삭제' }));
await vi.waitFor(() => expect(deleted).toEqual({ bannerId: '5' }));
}, 15_000); // 앱 부팅부터 여러 단계를 한 번에 도는 흐름이라 기본 5초가 빠듯하다
});

it('목록을 켜 둔 채 시작 시각이 되면 예약이 노출 중·현재 노출로 바뀐다', async () => {
// 실제 시간도 흐르게 둬 부팅·요청은 그대로 진행되고, 시작 시각만 앞당겨 넘긴다
Expand Down
2 changes: 1 addition & 1 deletion src/features/notifications/pages/history-page.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe('알림 발송 이력', () => {
targetKind: null,
}),
);
}, 15_000); // 앱 부팅부터 여러 단계를 한 번에 도는 흐름이라 기본 5초가 빠듯하다
});

it('제목을 누르면 상세 시트에 본문·대상과 받지 못한 계정 ID를 보이고, 닫으면 주소에서 뺀다', async () => {
boot('/notifications');
Expand Down
2 changes: 1 addition & 1 deletion src/features/notifications/pages/send-page.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,5 +191,5 @@ describe('알림 보내기', () => {
);
expect(screen.getByLabelText('제목')).toHaveValue('');
expect(screen.queryByRole('alertdialog')).toBeNull();
}, 15_000); // 앱 부팅부터 여러 단계를 한 번에 도는 흐름이라 기본 5초가 빠듯하다
});
});
12 changes: 12 additions & 0 deletions src/test/infra/sonner-style.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { toast } from 'sonner';

/** 테스트 설정(setup.ts)이 sonner의 주입 스타일시트를 걷어내는지 고정한다 — 남으면 조작 직후 역할 조회가 약 3배 느려진다 */
describe('테스트 환경의 sonner 스타일시트', () => {
it('sonner를 불러와도 테스트 시작 시점의 문서에는 토스트 스타일시트가 없다', () => {
expect(typeof toast).toBe('function');
const injected = [...document.querySelectorAll('style')].filter((el) =>
el.textContent?.includes('data-sonner-toaster'),
);
expect(injected).toHaveLength(0);
});
});
13 changes: 12 additions & 1 deletion src/test/setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom/vitest';
import { cleanup, configure } from '@testing-library/react';
import { afterAll, afterEach, beforeAll } from 'vitest';
import { afterAll, afterEach, beforeAll, beforeEach } from 'vitest';

import { installZodKorean } from '@/shared/lib/zod-locale';

Expand Down Expand Up @@ -32,7 +32,18 @@ proto.setPointerCapture ??= () => undefined;
proto.releasePointerCapture ??= () => undefined;
proto.scrollIntoView ??= () => undefined;

/** sonner가 import될 때 문서에 넣는 토스트 스타일시트를 찾는 표식 */
const SONNER_STYLE_MARKER = 'data-sonner-toaster';

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
// sonner는 import 시점에 97규칙짜리 <style>을 넣는다. jsdom은 DOM이 바뀔 때마다 스타일 캐시를 버리고
// getComputedStyle에서 문서의 모든 규칙을 다시 대조하는데, 역할·이름 조회가 조회 1회에 이를 100번 넘게 부른다.
// 조작 직후 조회가 66ms → 22ms, 전체 스위트(커버리지) 합계 135초 → 99초. jsdom에서 토스트 CSS는 쓸 데가 없다
beforeEach(() => {
document.querySelectorAll('style').forEach((el) => {
if (el.textContent?.includes(SONNER_STYLE_MARKER)) el.remove();
});
});
afterEach(() => {
server.resetHandlers();
cleanup();
Expand Down
Loading