test: integrate playwright cache navigation spec

This commit is contained in:
Luca Sacchi Ricciardi
2026-04-25 16:06:59 +02:00
parent 760c9cc923
commit ac2089f921
4 changed files with 107 additions and 1 deletions
+3
View File
@@ -376,6 +376,9 @@ pytest tests/ -v
# Test con coverage # Test con coverage
pytest tests/ --cov=app pytest tests/ --cov=app
# Browser E2E test (cache-first navigation)
OLLAMA_HOST=http://192.168.254.115:11434 npm run test:e2e
# Hot reload durante sviluppo # Hot reload durante sviluppo
uvicorn main:app --reload uvicorn main:app --reload
``` ```
+4 -1
View File
@@ -1,13 +1,16 @@
{ {
"name": "llm-monitor", "name": "llm-monitor",
"version": "1.0.0", "version": "1.0.0",
"type": "commonjs",
"description": "Dashboard per controllare i modelli caricati in Ollama", "description": "Dashboard per controllare i modelli caricati in Ollama",
"private": true, "private": true,
"scripts": { "scripts": {
"tailwind:dev": "tailwindcss -i ./app/web/static/css/input.css -o ./app/web/static/css/output.css --watch", "tailwind:dev": "tailwindcss -i ./app/web/static/css/input.css -o ./app/web/static/css/output.css --watch",
"tailwind:build": "tailwindcss -i ./app/web/static/css/input.css -o ./app/web/static/css/output.css" "tailwind:build": "tailwindcss -i ./app/web/static/css/input.css -o ./app/web/static/css/output.css",
"test:e2e": "playwright test tests/e2e/cache-navigation.spec.js"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.59.1",
"tailwindcss": "^3.4.0" "tailwindcss": "^3.4.0"
} }
} }
+22
View File
@@ -0,0 +1,22 @@
const { defineConfig } = require('@playwright/test');
const baseURL = process.env.TARGET_URL || 'http://127.0.0.1:8011';
module.exports = defineConfig({
testDir: './tests/e2e',
timeout: 45000,
fullyParallel: false,
retries: 0,
reporter: 'list',
use: {
baseURL,
headless: true,
serviceWorkers: 'block'
},
webServer: {
command: 'python3 -m uvicorn main:app --host 127.0.0.1 --port 8011',
url: baseURL,
reuseExistingServer: true,
timeout: 30000
}
});
+78
View File
@@ -0,0 +1,78 @@
const { test, expect } = require('@playwright/test');
const OLLAMA_HOST = process.env.OLLAMA_HOST || 'http://192.168.254.115:11434';
const SERVER_ID = process.env.TEST_SERVER_ID || 'srv_e2e_cache';
const SERVER_NAME = process.env.TEST_SERVER_NAME || 'E2E Cache Server';
const QUIET_WINDOW_MS = Number(process.env.QUIET_WINDOW_MS || 1500);
const CACHE_WAIT_TIMEOUT_MS = Number(process.env.CACHE_WAIT_TIMEOUT_MS || 20000);
test.describe('cache-first server navigation', () => {
test.beforeEach(async ({ page }) => {
await page.addInitScript(
({ serverId, serverName, host }) => {
localStorage.setItem(
'llm_monitor_servers',
JSON.stringify([
{
id: serverId,
name: serverName,
host
}
])
);
localStorage.setItem('llm_monitor_active_server', serverId);
},
{
serverId: SERVER_ID,
serverName: SERVER_NAME,
host: OLLAMA_HOST
}
);
});
test('serves cached data when navigating between running and available pages', async ({ context, page }) => {
const apiRequests = [];
context.on('request', (request) => {
const url = new URL(request.url());
if (url.pathname.startsWith('/api/v1/')) {
apiRequests.push(url.pathname + url.search);
}
});
const resetApiRequests = () => {
apiRequests.length = 0;
};
const waitForQuietWindow = async (label) => {
await page.waitForTimeout(QUIET_WINDOW_MS);
expect(apiRequests, `${label} should not issue API requests while cache is fresh`).toEqual([]);
};
await page.goto(`/models-running?server=${SERVER_ID}`, { waitUntil: 'domcontentloaded' });
await page.waitForFunction(
(serverId) => {
return ['health', 'models', 'running'].every((suffix) => {
return Boolean(localStorage.getItem(`llm_monitor_${suffix}_${serverId}`));
});
},
SERVER_ID,
{ timeout: CACHE_WAIT_TIMEOUT_MS }
);
expect(apiRequests.length).toBeGreaterThan(0);
resetApiRequests();
await page.goto(`/models-available?server=${SERVER_ID}`, { waitUntil: 'domcontentloaded' });
await waitForQuietWindow('running -> available');
resetApiRequests();
await page.goto(`/models-running?server=${SERVER_ID}`, { waitUntil: 'domcontentloaded' });
await waitForQuietWindow('available -> running');
resetApiRequests();
await page.goto(`/models-available?server=${SERVER_ID}`, { waitUntil: 'domcontentloaded' });
await waitForQuietWindow('running -> available again');
});
});