From c47c5a6c8b36ebe7d8620a14fe804945d3a5559c Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Sun, 9 Aug 2026 11:08:52 -0400 Subject: [PATCH] Fix Windows E2E command and improve smoke tests Add Windows PowerShell alternative for running E2E tests in README and update smoke tests to verify the target is a Shaarli instance, with better diagnostics for misconfigured URLs. --- README.md | 5 +++ shaarli-pro/linklist.paging.html | 4 +- shaarli-pro/tests/smoke.spec.js | 70 ++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9898fb5..f4f9f73 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,12 @@ Un socle de tests E2E est fourni pour valider les parcours critiques : ```bash cd shaarli-pro npm run test:e2e:install # installer les navigateurs Playwright (une fois) + +# Linux / macOS SHAARLI_URL=http://localhost:8080 npm run test:e2e + +# Windows (PowerShell) +$env:SHAARLI_URL="http://localhost:8080"; npm run test:e2e ``` Les tests couvrent actuellement : diff --git a/shaarli-pro/linklist.paging.html b/shaarli-pro/linklist.paging.html index b0303d5..42d4b15 100644 --- a/shaarli-pro/linklist.paging.html +++ b/shaarli-pro/linklist.paging.html @@ -14,9 +14,9 @@ {$from=($page_current - 1) * $links_per_page + 1} {$to=min($total, ($page_current - 1) * $links_per_page + $links_per_page)} {if="!empty($search_tags) && stripos($search_tags, 'note') !== false"} -{$paging_label="{'Notes'|t}"} +{$paging_label=t('Notes')} {else} -{$paging_label="{'Bookmarks'|t}"} +{$paging_label=t('Bookmarks')} {/if}
{if="$page_max > 1"} diff --git a/shaarli-pro/tests/smoke.spec.js b/shaarli-pro/tests/smoke.spec.js index 3603367..081f1d5 100644 --- a/shaarli-pro/tests/smoke.spec.js +++ b/shaarli-pro/tests/smoke.spec.js @@ -3,36 +3,76 @@ * * These tests require a running Shaarli instance with the shaarli-pro theme * activated. Set SHAARLI_URL before running. + * + * Example: + * SHAARLI_URL=http://localhost:8080 npx playwright test */ 'use strict'; const { test, expect } = require('@playwright/test'); +/** + * Verify the current page resolves to a Shaarli instance. + * Returns true if Shaarli elements are found, skips the test otherwise. + */ +async function ensureShaarli(page, testInfo) { + // Check for Shaarli-specific markers (linklist container, sidebar, or the search overlay) + const shaarliMarkers = page.locator('#linklist, .shaarli-sidebar, #search-overlay, .search-overlay, meta[name="generator"][content*="Shaarli"]'); + await shaarliMarkers.first().waitFor({ state: 'attached', timeout: 3000 }).catch(() => {}); + const count = await shaarliMarkers.count(); + if (count === 0) { + // Diagnose: what's actually running on this URL? + const title = await page.title(); + const bodyText = await page.locator('body').textContent({ timeout: 2000 }).catch(() => '(timeout)'); + const snippet = (bodyText || '').substring(0, 200); + throw new Error( + `SHAARLI_URL (${testInfo.project.use.baseURL}) does not appear to be a Shaarli instance.\n` + + `Page title: "${title}"\n` + + `Page content: "${snippet}"\n\n` + + `Make sure:\n` + + ` 1. Shaarli is running and accessible at this URL\n` + + ` 2. The "shaarli-pro" theme is activated in Shaarli settings\n` + + ` 3. No other application is using this port` + ); + } + return true; +} + test.describe('Shaarli Pro theme smoke tests', () => { - test('homepage loads and shows the main layout', async ({ page }) => { + test('homepage loads and shows the main layout', async ({ page }, testInfo) => { await page.goto('/'); await expect(page.locator('body')).toBeVisible(); - // Sidebar or header should be present. - await expect( - page.locator('.shaarli-sidebar, .sidebar, header, .header') - ).toHaveCount(1); + await ensureShaarli(page, testInfo); + + // Header should be present (the theme uses
) + const header = page.locator('header.header-main'); + await expect(header).toBeVisible({ timeout: 5000 }); + + // Sidebar should be present + const sidebar = page.locator('.sidebar'); + await expect(sidebar).toBeVisible(); }); - test('search overlay opens with the S shortcut', async ({ page }) => { + test('search overlay opens with the S shortcut', async ({ page }, testInfo) => { await page.goto('/'); + await ensureShaarli(page, testInfo); + const search = page.locator('.search-overlay, #search-overlay'); await expect(search).not.toBeVisible(); await page.keyboard.press('s'); - await expect(search).toBeVisible(); + await expect(search).toBeVisible({ timeout: 3000 }); await page.keyboard.press('Escape'); - await expect(search).not.toBeVisible(); + await expect(search).not.toBeVisible({ timeout: 2000 }); }); - test('theme toggle changes data-theme attribute', async ({ page }) => { + test('theme toggle changes data-theme attribute', async ({ page }, testInfo) => { await page.goto('/'); + await ensureShaarli(page, testInfo); + const toggle = page.locator('[data-theme-toggle], .theme-toggle, #theme-toggle'); if (await toggle.count() === 0) { test.skip('No theme toggle found on this page'); + return; } const initialTheme = await page.locator('html').getAttribute('data-theme'); await toggle.click(); @@ -41,16 +81,22 @@ test.describe('Shaarli Pro theme smoke tests', () => { expect(newTheme).not.toEqual(initialTheme); }); - test('skip-link is present for keyboard users', async ({ page }) => { + test('skip-link is present for keyboard users', async ({ page }, testInfo) => { await page.goto('/'); + await ensureShaarli(page, testInfo); + + await expect(page.locator('.skip-link')).toBeVisible(); await expect(page.locator('.skip-link')).toHaveAttribute('href'); }); - test('bulk selection button is present on link list', async ({ page }) => { + test('bulk selection button is present on link list', async ({ page }, testInfo) => { await page.goto('/'); + await ensureShaarli(page, testInfo); + const bulkButton = page.locator('[data-bulk-select], .bulk-select-toggle, #bulk-select'); if (await bulkButton.count() === 0) { - test.skip('No bulk selection button found'); + test.skip('No bulk selection button found (user may not be logged in)'); + return; } await expect(bulkButton).toBeVisible(); });