chore(release): v0.3.6 — 이동 modal 복원 (v0.3.5 의도 정정)

v0.3.5 의 이동 dropdown 단순화가 사용자 의도와 어긋남.
사용자는 dropdown 의 목적지 중복 (modal 도 목적지 묻기) 만 거슬렸지,
사유 입력 + AI 자동 분류 + 수동 status 선택을 한 곳에서 처리하는 modal 은
보존해야 하는 핵심 UX 였음. 단일 "이동" 버튼 → MoveStatusModal path 로 정정.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
th-kim0823
2026-05-11 11:16:14 +09:00
parent 2c6bfebb5b
commit e2058cfdbe
8 changed files with 317 additions and 152 deletions

View File

@@ -128,23 +128,19 @@ describe('NoteCard — ai_status=disabled fallback (v0.2.9 Cut B Task 13)', () =
});
});
describe('NoteCard — 이동 메뉴 (v0.2.9 Cut B Task 6)', () => {
describe('NoteCard — 이동 버튼', () => {
beforeEach(() => {
vi.clearAllMocks();
cleanup();
});
it('이동 클릭 → 현재 status 외 3개 목적지 메뉴 표시', () => {
// baseNote.status = 'active' → 완료/보관/휴지통 만 표시
it('이동 클릭 → MoveStatusModal 열림', () => {
render(<NoteCard note={baseNote} onUpdated={() => {}} mode="inbox" />);
fireEvent.click(screen.getByRole('button', { name: '이동' }));
expect(screen.getByRole('button', { name: '완료로 이동' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '보관으로 이동' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '휴지통으로 이동' })).toBeInTheDocument();
expect(screen.queryByRole('button', { name: '활성으로 이동' })).toBeNull();
expect(screen.getByRole('dialog', { name: '이동' })).toBeInTheDocument();
});
it('메뉴 항목 클릭 → 즉시 setStatus 호출 (modal 없음)', async () => {
it('Modal 내부 "완료" 버튼 → setStatus 호출 + onUpdated + onDeleted + refreshMeta', async () => {
const onUpdated = vi.fn();
const onDeleted = vi.fn();
render(
@@ -156,33 +152,13 @@ describe('NoteCard — 이동 메뉴 (v0.2.9 Cut B Task 6)', () => {
/>
);
fireEvent.click(screen.getByRole('button', { name: '이동' }));
fireEvent.click(screen.getByRole('button', { name: '완료로 이동' }));
fireEvent.click(screen.getByRole('button', { name: '완료' }));
await waitFor(() => {
expect(mockSetStatus).toHaveBeenCalledWith('n1', 'completed', null);
expect(onUpdated).toHaveBeenCalled();
// status 변경 → 현재 view (inbox) 에서 제거되어야 함.
expect(onDeleted).toHaveBeenCalled();
// 헤더 탭 count 동기화.
expect(mockRefreshMeta).toHaveBeenCalled();
});
// modal 미존재 검증.
expect(screen.queryByRole('dialog', { name: '이동' })).toBeNull();
});
it('이동 메뉴 외부 클릭 시 dropdown 닫힘', () => {
render(<NoteCard note={baseNote} onUpdated={() => {}} mode="inbox" />);
fireEvent.click(screen.getByRole('button', { name: '이동' }));
expect(screen.getByRole('button', { name: '완료로 이동' })).toBeInTheDocument();
fireEvent.mouseDown(document.body);
expect(screen.queryByRole('button', { name: '완료로 이동' })).toBeNull();
});
it('이동 메뉴 열린 상태에서 Escape → dropdown 닫힘', () => {
render(<NoteCard note={baseNote} onUpdated={() => {}} mode="inbox" />);
fireEvent.click(screen.getByRole('button', { name: '이동' }));
expect(screen.getByRole('button', { name: '완료로 이동' })).toBeInTheDocument();
fireEvent.keyDown(document, { key: 'Escape' });
expect(screen.queryByRole('button', { name: '완료로 이동' })).toBeNull();
});
});