feat(notebook): m009 sort_order 컬럼 + reorder 메서드 + IPC notebook:reorder

- m009 마이그레이션: notebooks.sort_order INTEGER 컬럼 추가, 기존 rows created_at 순으로 backfill
- NotebookRepository.list ORDER BY sort_order ASC, name ASC 로 변경
- NotebookRepository.create 신규 노트북 sort_order = max+1 자동 할당
- NotebookRepository.reorder(id, direction) — swap transaction 으로 atomic 순서 변경
- IPC notebook:reorder 핸들러 등록, preload/shared types pass-through
- 테스트 45개 추가 (m009, reorder 케이스 4, list ORDER BY, IPC 핸들러 2)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
th-kim0823
2026-05-15 15:06:44 +09:00
parent fb17704570
commit eca91a1e7c
10 changed files with 142 additions and 8 deletions

View File

@@ -112,4 +112,49 @@ describe('NotebookRepository', () => {
it('findByName: 없으면 null', () => {
expect(repo.findByName('없음')).toBeNull();
});
it('list: sort_order ASC 순서로 반환', () => {
const a = repo.create({ name: 'A' }); // sort_order = 1 (기본=0)
const b = repo.create({ name: 'B' }); // sort_order = 2
const all = repo.list();
expect(all[0]!.name).toBe('기본');
expect(all[1]!.id).toBe(a.id);
expect(all[2]!.id).toBe(b.id);
});
it('reorder: B.up → B/기본/A 순서로 swap', () => {
const a = repo.create({ name: 'A' }); // sort_order=1
const b = repo.create({ name: 'B' }); // sort_order=2
// 초기: 기본(0), A(1), B(2)
const r = repo.reorder(b.id, 'up');
expect(r.ok).toBe(true);
const names = repo.list().map((n) => n.name);
expect(names).toEqual(['기본', 'B', 'A']);
});
it('reorder: 첫 번째 notebook up → ok:false', () => {
const defaultId = repo.list()[0]!.id;
const r = repo.reorder(defaultId, 'up');
expect(r.ok).toBe(false);
});
it('reorder: 마지막 notebook down → ok:false', () => {
const c = repo.create({ name: 'C' }); // sort_order=1
const r = repo.reorder(c.id, 'down');
expect(r.ok).toBe(false);
});
it('reorder: B.down → 기본/A/C/B 순서', () => {
const a = repo.create({ name: 'A' }); // sort_order=1
const b = repo.create({ name: 'B' }); // sort_order=2
const c = repo.create({ name: 'C' }); // sort_order=3
// 초기: 기본(0), A(1), B(2), C(3)
const r = repo.reorder(b.id, 'down');
expect(r.ok).toBe(true);
const names = repo.list().map((n) => n.name);
expect(names).toEqual(['기본', 'A', 'C', 'B']);
// a, c 순서 안 변함 확인
expect(names.indexOf('A')).toBeLessThan(names.indexOf('C'));
void a; void c;
});
});