WIP: Améliorations UX et corrections de bugs avant création des épiques
This commit is contained in:
176
keep-notes/tests/bug-move-direct.spec.ts
Normal file
176
keep-notes/tests/bug-move-direct.spec.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Bug: Move note to notebook - DIRECT TEST', () => {
|
||||
test('BUG: Note should disappear from main page after moving to notebook', async ({ page }) => {
|
||||
const timestamp = Date.now()
|
||||
|
||||
// Step 1: Go to homepage
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Get initial note count
|
||||
const notesBefore = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Initial notes count:', notesBefore)
|
||||
|
||||
// Step 2: Create a test note
|
||||
const testNoteTitle = `TEST-BUG-${timestamp}`
|
||||
const testNoteContent = `Test content ${timestamp}`
|
||||
|
||||
console.log('[TEST] Creating note:', testNoteTitle)
|
||||
|
||||
await page.click('input[placeholder="Take a note..."]')
|
||||
await page.fill('input[placeholder="Title"]', testNoteTitle)
|
||||
await page.fill('textarea[placeholder="Take a note..."]', testNoteContent)
|
||||
await page.click('button:has-text("Add")')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
const notesAfterCreation = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes after creation:', notesAfterCreation)
|
||||
expect(notesAfterCreation).toBe(notesBefore + 1)
|
||||
|
||||
// Step 3: Create a test notebook
|
||||
console.log('[TEST] Creating notebook')
|
||||
|
||||
// Try to find and click "Create Notebook" button
|
||||
const createNotebookButtons = page.locator('button')
|
||||
const createButtonsCount = await createNotebookButtons.count()
|
||||
console.log('[TEST] Total buttons found:', createButtonsCount)
|
||||
|
||||
// List all button texts for debugging
|
||||
for (let i = 0; i < Math.min(createButtonsCount, 10); i++) {
|
||||
const btn = createNotebookButtons.nth(i)
|
||||
const btnText = await btn.textContent()
|
||||
console.log(`[TEST] Button ${i}: "${btnText?.trim()}"`)
|
||||
}
|
||||
|
||||
// Look for a "+" button or "Créer" button
|
||||
let createBtn = page.locator('button').filter({ hasText: '+' }).first()
|
||||
if (await createBtn.count() === 0) {
|
||||
createBtn = page.locator('button').filter({ hasText: 'Créer' }).first()
|
||||
}
|
||||
|
||||
if (await createBtn.count() > 0) {
|
||||
await createBtn.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Try to fill notebook name
|
||||
const testNotebookName = `TEST-NOTEBOOK-${timestamp}`
|
||||
|
||||
// Look for any input field
|
||||
const inputs = page.locator('input')
|
||||
const inputCount = await inputs.count()
|
||||
console.log('[TEST] Input fields found:', inputCount)
|
||||
|
||||
// Fill first input with notebook name
|
||||
if (inputCount > 0) {
|
||||
const firstInput = inputs.first()
|
||||
await firstInput.fill(testNotebookName)
|
||||
|
||||
// Submit the form
|
||||
await page.keyboard.press('Enter')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
console.log('[TEST] Notebook created (or attempted)')
|
||||
}
|
||||
} else {
|
||||
console.log('[TEST] No create button found!')
|
||||
}
|
||||
|
||||
// Take screenshot to see current state
|
||||
await page.screenshot({ path: `playwright-report/after-notebook-creation-${timestamp}.png` })
|
||||
console.log('[TEST] Screenshot saved')
|
||||
|
||||
// Step 4: Try to move the note to the notebook using UI
|
||||
console.log('[TEST] Attempting to move note...')
|
||||
|
||||
// Find the note we just created
|
||||
const ourNote = page.locator('[data-draggable="true"]').filter({ hasText: testNoteTitle })
|
||||
const ourNoteCount = await ourNote.count()
|
||||
console.log('[TEST] Our note found:', ourNoteCount)
|
||||
|
||||
if (ourNoteCount > 0) {
|
||||
console.log('[TEST] Found our note, trying to move it')
|
||||
|
||||
// Try to find any button/element in the note card
|
||||
const noteElement = await ourNote.innerHTML()
|
||||
console.log('[TEST] Note HTML:', noteElement.substring(0, 500))
|
||||
|
||||
// Look for any clickable elements in the note
|
||||
const allButtonsInNote = await ourNote.locator('button').all()
|
||||
console.log('[TEST] Buttons in note:', allButtonsInNote.length)
|
||||
|
||||
for (let i = 0; i < allButtonsInNote.length; i++) {
|
||||
const btn = allButtonsInNote[i]
|
||||
const btnText = await btn.textContent()
|
||||
const btnAriaLabel = await btn.getAttribute('aria-label')
|
||||
console.log(`[TEST] Note button ${i}: text="${btnText}" aria-label="${btnAriaLabel}"`)
|
||||
}
|
||||
|
||||
// Take screenshot before move attempt
|
||||
await page.screenshot({ path: `playwright-report/before-move-${timestamp}.png` })
|
||||
|
||||
// Try to click any button that might be related to notebooks
|
||||
if (allButtonsInNote.length > 0) {
|
||||
// Try clicking the first few buttons
|
||||
for (let i = 0; i < Math.min(allButtonsInNote.length, 3); i++) {
|
||||
const btn = allButtonsInNote[i]
|
||||
const btnText = await btn.textContent()
|
||||
|
||||
console.log(`[TEST] Clicking button ${i}: "${btnText}"`)
|
||||
await btn.click()
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
// Take screenshot after each click
|
||||
await page.screenshot({ path: `playwright-report/after-click-${i}-${timestamp}.png` })
|
||||
|
||||
// Check if a menu opened
|
||||
const menuItems = page.locator('[role="menuitem"], [role="option"]')
|
||||
const menuItemCount = await menuItems.count()
|
||||
console.log(`[TEST] Menu items after click ${i}:`, menuItemCount)
|
||||
|
||||
if (menuItemCount > 0) {
|
||||
// List menu items
|
||||
for (let j = 0; j < Math.min(menuItemCount, 5); j++) {
|
||||
const item = menuItems.nth(j)
|
||||
const itemText = await item.textContent()
|
||||
console.log(`[TEST] Menu item ${j}: "${itemText}"`)
|
||||
}
|
||||
|
||||
// Try to click the first menu item (likely our notebook)
|
||||
const firstMenuItem = menuItems.first()
|
||||
await firstMenuItem.click()
|
||||
await page.waitForTimeout(2000)
|
||||
break
|
||||
}
|
||||
|
||||
// Close menu if any (press Escape)
|
||||
await page.keyboard.press('Escape')
|
||||
await page.waitForTimeout(500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CRITICAL: Check if note is still visible WITHOUT refresh
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
const ourNoteAfterMove = await page.locator('[data-draggable="true"]').filter({ hasText: testNoteTitle }).count()
|
||||
const allNotesAfterMove = await page.locator('[data-draggable="true"]').count()
|
||||
|
||||
console.log('[TEST] ===== RESULTS =====')
|
||||
console.log('[TEST] Our note still visible in main page:', ourNoteAfterMove)
|
||||
console.log('[TEST] Total notes in main page:', allNotesAfterMove)
|
||||
|
||||
// Take final screenshot
|
||||
await page.screenshot({ path: `playwright-report/final-state-${timestamp}.png` })
|
||||
console.log('[TEST] Final screenshot saved')
|
||||
|
||||
// THE BUG: If ourNoteAfterMove === 1, the note is still visible - triggerRefresh() didn't work!
|
||||
if (ourNoteAfterMove === 1) {
|
||||
console.log('[BUG CONFIRMED] triggerRefresh() is NOT working - note still visible!')
|
||||
console.log('[BUG CONFIRMED] This is the exact bug the user reported')
|
||||
} else {
|
||||
console.log('[SUCCESS] Note disappeared from main page - triggerRefresh() worked!')
|
||||
}
|
||||
})
|
||||
})
|
||||
138
keep-notes/tests/bug-note-move-refresh.spec.ts
Normal file
138
keep-notes/tests/bug-note-move-refresh.spec.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Bug: Note move to notebook - REFRESH ISSUE', () => {
|
||||
test('should update UI immediately when moving note to notebook WITHOUT page refresh', async ({ page }) => {
|
||||
const timestamp = Date.now()
|
||||
|
||||
// Step 1: Go to homepage (no login needed based on drag-drop tests)
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 2: Create a test note
|
||||
const testNoteTitle = `TEST-${timestamp}-Move Note`
|
||||
const testNoteContent = `This is a test note to verify move bug. Timestamp: ${timestamp}`
|
||||
|
||||
console.log('[TEST] Creating test note:', testNoteTitle)
|
||||
await page.click('input[placeholder="Take a note..."]')
|
||||
await page.fill('input[placeholder="Title"]', testNoteTitle)
|
||||
await page.fill('textarea[placeholder="Take a note..."]', testNoteContent)
|
||||
await page.click('button:has-text("Add")')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 3: Find the created note
|
||||
const notesBefore = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes count after creation:', notesBefore)
|
||||
expect(notesBefore).toBeGreaterThan(0)
|
||||
|
||||
// Step 4: Get the first note's ID and title
|
||||
const firstNote = page.locator('[data-draggable="true"]').first()
|
||||
const noteText = await firstNote.textContent()
|
||||
console.log('[TEST] First note text:', noteText?.substring(0, 100))
|
||||
|
||||
// Step 5: Create a test notebook
|
||||
console.log('[TEST] Creating test notebook')
|
||||
const testNotebookName = `TEST-NOTEBOOK-${timestamp}`
|
||||
|
||||
// Click the "Create Notebook" button (check for different possible selectors)
|
||||
const createNotebookBtn = page.locator('button:has-text("Créer"), button:has-text("Create"), button:has-text("+")').first()
|
||||
await createNotebookBtn.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Fill notebook name
|
||||
const notebookInput = page.locator('input[name="name"], input[placeholder*="notebook"], input[placeholder*="nom"]').first()
|
||||
await notebookInput.fill(testNotebookName)
|
||||
|
||||
// Submit
|
||||
const submitBtn = page.locator('button:has-text("Créer"), button:has-text("Create"), button[type="submit"]').first()
|
||||
await submitBtn.click()
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
console.log('[TEST] Notebook created:', testNotebookName)
|
||||
|
||||
// Step 6: Move the first note to the notebook
|
||||
console.log('[TEST] Moving note to notebook...')
|
||||
|
||||
// Look for a way to move the note - try to find a menu or button on the note
|
||||
// Try to find a notebook menu or context menu
|
||||
const notebookMenuBtn = firstNote.locator('button[aria-label*="notebook"], button[title*="notebook"], button:has(.icon-folder)').first()
|
||||
|
||||
if (await notebookMenuBtn.count() > 0) {
|
||||
console.log('[TEST] Found notebook menu button')
|
||||
await notebookMenuBtn.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Select the created notebook
|
||||
const notebookOption = page.locator(`[role="menuitem"]:has-text("${testNotebookName}")`).first()
|
||||
if (await notebookOption.count() > 0) {
|
||||
await notebookOption.click()
|
||||
console.log('[TEST] Clicked notebook option')
|
||||
} else {
|
||||
console.log('[TEST] Notebook option not found in menu')
|
||||
// List all menu items for debugging
|
||||
const allMenuItems = await page.locator('[role="menuitem"]').allTextContents()
|
||||
console.log('[TEST] Available menu items:', allMenuItems)
|
||||
}
|
||||
} else {
|
||||
console.log('[TEST] Notebook menu button not found, trying drag and drop')
|
||||
|
||||
// Alternative: Use drag and drop to move note to notebook
|
||||
const notebooksList = page.locator('[class*="notebook"], [class*="sidebar"]').locator(`text=${testNotebookName}`)
|
||||
const notebookCount = await notebooksList.count()
|
||||
console.log('[TEST] Found notebook in list:', notebookCount)
|
||||
|
||||
if (notebookCount > 0) {
|
||||
const notebookElement = notebooksList.first()
|
||||
await firstNote.dragTo(notebookElement)
|
||||
console.log('[TEST] Dragged note to notebook')
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the move operation to complete
|
||||
await page.waitForTimeout(3000)
|
||||
|
||||
// CRITICAL CHECK: Is the note still visible WITHOUT refresh?
|
||||
const notesAfterMove = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes count AFTER move (NO REFRESH):', notesAfterMove)
|
||||
|
||||
// Get title of first note after move
|
||||
const firstNoteAfter = page.locator('[data-draggable="true"]').first()
|
||||
const firstNoteAfterTitle = await firstNoteAfter.locator('[class*="title"], h1, h2, h3').first().textContent()
|
||||
|
||||
console.log('[TEST] First note title after move:', firstNoteAfterTitle)
|
||||
console.log('[TEST] Original note title:', testNoteTitle)
|
||||
|
||||
// The bug is: the moved note is STILL VISIBLE in "Notes générales"
|
||||
// This means the UI did NOT update after the move
|
||||
if (firstNoteAfterTitle?.includes(testNoteTitle)) {
|
||||
console.log('[BUG CONFIRMED] Moved note is STILL VISIBLE - UI did not update!')
|
||||
console.log('[BUG CONFIRMED] This confirms the bug: triggerRefresh() is not working')
|
||||
|
||||
// Take a screenshot for debugging
|
||||
await page.screenshot({ path: `playwright-report/bug-screenshot-${timestamp}.png` })
|
||||
} else {
|
||||
console.log('[SUCCESS] Moved note is no longer visible - UI updated correctly!')
|
||||
}
|
||||
|
||||
// Now refresh the page to see what happens
|
||||
console.log('[TEST] Refreshing page...')
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
const notesAfterRefresh = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes count AFTER REFRESH:', notesAfterRefresh)
|
||||
|
||||
// Check if the note is now gone after refresh
|
||||
const firstNoteAfterRefresh = await page.locator('[data-draggable="true"]').first()
|
||||
const firstNoteAfterRefreshTitle = await firstNoteAfterRefresh.locator('[class*="title"], h1, h2, h3').first().textContent()
|
||||
|
||||
console.log('[TEST] First note title AFTER REFRESH:', firstNoteAfterRefreshTitle)
|
||||
|
||||
if (firstNoteAfterRefreshTitle?.includes(testNoteTitle)) {
|
||||
console.log('[BUG CONFIRMED] Note is STILL visible after refresh too - move might have failed')
|
||||
} else {
|
||||
console.log('[SUCCESS] Note is gone after refresh - it was moved to notebook')
|
||||
}
|
||||
})
|
||||
})
|
||||
68
keep-notes/tests/bug-note-move-to-notebook.spec.ts
Normal file
68
keep-notes/tests/bug-note-move-to-notebook.spec.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Bug: Note move to notebook', () => {
|
||||
test('should update UI immediately when moving note to notebook', async ({ page }) => {
|
||||
// Step 1: Login
|
||||
await page.goto('http://localhost:3000/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
await page.waitForURL('http://localhost:3000/')
|
||||
|
||||
// Step 2: Create a test note in "Notes générales"
|
||||
const testNoteContent = `Test note for move bug ${Date.now()}`
|
||||
await page.fill('textarea[placeholder*="note"]', testNoteContent)
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Wait for note creation
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 3: Find the created note
|
||||
const notes = await page.locator('.note-card').all()
|
||||
expect(notes.length).toBeGreaterThan(0)
|
||||
|
||||
const firstNote = notes[0]
|
||||
const noteId = await firstNote.getAttribute('data-note-id')
|
||||
console.log('Created note with ID:', noteId)
|
||||
|
||||
// Step 4: Create a test notebook
|
||||
await page.click('button:has-text("Créer un notebook")')
|
||||
await page.fill('input[name="name"]', `Test Notebook ${Date.now()}`)
|
||||
await page.click('button:has-text("Créer")')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 5: Move the note to the notebook
|
||||
// Open notebook menu on the note
|
||||
await firstNote.click('button[aria-label*="notebook"]')
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Select the first notebook in the list
|
||||
const notebookOption = page.locator('[role="menuitem"]').first()
|
||||
const notebookName = await notebookOption.textContent()
|
||||
await notebookOption.click()
|
||||
|
||||
// Wait for the move operation
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 6: Verify the note is NO LONGER visible in "Notes générales"
|
||||
const notesAfterMove = await page.locator('.note-card').all()
|
||||
console.log('Notes in "Notes générales" after move:', notesAfterMove.length)
|
||||
|
||||
// The note should be gone from "Notes générales"
|
||||
const movedNote = await page.locator(`.note-card[data-note-id="${noteId}"]`).count()
|
||||
console.log('Moved note still visible in "Notes générales":', movedNote)
|
||||
expect(movedNote).toBe(0) // This should pass!
|
||||
|
||||
// Step 7: Navigate to the notebook
|
||||
await page.click(`text="${notebookName}"`)
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 8: Verify the note IS visible in the notebook
|
||||
const notesInNotebook = await page.locator('.note-card').all()
|
||||
console.log('Notes in notebook:', notesInNotebook.length)
|
||||
|
||||
const movedNoteInNotebook = await page.locator(`.note-card[data-note-id="${noteId}"]`).count()
|
||||
console.log('Moved note visible in notebook:', movedNoteInNotebook)
|
||||
expect(movedNoteInNotebook).toBe(1) // This should pass!
|
||||
})
|
||||
})
|
||||
194
keep-notes/tests/bug-note-visibility.spec.ts
Normal file
194
keep-notes/tests/bug-note-visibility.spec.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Bug: Note visibility after creation', () => {
|
||||
test('should display note immediately after creation in inbox WITHOUT page refresh', async ({ page }) => {
|
||||
const timestamp = Date.now()
|
||||
|
||||
// Step 1: Go to homepage
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 2: Count notes before creation
|
||||
const notesBefore = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes count before creation:', notesBefore)
|
||||
|
||||
// Step 3: Create a test note in inbox
|
||||
const testNoteTitle = `TEST-${timestamp}-Visibility Inbox`
|
||||
const testNoteContent = `This is a test note to verify visibility bug. Timestamp: ${timestamp}`
|
||||
|
||||
console.log('[TEST] Creating test note in inbox:', testNoteTitle)
|
||||
|
||||
// Click the note input
|
||||
const noteInput = page.locator('input[placeholder*="Take a note"], textarea[placeholder*="Take a note"]').first()
|
||||
await noteInput.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Fill title if input exists
|
||||
const titleInput = page.locator('input[placeholder*="Title"], input[name="title"]').first()
|
||||
if (await titleInput.count() > 0) {
|
||||
await titleInput.fill(testNoteTitle)
|
||||
await page.waitForTimeout(300)
|
||||
}
|
||||
|
||||
// Fill content
|
||||
const contentInput = page.locator('textarea[placeholder*="Take a note"], textarea').first()
|
||||
await contentInput.fill(testNoteContent)
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
// Submit note
|
||||
const submitBtn = page.locator('button:has-text("Add"), button:has-text("Ajouter"), button[type="submit"]').first()
|
||||
await submitBtn.click()
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 4: Verify note appears immediately WITHOUT refresh
|
||||
const notesAfter = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes count after creation (NO REFRESH):', notesAfter)
|
||||
|
||||
// Note count should increase
|
||||
expect(notesAfter).toBeGreaterThan(notesBefore)
|
||||
|
||||
// Verify the note is visible with the correct title
|
||||
const noteCards = page.locator('[data-draggable="true"]')
|
||||
let noteFound = false
|
||||
const noteCount = await noteCards.count()
|
||||
|
||||
for (let i = 0; i < noteCount; i++) {
|
||||
const noteText = await noteCards.nth(i).textContent()
|
||||
if (noteText?.includes(testNoteTitle) || noteText?.includes(testNoteContent.substring(0, 20))) {
|
||||
noteFound = true
|
||||
console.log('[SUCCESS] Note found immediately after creation!')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
expect(noteFound).toBe(true)
|
||||
})
|
||||
|
||||
test('should display note immediately after creation in notebook WITHOUT page refresh', async ({ page }) => {
|
||||
const timestamp = Date.now()
|
||||
|
||||
// Step 1: Go to homepage
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 2: Create a test notebook
|
||||
const testNotebookName = `TEST-NOTEBOOK-${timestamp}`
|
||||
console.log('[TEST] Creating test notebook:', testNotebookName)
|
||||
|
||||
const createNotebookBtn = page.locator('button:has-text("Créer"), button:has-text("Create"), button:has-text("+")').first()
|
||||
await createNotebookBtn.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
const notebookInput = page.locator('input[name="name"], input[placeholder*="notebook"], input[placeholder*="nom"]').first()
|
||||
await notebookInput.fill(testNotebookName)
|
||||
|
||||
const submitNotebookBtn = page.locator('button:has-text("Créer"), button:has-text("Create"), button[type="submit"]').first()
|
||||
await submitNotebookBtn.click()
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 3: Select the notebook
|
||||
const notebooksList = page.locator('[class*="notebook"], [class*="sidebar"]')
|
||||
const notebookItem = notebooksList.locator(`text=${testNotebookName}`).first()
|
||||
await notebookItem.click()
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 4: Count notes in notebook before creation
|
||||
const notesBefore = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes count in notebook before creation:', notesBefore)
|
||||
|
||||
// Step 5: Create a test note in the notebook
|
||||
const testNoteTitle = `TEST-${timestamp}-Visibility Notebook`
|
||||
const testNoteContent = `This is a test note in notebook. Timestamp: ${timestamp}`
|
||||
|
||||
console.log('[TEST] Creating test note in notebook:', testNoteTitle)
|
||||
|
||||
// Click the note input
|
||||
const noteInput = page.locator('input[placeholder*="Take a note"], textarea[placeholder*="Take a note"]').first()
|
||||
await noteInput.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Fill title if input exists
|
||||
const titleInput = page.locator('input[placeholder*="Title"], input[name="title"]').first()
|
||||
if (await titleInput.count() > 0) {
|
||||
await titleInput.fill(testNoteTitle)
|
||||
await page.waitForTimeout(300)
|
||||
}
|
||||
|
||||
// Fill content
|
||||
const contentInput = page.locator('textarea[placeholder*="Take a note"], textarea').first()
|
||||
await contentInput.fill(testNoteContent)
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
// Submit note
|
||||
const submitBtn = page.locator('button:has-text("Add"), button:has-text("Ajouter"), button[type="submit"]').first()
|
||||
await submitBtn.click()
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 6: Verify note appears immediately WITHOUT refresh
|
||||
const notesAfter = await page.locator('[data-draggable="true"]').count()
|
||||
console.log('[TEST] Notes count in notebook after creation (NO REFRESH):', notesAfter)
|
||||
|
||||
// Note count should increase
|
||||
expect(notesAfter).toBeGreaterThan(notesBefore)
|
||||
|
||||
// Verify the note is visible with the correct title
|
||||
const noteCards = page.locator('[data-draggable="true"]')
|
||||
let noteFound = false
|
||||
const noteCount = await noteCards.count()
|
||||
|
||||
for (let i = 0; i < noteCount; i++) {
|
||||
const noteText = await noteCards.nth(i).textContent()
|
||||
if (noteText?.includes(testNoteTitle) || noteText?.includes(testNoteContent.substring(0, 20))) {
|
||||
noteFound = true
|
||||
console.log('[SUCCESS] Note found immediately after creation in notebook!')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
expect(noteFound).toBe(true)
|
||||
})
|
||||
|
||||
test('should maintain scroll position after note creation', async ({ page }) => {
|
||||
const timestamp = Date.now()
|
||||
|
||||
// Step 1: Go to homepage
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 2: Scroll down a bit
|
||||
await page.evaluate(() => window.scrollTo(0, 300))
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
// Get scroll position before
|
||||
const scrollBefore = await page.evaluate(() => window.scrollY)
|
||||
console.log('[TEST] Scroll position before creation:', scrollBefore)
|
||||
|
||||
// Step 3: Create a test note
|
||||
const testNoteContent = `TEST-${timestamp}-Scroll Position`
|
||||
|
||||
console.log('[TEST] Creating test note...')
|
||||
|
||||
const noteInput = page.locator('input[placeholder*="Take a note"], textarea[placeholder*="Take a note"]').first()
|
||||
await noteInput.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
const contentInput = page.locator('textarea[placeholder*="Take a note"], textarea').first()
|
||||
await contentInput.fill(testNoteContent)
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
const submitBtn = page.locator('button:has-text("Add"), button:has-text("Ajouter"), button[type="submit"]').first()
|
||||
await submitBtn.click()
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Step 4: Verify scroll position is maintained (should be similar, not reset to 0)
|
||||
const scrollAfter = await page.evaluate(() => window.scrollY)
|
||||
console.log('[TEST] Scroll position after creation:', scrollAfter)
|
||||
|
||||
// Scroll position should be maintained (not reset to 0)
|
||||
// Allow some tolerance for UI updates
|
||||
expect(Math.abs(scrollAfter - scrollBefore)).toBeLessThan(100)
|
||||
})
|
||||
})
|
||||
170
keep-notes/tests/favorites-section.spec.ts
Normal file
170
keep-notes/tests/favorites-section.spec.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Favorites Section', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to home page
|
||||
await page.goto('/')
|
||||
// Wait for page to load
|
||||
await page.waitForLoadState('networkidle')
|
||||
})
|
||||
|
||||
test('should not show favorites section when no notes are pinned', async ({ page }) => {
|
||||
// Favorites section should not be present
|
||||
const favoritesSection = page.locator('[data-testid="favorites-section"]')
|
||||
await expect(favoritesSection).not.toBeVisible()
|
||||
})
|
||||
|
||||
test('should pin a note and show it in favorites section', async ({ page }) => {
|
||||
// Check if there are any existing notes
|
||||
const existingNotes = page.locator('[data-testid="note-card"]')
|
||||
const noteCount = await existingNotes.count()
|
||||
|
||||
if (noteCount === 0) {
|
||||
// Skip test if no notes exist
|
||||
test.skip()
|
||||
return
|
||||
}
|
||||
|
||||
// Pin the first note
|
||||
const firstNoteCard = existingNotes.first()
|
||||
await firstNoteCard.hover()
|
||||
|
||||
// Find and click the pin button (it's near the top right)
|
||||
const pinButton = firstNoteCard.locator('button').filter({ hasText: '' }).nth(0)
|
||||
await pinButton.click()
|
||||
|
||||
// Wait for page refresh after pinning
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Favorites section should be visible
|
||||
const favoritesSection = page.locator('[data-testid="favorites-section"]')
|
||||
await expect(favoritesSection).toBeVisible()
|
||||
|
||||
// Should have section title
|
||||
const sectionTitle = favoritesSection.locator('h2')
|
||||
await expect(sectionTitle).toContainText('Pinned')
|
||||
|
||||
// Should have at least 1 pinned note
|
||||
const pinnedNotes = favoritesSection.locator('[data-testid="note-card"]')
|
||||
await expect(pinnedNotes).toHaveCount(1)
|
||||
})
|
||||
|
||||
test('should unpin a note and remove it from favorites', async ({ page }) => {
|
||||
// Check if there are any pinned notes already
|
||||
const favoritesSection = page.locator('[data-testid="favorites-section"]')
|
||||
const isFavoritesVisible = await favoritesSection.isVisible().catch(() => false)
|
||||
|
||||
if (!isFavoritesVisible) {
|
||||
// Skip test if no favorites exist
|
||||
test.skip()
|
||||
return
|
||||
}
|
||||
|
||||
const pinnedNotes = favoritesSection.locator('[data-testid="note-card"]')
|
||||
const pinnedCount = await pinnedNotes.count()
|
||||
|
||||
if (pinnedCount === 0) {
|
||||
// Skip test if no pinned notes
|
||||
test.skip()
|
||||
return
|
||||
}
|
||||
|
||||
// Unpin the first pinned note
|
||||
const firstPinnedNote = pinnedNotes.first()
|
||||
await firstPinnedNote.hover()
|
||||
|
||||
const pinButton = firstPinnedNote.locator('button').filter({ hasText: '' }).nth(0)
|
||||
await pinButton.click()
|
||||
|
||||
// Wait for page refresh after unpinning
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// After unpinning the last pinned note, section should be hidden
|
||||
const updatedPinnedCount = await favoritesSection.locator('[data-testid="note-card"]').count().catch(() => 0)
|
||||
const isStillVisible = await favoritesSection.isVisible().catch(() => false)
|
||||
|
||||
// If there were only 1 pinned note, section should be hidden
|
||||
// Otherwise, count should be reduced
|
||||
if (pinnedCount === 1) {
|
||||
await expect(isStillVisible).toBe(false)
|
||||
} else {
|
||||
await expect(updatedPinnedCount).toBe(pinnedCount - 1)
|
||||
}
|
||||
})
|
||||
|
||||
test('should show multiple pinned notes in favorites section', async ({ page }) => {
|
||||
// Check if there are existing notes
|
||||
const existingNotes = page.locator('[data-testid="note-card"]')
|
||||
const noteCount = await existingNotes.count()
|
||||
|
||||
if (noteCount < 2) {
|
||||
// Skip test if not enough notes exist
|
||||
test.skip()
|
||||
return
|
||||
}
|
||||
|
||||
// Pin first two notes
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const noteCard = existingNotes.nth(i)
|
||||
await noteCard.hover()
|
||||
|
||||
const pinButton = noteCard.locator('button').filter({ hasText: '' }).nth(0)
|
||||
await pinButton.click()
|
||||
|
||||
// Wait for page refresh
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Re-query notes after refresh
|
||||
const refreshedNotes = page.locator('[data-testid="note-card"]')
|
||||
await refreshedNotes.count()
|
||||
}
|
||||
|
||||
// Favorites section should be visible
|
||||
const favoritesSection = page.locator('[data-testid="favorites-section"]')
|
||||
await expect(favoritesSection).toBeVisible()
|
||||
|
||||
// Should have 2 pinned notes
|
||||
const pinnedNotes = favoritesSection.locator('[data-testid="note-card"]')
|
||||
await expect(pinnedNotes).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('should show favorites section above main notes', async ({ page }) => {
|
||||
// Check if there are existing notes
|
||||
const existingNotes = page.locator('[data-testid="note-card"]')
|
||||
const noteCount = await existingNotes.count()
|
||||
|
||||
if (noteCount === 0) {
|
||||
// Skip test if no notes exist
|
||||
test.skip()
|
||||
return
|
||||
}
|
||||
|
||||
// Pin a note
|
||||
const firstNoteCard = existingNotes.first()
|
||||
await firstNoteCard.hover()
|
||||
|
||||
const pinButton = firstNoteCard.locator('button').filter({ hasText: '' }).nth(0)
|
||||
await pinButton.click()
|
||||
|
||||
// Wait for page refresh
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Both sections should be visible
|
||||
const favoritesSection = page.locator('[data-testid="favorites-section"]')
|
||||
const mainNotesGrid = page.locator('[data-testid="notes-grid"]')
|
||||
|
||||
await expect(favoritesSection).toBeVisible()
|
||||
|
||||
// Main notes grid might be visible only if there are unpinned notes
|
||||
const hasUnpinnedNotes = await mainNotesGrid.isVisible().catch(() => false)
|
||||
if (hasUnpinnedNotes) {
|
||||
// Get Y positions to verify favorites is above
|
||||
const favoritesY = await favoritesSection.boundingBox()
|
||||
const mainNotesY = await mainNotesGrid.boundingBox()
|
||||
|
||||
if (favoritesY && mainNotesY) {
|
||||
expect(favoritesY.y).toBeLessThan(mainNotesY.y)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
161
keep-notes/tests/recent-notes-section.spec.ts
Normal file
161
keep-notes/tests/recent-notes-section.spec.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Recent Notes Section', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to home page
|
||||
await page.goto('/')
|
||||
// Wait for page to load
|
||||
await page.waitForLoadState('networkidle')
|
||||
})
|
||||
|
||||
test('should display recent notes section when notes exist', async ({ page }) => {
|
||||
// Check if recent notes section exists
|
||||
const recentSection = page.locator('[data-testid="recent-notes-section"]')
|
||||
|
||||
// The section should be visible when there are recent notes
|
||||
// Note: This test assumes there are notes created/modified in the last 7 days
|
||||
await expect(recentSection).toBeVisible()
|
||||
})
|
||||
|
||||
test('should show section header with clock icon and title', async ({ page }) => {
|
||||
const recentSection = page.locator('[data-testid="recent-notes-section"]')
|
||||
|
||||
// Check for header elements
|
||||
await expect(recentSection.locator('text=Recent Notes')).toBeVisible()
|
||||
await expect(recentSection.locator('text=(last 7 days)')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should be collapsible', async ({ page }) => {
|
||||
const recentSection = page.locator('[data-testid="recent-notes-section"]')
|
||||
const collapseButton = recentSection.locator('button[aria-expanded]')
|
||||
|
||||
// Check that collapse button exists
|
||||
await expect(collapseButton).toBeVisible()
|
||||
|
||||
// Click to collapse
|
||||
await collapseButton.click()
|
||||
await expect(collapseButton).toHaveAttribute('aria-expanded', 'false')
|
||||
|
||||
// Click to expand
|
||||
await collapseButton.click()
|
||||
await expect(collapseButton).toHaveAttribute('aria-expanded', 'true')
|
||||
})
|
||||
|
||||
test('should display notes in grid layout', async ({ page }) => {
|
||||
const recentSection = page.locator('[data-testid="recent-notes-section"]')
|
||||
const collapseButton = recentSection.locator('button[aria-expanded]')
|
||||
|
||||
// Ensure section is expanded
|
||||
if (await collapseButton.getAttribute('aria-expanded') === 'false') {
|
||||
await collapseButton.click()
|
||||
}
|
||||
|
||||
// Check for grid layout
|
||||
const grid = recentSection.locator('.grid')
|
||||
await expect(grid).toBeVisible()
|
||||
|
||||
// Check that grid has correct classes
|
||||
await expect(grid).toHaveClass(/grid-cols-1/)
|
||||
})
|
||||
|
||||
test('should not show pinned notes in recent section', async ({ page }) => {
|
||||
const recentSection = page.locator('[data-testid="recent-notes-section"]')
|
||||
|
||||
// Recent notes should filter out pinned notes
|
||||
// Get all note cards in recent section
|
||||
const recentNoteCards = recentSection.locator('[data-testid^="note-card-"]')
|
||||
|
||||
// If there are recent notes, none should be pinned
|
||||
const count = await recentNoteCards.count()
|
||||
if (count > 0) {
|
||||
// Check that none of the notes in recent section have pin indicator
|
||||
// This is an indirect check - pinned notes are shown in FavoritesSection
|
||||
// The implementation should filter them out
|
||||
const favoriteSection = page.locator('[data-testid="favorites-section"]')
|
||||
await expect(favoriteSection).toBeVisible()
|
||||
}
|
||||
})
|
||||
|
||||
test('should handle empty state (no recent notes)', async ({ page }) => {
|
||||
// This test would need to manipulate the database to ensure no recent notes
|
||||
// For now, we can check that the section doesn't break when empty
|
||||
|
||||
// Reload page to check stability
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// Page should load without errors
|
||||
await expect(page).toHaveTitle(/Keep/)
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Recent Notes - Integration', () => {
|
||||
test('new note should appear in recent section', async ({ page }) => {
|
||||
// Create a new note
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
const noteContent = `Test note for recent section - ${Date.now()}`
|
||||
|
||||
// Type in note input
|
||||
const noteInput = page.locator('[data-testid="note-input-textarea"]')
|
||||
await noteInput.fill(noteContent)
|
||||
|
||||
// Submit note
|
||||
const submitButton = page.locator('button[type="submit"]')
|
||||
await submitButton.click()
|
||||
|
||||
// Wait for note to be created
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
// Reload page to refresh recent notes
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// Check if recent notes section is visible
|
||||
const recentSection = page.locator('[data-testid="recent-notes-section"]')
|
||||
|
||||
// The section should now be visible with the new note
|
||||
await expect(recentSection).toBeVisible()
|
||||
})
|
||||
|
||||
test('editing note should update its position in recent section', async ({ page }) => {
|
||||
// This test verifies that edited notes move to top
|
||||
// It requires at least one note to exist
|
||||
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
const recentSection = page.locator('[data-testid="recent-notes-section"]')
|
||||
|
||||
// If recent notes exist
|
||||
if (await recentSection.isVisible()) {
|
||||
// Get first note card
|
||||
const firstNote = recentSection.locator('[data-testid^="note-card-"]').first()
|
||||
|
||||
// Click to edit
|
||||
await firstNote.click()
|
||||
|
||||
// Wait for editor to open
|
||||
const editor = page.locator('[data-testid="note-editor"]')
|
||||
await expect(editor).toBeVisible()
|
||||
|
||||
// Make a small edit
|
||||
const contentArea = editor.locator('textarea').first()
|
||||
await contentArea.press('End')
|
||||
await contentArea.type(' - edited')
|
||||
|
||||
// Save changes
|
||||
const saveButton = editor.locator('button:has-text("Save")').first()
|
||||
await saveButton.click()
|
||||
|
||||
// Wait for save and reload
|
||||
await page.waitForTimeout(1000)
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// The edited note should still be in recent section
|
||||
await expect(recentSection).toBeVisible()
|
||||
}
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user