feat(ext/popup): trash view — list trashed items with restore/purge
Shows trashed items sorted newest-first with restore buttons. Empty trash button purges all items + orphan blobs. Header shows count and days until oldest auto-purges. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
67
extension/src/popup/components/__tests__/trash.test.ts
Normal file
67
extension/src/popup/components/__tests__/trash.test.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { renderTrash } from '../trash';
|
||||
|
||||
// Mock popup module
|
||||
vi.mock('../../popup', () => ({
|
||||
getState: vi.fn(() => ({
|
||||
vaultSettings: { trash_retention: { kind: 'days', value: 30 } },
|
||||
})),
|
||||
setState: vi.fn(),
|
||||
sendMessage: vi.fn(),
|
||||
navigate: vi.fn(),
|
||||
escapeHtml: (s: string) => s,
|
||||
}));
|
||||
|
||||
import { sendMessage, navigate } from '../../popup';
|
||||
|
||||
describe('trash view', () => {
|
||||
let app: HTMLElement;
|
||||
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = '<div id="app"></div>';
|
||||
app = document.getElementById('app')!;
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders empty state when no trashed items', async () => {
|
||||
(sendMessage as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
ok: true,
|
||||
data: { items: [] },
|
||||
});
|
||||
|
||||
await renderTrash(app);
|
||||
|
||||
expect(app.innerHTML).toContain('Trash is empty');
|
||||
expect(app.querySelector('#empty-trash-btn')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders trashed items with restore buttons', async () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
(sendMessage as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
ok: true,
|
||||
data: {
|
||||
items: [
|
||||
['id1', { id: 'id1', type: 'login', title: 'Test Login', trashed_at: now - 3600, tags: [], favorite: false, modified: now, attachment_summaries: [] }],
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await renderTrash(app);
|
||||
|
||||
expect(app.innerHTML).toContain('Test Login');
|
||||
expect(app.innerHTML).toContain('restore');
|
||||
expect(app.querySelector('#empty-trash-btn')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('back button navigates to list', async () => {
|
||||
(sendMessage as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
ok: true,
|
||||
data: { items: [] },
|
||||
});
|
||||
|
||||
await renderTrash(app);
|
||||
app.querySelector<HTMLButtonElement>('#back-btn')?.click();
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith('list');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user