feat(trash): NoteRepository.permanentDelete/emptyTrash/listTrashed (#4 v0.2.3)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -280,3 +280,86 @@ describe('NoteRepository.restore', () => {
|
||||
expect(repo.findById(id)!.deletedAt).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('NoteRepository.permanentDelete', () => {
|
||||
let db: Database.Database;
|
||||
let repo: NoteRepository;
|
||||
beforeEach(() => {
|
||||
db = new Database(':memory:');
|
||||
runMigrations(db);
|
||||
repo = new NoteRepository(db);
|
||||
});
|
||||
|
||||
it('removes notes row + cascades note_tags / pending_jobs', () => {
|
||||
const { id } = repo.create({ rawText: 'x' });
|
||||
repo.updateAiResult(id, { title: 'T', summary: 'a\nb\nc', tags: ['tag-a'], provider: 'p', dueDate: null });
|
||||
expect(db.prepare('SELECT COUNT(*) AS c FROM note_tags WHERE note_id=?').get(id)).toMatchObject({ c: 1 });
|
||||
repo.permanentDelete(id);
|
||||
expect(repo.findById(id)).toBeNull();
|
||||
expect(db.prepare('SELECT COUNT(*) AS c FROM note_tags WHERE note_id=?').get(id)).toMatchObject({ c: 0 });
|
||||
expect(db.prepare('SELECT COUNT(*) AS c FROM pending_jobs WHERE note_id=?').get(id)).toMatchObject({ c: 0 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('NoteRepository.emptyTrash', () => {
|
||||
let db: Database.Database;
|
||||
let repo: NoteRepository;
|
||||
beforeEach(() => {
|
||||
db = new Database(':memory:');
|
||||
runMigrations(db);
|
||||
repo = new NoteRepository(db);
|
||||
});
|
||||
|
||||
it('hard-deletes all trashed notes and returns their ids', () => {
|
||||
const a = repo.create({ rawText: 'a' }).id;
|
||||
const b = repo.create({ rawText: 'b' }).id;
|
||||
const c = repo.create({ rawText: 'c' }).id;
|
||||
repo.trash(a, '2026-05-01T00:00:00.000Z');
|
||||
repo.trash(c, '2026-05-01T01:00:00.000Z');
|
||||
const r = repo.emptyTrash();
|
||||
expect(r.noteIds.sort()).toEqual([a, c].sort());
|
||||
expect(repo.findById(a)).toBeNull();
|
||||
expect(repo.findById(b)).not.toBeNull();
|
||||
expect(repo.findById(c)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns empty array when trash is empty', () => {
|
||||
expect(repo.emptyTrash()).toEqual({ noteIds: [] });
|
||||
});
|
||||
});
|
||||
|
||||
describe('NoteRepository.listTrashed', () => {
|
||||
let db: Database.Database;
|
||||
let repo: NoteRepository;
|
||||
beforeEach(() => {
|
||||
db = new Database(':memory:');
|
||||
runMigrations(db);
|
||||
repo = new NoteRepository(db);
|
||||
});
|
||||
|
||||
it('returns trashed notes ordered by deleted_at DESC', () => {
|
||||
const a = repo.create({ rawText: 'a' }).id;
|
||||
const b = repo.create({ rawText: 'b' }).id;
|
||||
const c = repo.create({ rawText: 'c' }).id;
|
||||
repo.trash(a, '2026-05-01T00:00:00.000Z');
|
||||
repo.trash(c, '2026-05-01T02:00:00.000Z');
|
||||
repo.trash(b, '2026-05-01T01:00:00.000Z');
|
||||
const r = repo.listTrashed({ limit: 50 });
|
||||
expect(r.map((n) => n.id)).toEqual([c, b, a]);
|
||||
});
|
||||
|
||||
it('excludes active notes', () => {
|
||||
repo.create({ rawText: 'active' });
|
||||
const r = repo.listTrashed({ limit: 50 });
|
||||
expect(r).toEqual([]);
|
||||
});
|
||||
|
||||
it('respects limit', () => {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const id = repo.create({ rawText: `n${i}` }).id;
|
||||
repo.trash(id, `2026-05-01T0${i}:00:00.000Z`);
|
||||
}
|
||||
const r = repo.listTrashed({ limit: 3 });
|
||||
expect(r).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user