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.
This commit is contained in:
@@ -183,7 +183,12 @@ Un socle de tests E2E est fourni pour valider les parcours critiques :
|
|||||||
```bash
|
```bash
|
||||||
cd shaarli-pro
|
cd shaarli-pro
|
||||||
npm run test:e2e:install # installer les navigateurs Playwright (une fois)
|
npm run test:e2e:install # installer les navigateurs Playwright (une fois)
|
||||||
|
|
||||||
|
# Linux / macOS
|
||||||
SHAARLI_URL=http://localhost:8080 npm run test:e2e
|
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 :
|
Les tests couvrent actuellement :
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
{$from=($page_current - 1) * $links_per_page + 1}
|
{$from=($page_current - 1) * $links_per_page + 1}
|
||||||
{$to=min($total, ($page_current - 1) * $links_per_page + $links_per_page)}
|
{$to=min($total, ($page_current - 1) * $links_per_page + $links_per_page)}
|
||||||
{if="!empty($search_tags) && stripos($search_tags, 'note') !== false"}
|
{if="!empty($search_tags) && stripos($search_tags, 'note') !== false"}
|
||||||
{$paging_label="{'Notes'|t}"}
|
{$paging_label=t('Notes')}
|
||||||
{else}
|
{else}
|
||||||
{$paging_label="{'Bookmarks'|t}"}
|
{$paging_label=t('Bookmarks')}
|
||||||
{/if}
|
{/if}
|
||||||
<div class="paging{if="$page_max <=1"} single-page{/if}">
|
<div class="paging{if="$page_max <=1"} single-page{/if}">
|
||||||
{if="$page_max > 1"}
|
{if="$page_max > 1"}
|
||||||
|
|||||||
@@ -3,36 +3,76 @@
|
|||||||
*
|
*
|
||||||
* These tests require a running Shaarli instance with the shaarli-pro theme
|
* These tests require a running Shaarli instance with the shaarli-pro theme
|
||||||
* activated. Set SHAARLI_URL before running.
|
* activated. Set SHAARLI_URL before running.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* SHAARLI_URL=http://localhost:8080 npx playwright test
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { test, expect } = require('@playwright/test');
|
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.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 page.goto('/');
|
||||||
await expect(page.locator('body')).toBeVisible();
|
await expect(page.locator('body')).toBeVisible();
|
||||||
// Sidebar or header should be present.
|
await ensureShaarli(page, testInfo);
|
||||||
await expect(
|
|
||||||
page.locator('.shaarli-sidebar, .sidebar, header, .header')
|
// Header should be present (the theme uses <header class="header-main">)
|
||||||
).toHaveCount(1);
|
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 page.goto('/');
|
||||||
|
await ensureShaarli(page, testInfo);
|
||||||
|
|
||||||
const search = page.locator('.search-overlay, #search-overlay');
|
const search = page.locator('.search-overlay, #search-overlay');
|
||||||
await expect(search).not.toBeVisible();
|
await expect(search).not.toBeVisible();
|
||||||
await page.keyboard.press('s');
|
await page.keyboard.press('s');
|
||||||
await expect(search).toBeVisible();
|
await expect(search).toBeVisible({ timeout: 3000 });
|
||||||
await page.keyboard.press('Escape');
|
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 page.goto('/');
|
||||||
|
await ensureShaarli(page, testInfo);
|
||||||
|
|
||||||
const toggle = page.locator('[data-theme-toggle], .theme-toggle, #theme-toggle');
|
const toggle = page.locator('[data-theme-toggle], .theme-toggle, #theme-toggle');
|
||||||
if (await toggle.count() === 0) {
|
if (await toggle.count() === 0) {
|
||||||
test.skip('No theme toggle found on this page');
|
test.skip('No theme toggle found on this page');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
const initialTheme = await page.locator('html').getAttribute('data-theme');
|
const initialTheme = await page.locator('html').getAttribute('data-theme');
|
||||||
await toggle.click();
|
await toggle.click();
|
||||||
@@ -41,16 +81,22 @@ test.describe('Shaarli Pro theme smoke tests', () => {
|
|||||||
expect(newTheme).not.toEqual(initialTheme);
|
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 page.goto('/');
|
||||||
|
await ensureShaarli(page, testInfo);
|
||||||
|
|
||||||
|
await expect(page.locator('.skip-link')).toBeVisible();
|
||||||
await expect(page.locator('.skip-link')).toHaveAttribute('href');
|
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 page.goto('/');
|
||||||
|
await ensureShaarli(page, testInfo);
|
||||||
|
|
||||||
const bulkButton = page.locator('[data-bulk-select], .bulk-select-toggle, #bulk-select');
|
const bulkButton = page.locator('[data-bulk-select], .bulk-select-toggle, #bulk-select');
|
||||||
if (await bulkButton.count() === 0) {
|
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();
|
await expect(bulkButton).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user