diff --git a/src/hooks/useThemeManager.test.ts b/src/hooks/useThemeManager.test.ts index 3c2abbc5..7906335c 100644 --- a/src/hooks/useThemeManager.test.ts +++ b/src/hooks/useThemeManager.test.ts @@ -470,6 +470,38 @@ text-primary: "#e0e0e0" expect(document.documentElement.style.getPropertyValue('--sidebar')).toBe('#2a2a3e') }) + it('notifyThemeSaved updates bullet-size and bullet-color CSS vars', async () => { + const { result } = renderHook(() => + useThemeManager('/vault', entries, allContent) + ) + await waitFor(() => { + expect(result.current.activeThemeId).toBe(THEME_PATH_DEFAULT) + }) + + const updatedContent = `--- +type: Theme +Description: Light theme +background: "#FFFFFF" +foreground: "#37352F" +primary: "#155DFF" +sidebar: "#F7F6F3" +text-primary: "#37352F" +lists-bullet-size: 32px +lists-bullet-color: "#FF0000" +--- + +# Default Theme +` + act(() => { + result.current.notifyThemeSaved(THEME_PATH_DEFAULT, updatedContent) + }) + + await waitFor(() => { + expect(document.documentElement.style.getPropertyValue('--lists-bullet-size')).toBe('32px') + }) + expect(document.documentElement.style.getPropertyValue('--lists-bullet-color')).toBe('#FF0000') + }) + it('notifyThemeSaved is a no-op for non-active theme path', async () => { const { result } = renderHook(() => useThemeManager('/vault', entries, allContent) diff --git a/tests/smoke/theme-live-reload-fix.spec.ts b/tests/smoke/theme-live-reload-fix.spec.ts deleted file mode 100644 index eb8c7b39..00000000 --- a/tests/smoke/theme-live-reload-fix.spec.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { test, expect, type Page } from '@playwright/test' -import { openCommandPalette, executeCommand } from './helpers' - -async function getCssVar(page: Page, name: string): Promise { - return page.evaluate( - (n) => document.documentElement.style.getPropertyValue(n), - name, - ) -} - -async function switchToDefaultTheme(page: Page) { - await openCommandPalette(page) - await executeCommand(page, 'Switch to Default Theme') - await expect(async () => { - expect(await getCssVar(page, '--background')).toBe('#FFFFFF') - }).toPass({ timeout: 5000 }) -} - -async function openThemeNoteInRawMode(page: Page) { - await openCommandPalette(page) - await executeCommand(page, 'Edit Default Theme') - await page.waitForTimeout(500) - - await openCommandPalette(page) - await executeCommand(page, 'Toggle Raw Editor') - await expect(page.locator('.cm-content')).toBeVisible({ timeout: 3000 }) -} - -/** Replace all text in the CodeMirror editor via its EditorView API. */ -async function setCmContent(page: Page, newContent: string) { - await page.evaluate((text) => { - const cmContent = document.querySelector('.cm-content') as HTMLElement | null - if (!cmContent) throw new Error('No .cm-content found') - // Access EditorView via CodeMirror's internal DOM reference - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const view = (cmContent as any).cmTile?.root?.view - if (!view) throw new Error('No EditorView found on .cm-content') - view.dispatch({ - changes: { from: 0, to: view.state.doc.length, insert: text }, - }) - }, newContent) -} - -test.describe('Theme live reload on save', () => { - // FIXME: these tests assume the default theme is light (#FFFFFF background) - // but the mock/test environment now starts with a dark theme (#1a1a2e). - // Skipping until the test fixture is updated. - test.skip() - - test.beforeEach(async ({ page }) => { - // Block the vault API ping so the app falls back to mock content - // instead of reading real files from the filesystem. - await page.route('**/api/vault/ping', (route) => - route.fulfill({ status: 404, body: 'blocked for testing' }), - ) - await page.goto('/') - await page.waitForLoadState('networkidle') - }) - - test.fixme('editing theme frontmatter and saving updates CSS vars immediately', async ({ page }) => { - // 1. Switch to the default theme - await switchToDefaultTheme(page) - expect(await getCssVar(page, '--background')).toBe('#FFFFFF') - expect(await getCssVar(page, '--sidebar')).toBe('#F7F6F3') - - // 2. Open the theme note in raw editor mode - await openThemeNoteInRawMode(page) - - // 3. Replace content via CodeMirror API with changed colors - const updatedContent = [ - '---', - 'type: Theme', - 'title: Default', - 'primary: "#155DFF"', - 'background: "#1a1a2e"', - 'foreground: "#37352F"', - 'sidebar: "#2a2a3e"', - 'border: "#E9E9E7"', - 'muted: "#F0F0EF"', - 'muted-foreground: "#9B9A97"', - 'accent: "#F0F7FF"', - 'accent-foreground: "#0A3B8F"', - 'font-family: "\'Inter\', -apple-system, BlinkMacSystemFont, sans-serif"', - 'font-size-base: 14', - 'line-height-base: 1.6', - '---', - '', - '# Default', - '', - 'Light theme with warm, paper-like tones.', - ].join('\n') - await setCmContent(page, updatedContent) - - // Wait for debounce to flush (RawEditorView has 500ms debounce) - await page.waitForTimeout(700) - - // 4. Save with Ctrl+S - await page.keyboard.press('Control+s') - - // 5. Verify CSS vars updated live - await expect(async () => { - expect(await getCssVar(page, '--background')).toBe('#1a1a2e') - }).toPass({ timeout: 5000 }) - expect(await getCssVar(page, '--sidebar')).toBe('#2a2a3e') - }) - - test.fixme('saving a non-theme note does not affect active theme CSS', async ({ page }) => { - // 1. Switch to the default theme - await switchToDefaultTheme(page) - expect(await getCssVar(page, '--background')).toBe('#FFFFFF') - - // 2. Open a regular note (first in list), switch to raw mode - const noteList = page.locator('[data-testid="note-list-container"]') - await noteList.waitFor({ timeout: 5000 }) - await noteList.locator('.cursor-pointer').first().click() - await page.waitForTimeout(300) - - await openCommandPalette(page) - await executeCommand(page, 'Toggle Raw Editor') - await expect(page.locator('.cm-content')).toBeVisible({ timeout: 3000 }) - - // 3. Type something and save - await page.locator('.cm-content').click() - await page.keyboard.type('test edit') - await page.keyboard.press('Control+s') - await page.waitForTimeout(500) - - // 4. Theme CSS vars unchanged - expect(await getCssVar(page, '--background')).toBe('#FFFFFF') - }) -}) diff --git a/tests/smoke/theme-live-reload-rework.spec.ts b/tests/smoke/theme-live-reload-rework.spec.ts index fa80adde..336424d0 100644 --- a/tests/smoke/theme-live-reload-rework.spec.ts +++ b/tests/smoke/theme-live-reload-rework.spec.ts @@ -59,6 +59,8 @@ test.describe('Theme live reload on raw editor save (rework)', () => { 'primary: "#155DFF"', 'sidebar: "#F7F6F3"', 'text-primary: "#37352F"', + 'lists-bullet-size: 32px', + 'lists-bullet-color: "#FF0000"', '---', '', '# Default', @@ -81,6 +83,10 @@ test.describe('Theme live reload on raw editor save (rework)', () => { // Verify other vars also updated expect(await getCssVar(page, '--sidebar')).toBe('#F7F6F3') expect(await getCssVar(page, '--foreground')).toBe('#37352F') + + // Verify bullet-size and bullet-color (rework regression) + expect(await getCssVar(page, '--lists-bullet-size')).toBe('32px') + expect(await getCssVar(page, '--lists-bullet-color')).toBe('#FF0000') }) test('saving a non-theme note does not affect active theme CSS', async ({ page }) => {