Keep/keep-notes/tests/search-quality.spec.ts
sepehr 640fcb26f7 fix: improve note interactions and markdown LaTeX support
## Bug Fixes

### Note Card Actions
- Fix broken size change functionality (missing state declaration)
- Implement React 19 useOptimistic for instant UI feedback
- Add startTransition for non-blocking updates
- Ensure smooth animations without page refresh
- All note actions now work: pin, archive, color, size, checklist

### Markdown LaTeX Rendering
- Add remark-math and rehype-katex plugins
- Support inline equations with dollar sign syntax
- Support block equations with double dollar sign syntax
- Import KaTeX CSS for proper styling
- Equations now render correctly instead of showing raw LaTeX

## Technical Details

- Replace undefined currentNote references with optimistic state
- Add optimistic updates before server actions for instant feedback
- Use router.refresh() in transitions for smart cache invalidation
- Install remark-math, rehype-katex, and katex packages

## Testing

- Build passes successfully with no TypeScript errors
- Dev server hot-reloads changes correctly
2026-01-09 22:13:49 +01:00

64 lines
2.6 KiB
TypeScript

import { test, expect } from '@playwright/test';
test.describe('Search Quality Tests', () => {
test.beforeEach(async ({ page }) => {
// 1. Go to Home
await page.goto('/');
// Handle Login if redirected (Mock behavior or real login)
if (page.url().includes('login')) {
// Assuming a simple dev login or we need to bypass.
// For this environment, let's try to just continue or fail explicitly if stuck.
console.log('Redirected to login. Please ensure you are logged in for tests.');
}
});
test('should find notes by semantic concept', async ({ page }) => {
// Clean up existing notes to avoid noise? (Optional, better to just create unique ones)
const timestamp = Date.now();
const techTitle = `React Tech ${timestamp}`;
const foodTitle = `Italian Food ${timestamp}`;
// 2. Create Tech Note
await page.getByPlaceholder('Take a note...').click();
await page.getByPlaceholder('Title').fill(techTitle);
await page.getByPlaceholder('Take a note...').fill('Hooks, useEffect, State management, Components logic.');
await page.getByRole('button', { name: 'Close' }).click();
await expect(page.getByText(techTitle)).toBeVisible();
// 3. Create Food Note
await page.getByPlaceholder('Take a note...').click();
await page.getByPlaceholder('Title').fill(foodTitle);
await page.getByPlaceholder('Take a note...').fill('Tomato sauce, Basil, Parmesan cheese, boiling water.');
await page.getByRole('button', { name: 'Close' }).click();
await expect(page.getByText(foodTitle)).toBeVisible();
// Wait a bit for potential async indexing (even if server action is awaited, good practice)
await page.waitForTimeout(2000);
// 4. Search for "Coding" (Semantic match for React)
const searchInput = page.getByPlaceholder('Search');
await searchInput.fill('Coding');
await searchInput.press('Enter');
// Allow time for search results
await page.waitForTimeout(1000);
// Assertions
// Tech note should be visible
await expect(page.getByText(techTitle)).toBeVisible();
// Food note should NOT be visible (or at least ranked lower/hidden if filtering is strict)
await expect(page.getByText(foodTitle)).toBeHidden();
// 5. Search for "Cooking" (Semantic match for Food)
await searchInput.fill('');
await searchInput.fill('Cooking dinner');
await searchInput.press('Enter');
await page.waitForTimeout(1000);
await expect(page.getByText(foodTitle)).toBeVisible();
await expect(page.getByText(techTitle)).toBeHidden();
});
});