import { test, expect } from '@playwright/test'; import * as fs from 'fs'; function loadFixture(name: string): string { return fs.readFileSync(`tests/Fixtures/ccli/${name}`, 'utf-8'); } test.describe('CCLI Paste Import - SongDB', () => { test('SongDB page shows CCLI import buttons', async ({ page }) => { await page.goto('/songs'); await page.waitForLoadState('networkidle'); await expect(page.getByTestId('open-ccli-paste-dialog-button-songdb')).toBeVisible(); }); test('SongSelect search button opens new tab with prefilled URL', async ({ page }) => { await page.goto('/songs'); await page.waitForLoadState('networkidle'); // Fill search input await page.getByTestId('song-list-search-input').fill('amazing grace'); await page.waitForTimeout(300); // Click SongSelect search button const [popup] = await Promise.all([ page.waitForEvent('popup'), page.getByTestId('songselect-search-button-songdb').click(), ]); await popup.waitForLoadState('domcontentloaded'); expect(popup.url()).toContain('songselect.ccli.com'); expect(popup.url()).toContain('amazing'); await popup.close(); }); test('opens CCLI paste dialog from SongDB', async ({ page }) => { await page.goto('/songs'); await page.waitForLoadState('networkidle'); await page.getByTestId('open-ccli-paste-dialog-button-songdb').click(); await expect(page.getByTestId('ccli-paste-textarea')).toBeVisible(); await expect(page.getByTestId('ccli-preview-button')).toBeDisabled(); }); test('preview button disabled when textarea empty', async ({ page }) => { await page.goto('/songs'); await page.waitForLoadState('networkidle'); await page.getByTestId('open-ccli-paste-dialog-button-songdb').click(); await expect(page.getByTestId('ccli-preview-button')).toBeDisabled(); }); test('paste fixture and preview shows metadata', async ({ page }) => { await page.goto('/songs'); await page.waitForLoadState('networkidle'); await page.getByTestId('open-ccli-paste-dialog-button-songdb').click(); const content = loadFixture('english-only-multi-verse.txt'); await page.getByTestId('ccli-paste-textarea').fill(content); await expect(page.getByTestId('ccli-preview-button')).toBeEnabled(); await page.getByTestId('ccli-preview-button').click(); await page.waitForTimeout(3000); const errorMsg = page.getByTestId('ccli-error-message'); const hasError = await errorMsg.isVisible().catch(() => false); if (hasError) { test.skip(); return; } await expect(page.locator('text=CCLI-Nr')).toBeVisible({ timeout: 5000 }); }); test('duplicate import shows error with edit link', async ({ page }) => { const content = loadFixture('english-only-multi-verse.txt'); await page.goto('/songs'); await page.waitForLoadState('networkidle'); const cookies = await page.context().cookies(); const xsrf = cookies.find(c => c.name === 'XSRF-TOKEN')?.value ?? ''; const importRes = await page.request.post('/api/songs/import-from-ccli-paste', { headers: { 'Content-Type': 'application/json', 'X-XSRF-TOKEN': decodeURIComponent(xsrf), }, data: { raw_text: content, mode: 'create' }, }); if (importRes.status() !== 201) { test.skip(); return; } // Now try to import again via UI await page.goto('/songs'); await page.waitForLoadState('networkidle'); await page.getByTestId('open-ccli-paste-dialog-button-songdb').click(); await page.getByTestId('ccli-paste-textarea').fill(content); await page.getByTestId('ccli-preview-button').click(); await page.waitForTimeout(2000); // Click import const importBtn = page.getByTestId('ccli-import-stay-button'); if (await importBtn.isVisible()) { await importBtn.click(); await page.waitForTimeout(2000); await expect(page.getByTestId('ccli-error-message')).toBeVisible(); await expect(page.getByTestId('ccli-existing-song-link')).toBeVisible(); } }); });