diff --git a/src/hooks/useNoteActions.test.ts b/src/hooks/useNoteActions.test.ts index 203d6851..c7acc6fa 100644 --- a/src/hooks/useNoteActions.test.ts +++ b/src/hooks/useNoteActions.test.ts @@ -28,6 +28,7 @@ vi.mock('../mock-tauri', () => ({ isTauri: vi.fn(() => false), addMockEntry: vi.fn(), updateMockContent: vi.fn(), + trackMockChange: vi.fn(), mockInvoke: vi.fn().mockResolvedValue(''), })) vi.mock('./mockFrontmatterHelpers', () => ({ diff --git a/src/hooks/useNoteActions.ts b/src/hooks/useNoteActions.ts index 6ba5522b..0b580762 100644 --- a/src/hooks/useNoteActions.ts +++ b/src/hooks/useNoteActions.ts @@ -1,6 +1,6 @@ import { useCallback, useEffect, useRef } from 'react' import { invoke } from '@tauri-apps/api/core' -import { isTauri, mockInvoke, addMockEntry, updateMockContent } from '../mock-tauri' +import { isTauri, mockInvoke, addMockEntry, updateMockContent, trackMockChange } from '../mock-tauri' import type { VaultEntry } from '../types' import type { FrontmatterValue } from '../components/Inspector' import { useTabManagement } from './useTabManagement' @@ -111,12 +111,14 @@ async function invokeFrontmatter(command: string, args: Record) function applyMockFrontmatterUpdate(path: string, key: string, value: FrontmatterValue): string { const content = updateMockFrontmatter(path, key, value) updateMockContent(path, content) + trackMockChange(path) return content } function applyMockFrontmatterDelete(path: string, key: string): string { const content = deleteMockFrontmatterProperty(path, key) updateMockContent(path, content) + trackMockChange(path) return content } diff --git a/src/mock-tauri/index.ts b/src/mock-tauri/index.ts index 6458902a..c0d4aa3e 100644 --- a/src/mock-tauri/index.ts +++ b/src/mock-tauri/index.ts @@ -5,10 +5,10 @@ */ import { MOCK_CONTENT } from './mock-content' -import { mockHandlers, addMockEntry, updateMockContent } from './mock-handlers' +import { mockHandlers, addMockEntry, updateMockContent, trackMockChange } from './mock-handlers' import { tryVaultApi } from './vault-api' -export { addMockEntry, updateMockContent } +export { addMockEntry, updateMockContent, trackMockChange } export function isTauri(): boolean { return typeof window !== 'undefined' && ('__TAURI__' in window || '__TAURI_INTERNALS__' in window) diff --git a/src/mock-tauri/mock-handlers.ts b/src/mock-tauri/mock-handlers.ts index e902cd59..0334b142 100644 --- a/src/mock-tauri/mock-handlers.ts +++ b/src/mock-tauri/mock-handlers.ts @@ -347,3 +347,7 @@ export function updateMockContent(path: string, content: string): void { MOCK_CONTENT[path] = content syncWindowContent() } + +export function trackMockChange(path: string): void { + mockSavedSinceCommit.add(path) +} diff --git a/tests/smoke/trashed-archived-not-saved.spec.ts b/tests/smoke/trashed-archived-not-saved.spec.ts new file mode 100644 index 00000000..3931bb50 --- /dev/null +++ b/tests/smoke/trashed-archived-not-saved.spec.ts @@ -0,0 +1,39 @@ +import { test, expect } from '@playwright/test' +import { openCommandPalette, executeCommand } from './helpers' + +test.describe('Trash/archive notes appear in Changes', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + }) + + test('trashing a note increments the Changes badge', async ({ page }) => { + const sidebar = page.locator('.app__sidebar') + + // Wait for Changes nav item (mock starts with 3 modified files) + const changesRow = sidebar.locator('div', { hasText: /^Changes/ }).first() + await changesRow.waitFor({ timeout: 5000 }) + + // Read the initial badge count from the Changes row + const badge = changesRow.locator('span').last() + const initialCount = Number(await badge.textContent()) + expect(initialCount).toBeGreaterThan(0) + + // Click the first note in the list to select it + const noteListContainer = page.locator('[data-testid="note-list-container"]') + await noteListContainer.waitFor({ timeout: 5000 }) + // Click on the first visible note item (border-b items inside the list) + const firstNote = noteListContainer.locator('.cursor-pointer').first() + await firstNote.click() + + // Trash the active note via command palette + await openCommandPalette(page) + await executeCommand(page, 'Trash Note') + + // Wait for the badge count to increase + await expect(async () => { + const text = await badge.textContent() + expect(Number(text)).toBeGreaterThan(initialCount) + }).toPass({ timeout: 5000 }) + }) +})