7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
283 lines
10 KiB
JavaScript
283 lines
10 KiB
JavaScript
/**
|
|
* Test Context Overflow Dashboard
|
|
* Tests the context overflow analytics page functionality
|
|
*/
|
|
|
|
const puppeteer = require('puppeteer');
|
|
const AuthHelper = require('./auth_helper');
|
|
|
|
const BASE_URL = process.env.BASE_URL || 'http://127.0.0.1:5000';
|
|
const HEADLESS = process.env.HEADLESS !== 'false';
|
|
const SLOW_MO = parseInt(process.env.SLOW_MO || '0', 10);
|
|
|
|
describe('Context Overflow Dashboard Tests', () => {
|
|
let browser;
|
|
let page;
|
|
let authHelper;
|
|
|
|
beforeAll(async () => {
|
|
browser = await puppeteer.launch({
|
|
headless: HEADLESS,
|
|
slowMo: SLOW_MO,
|
|
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
});
|
|
});
|
|
|
|
afterAll(async () => {
|
|
if (browser) {
|
|
await browser.close();
|
|
}
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
page = await browser.newPage();
|
|
await page.setViewport({ width: 1280, height: 800 });
|
|
authHelper = new AuthHelper(page, BASE_URL);
|
|
|
|
// Set longer timeout for slower operations
|
|
page.setDefaultTimeout(30000);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (page) {
|
|
await page.close();
|
|
}
|
|
});
|
|
|
|
test('Context overflow dashboard loads and displays data', async () => {
|
|
console.log('📊 Testing context overflow dashboard...');
|
|
|
|
// Login first
|
|
await authHelper.ensureAuthenticated();
|
|
|
|
// Navigate to context overflow page
|
|
console.log(' Navigating to context overflow page...');
|
|
await page.goto(`${BASE_URL}/metrics/context-overflow`, {
|
|
waitUntil: 'domcontentloaded',
|
|
timeout: 30000
|
|
});
|
|
|
|
// Wait for page to load
|
|
await page.waitForSelector('#context-overflow', { timeout: 10000 });
|
|
console.log(' ✅ Context overflow page loaded');
|
|
|
|
// Sanity-check that the controller JS was extracted out of the
|
|
// template into its own deferred file. If someone re-inlines the
|
|
// IIFE later, the deferred-script ordering bug returns silently.
|
|
const externalScripts = await page.$$eval('script[defer][src]', els =>
|
|
els.map(s => s.getAttribute('src'))
|
|
);
|
|
expect(externalScripts).toContain('/static/js/components/context-overflow.js');
|
|
expect(externalScripts).toContain('/static/js/components/context-overflow-shared.js');
|
|
|
|
// Wait for loading to complete
|
|
console.log(' Waiting for data to load...');
|
|
await page.waitForFunction(
|
|
() => {
|
|
const loading = document.getElementById('loading');
|
|
const content = document.getElementById('content');
|
|
return loading && loading.style.display === 'none' &&
|
|
content && content.style.display !== 'none';
|
|
},
|
|
{ timeout: 15000 }
|
|
);
|
|
console.log(' ✅ Data loading complete');
|
|
|
|
// Check for main sections
|
|
const sections = await page.evaluate(() => {
|
|
const results = {
|
|
hasOverviewCards: false,
|
|
hasContextChart: false,
|
|
hasModelStats: false,
|
|
hasTruncatedList: false,
|
|
truncationRate: null,
|
|
avgTokensLost: null,
|
|
modelsTracked: null,
|
|
dataCoverage: null
|
|
};
|
|
|
|
// Check overview cards
|
|
const overviewCards = document.querySelector('.overflow-grid');
|
|
results.hasOverviewCards = !!overviewCards;
|
|
|
|
// Get metrics values
|
|
const truncationRate = document.getElementById('truncation-rate');
|
|
if (truncationRate) {
|
|
results.truncationRate = truncationRate.textContent.trim();
|
|
}
|
|
|
|
const avgTokensLost = document.getElementById('avg-tokens-lost');
|
|
if (avgTokensLost) {
|
|
results.avgTokensLost = avgTokensLost.textContent.trim();
|
|
}
|
|
|
|
const modelsTracked = document.getElementById('models-tracked');
|
|
if (modelsTracked) {
|
|
results.modelsTracked = modelsTracked.textContent.trim();
|
|
}
|
|
|
|
const dataCoverage = document.getElementById('data-coverage');
|
|
if (dataCoverage) {
|
|
results.dataCoverage = dataCoverage.textContent.trim();
|
|
}
|
|
|
|
// Check charts
|
|
const contextChart = document.getElementById('context-chart');
|
|
results.hasContextChart = !!contextChart;
|
|
|
|
// Check model stats section
|
|
const modelStats = document.getElementById('model-stats');
|
|
results.hasModelStats = !!modelStats;
|
|
|
|
// Check truncated list section
|
|
const truncatedList = document.getElementById('truncated-list');
|
|
results.hasTruncatedList = !!truncatedList;
|
|
|
|
return results;
|
|
});
|
|
|
|
console.log(' 📊 Dashboard sections found:');
|
|
console.log(` - Overview cards: ${sections.hasOverviewCards ? '✅' : '❌'}`);
|
|
console.log(` - Context chart: ${sections.hasContextChart ? '✅' : '❌'}`);
|
|
console.log(` - Model stats: ${sections.hasModelStats ? '✅' : '❌'}`);
|
|
console.log(` - Truncated list: ${sections.hasTruncatedList ? '✅' : '❌'}`);
|
|
|
|
console.log(' 📈 Metrics values:');
|
|
console.log(` - Truncation rate: ${sections.truncationRate}`);
|
|
console.log(` - Avg tokens lost: ${sections.avgTokensLost}`);
|
|
console.log(` - Models tracked: ${sections.modelsTracked}`);
|
|
console.log(` - Data coverage: ${sections.dataCoverage}`);
|
|
|
|
// Verify all main sections are present
|
|
expect(sections.hasOverviewCards).toBe(true);
|
|
expect(sections.hasContextChart).toBe(true);
|
|
expect(sections.hasModelStats).toBe(true);
|
|
expect(sections.hasTruncatedList).toBe(true);
|
|
|
|
// Verify metrics are displayed (even if 0)
|
|
expect(sections.truncationRate).not.toBeNull();
|
|
expect(sections.avgTokensLost).not.toBeNull();
|
|
expect(sections.modelsTracked).not.toBeNull();
|
|
expect(sections.dataCoverage).not.toBeNull();
|
|
});
|
|
|
|
test('Time range selector works', async () => {
|
|
console.log('🕐 Testing time range selector...');
|
|
|
|
// Login first
|
|
await authHelper.ensureAuthenticated();
|
|
|
|
// Navigate to context overflow page
|
|
await page.goto(`${BASE_URL}/metrics/context-overflow`, {
|
|
waitUntil: 'domcontentloaded',
|
|
timeout: 30000
|
|
});
|
|
|
|
// Wait for page to load
|
|
await page.waitForSelector('.time-range-selector', { timeout: 10000 });
|
|
|
|
// Get initial active period
|
|
const initialPeriod = await page.evaluate(() => {
|
|
const activeBtn = document.querySelector('.time-range-btn.active');
|
|
return activeBtn ? activeBtn.getAttribute('data-period') : null;
|
|
});
|
|
console.log(` Initial period: ${initialPeriod}`);
|
|
|
|
// Try clicking different time periods
|
|
const periods = ['7d', '30d', '3m', '1y', 'all'];
|
|
|
|
for (const period of periods) {
|
|
console.log(` Testing period: ${period}`);
|
|
|
|
// Click the time range button
|
|
await page.click(`[data-period="${period}"]`);
|
|
|
|
// Wait a moment for the request to start
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Verify the button is now active
|
|
const isActive = await page.evaluate((p) => {
|
|
const btn = document.querySelector(`[data-period="${p}"]`);
|
|
return btn && btn.classList.contains('active');
|
|
}, period);
|
|
|
|
expect(isActive).toBe(true);
|
|
console.log(` ✅ ${period} button activated`);
|
|
}
|
|
});
|
|
|
|
test('API endpoint returns data', async () => {
|
|
console.log('🔌 Testing API endpoint...');
|
|
|
|
// Login first
|
|
await authHelper.ensureAuthenticated();
|
|
|
|
// Get cookies for authenticated request
|
|
const cookies = await page.cookies();
|
|
const sessionCookie = cookies.find(c => c.name === 'session');
|
|
|
|
if (!sessionCookie) {
|
|
console.log(' ⚠️ No session cookie found');
|
|
return;
|
|
}
|
|
|
|
// Make API request
|
|
const response = await page.evaluate(async (baseUrl) => {
|
|
try {
|
|
const res = await fetch(`${baseUrl}/metrics/api/context-overflow?period=30d`, {
|
|
method: 'GET',
|
|
credentials: 'include',
|
|
headers: {
|
|
'Accept': 'application/json'
|
|
}
|
|
});
|
|
|
|
const data = await res.json();
|
|
return {
|
|
status: res.status,
|
|
ok: res.ok,
|
|
data
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
error: error.message
|
|
};
|
|
}
|
|
}, BASE_URL);
|
|
|
|
console.log(` API Response status: ${response.status}`);
|
|
console.log(` API Response OK: ${response.ok}`);
|
|
|
|
if (response.data) {
|
|
console.log(` API Response status field: ${response.data.status}`);
|
|
|
|
if (response.data.overview) {
|
|
console.log(' 📊 Overview data:');
|
|
console.log(` - Total requests: ${response.data.overview.total_requests}`);
|
|
console.log(` - Requests with context: ${response.data.overview.requests_with_context_data}`);
|
|
console.log(` - Truncated requests: ${response.data.overview.truncated_requests}`);
|
|
console.log(` - Truncation rate: ${response.data.overview.truncation_rate}%`);
|
|
}
|
|
|
|
if (response.data.model_stats) {
|
|
console.log(` 📊 Model stats count: ${response.data.model_stats.length}`);
|
|
}
|
|
|
|
if (response.data.context_limits) {
|
|
console.log(` 📊 Context limits count: ${response.data.context_limits.length}`);
|
|
}
|
|
|
|
if (response.data.chart_data) {
|
|
console.log(` 📊 Chart data points: ${response.data.chart_data.length}`);
|
|
}
|
|
}
|
|
|
|
// Verify response structure
|
|
expect(response.status).toBe(200);
|
|
expect(response.ok).toBe(true);
|
|
expect(response.data).toBeDefined();
|
|
expect(response.data.status).toBe('success');
|
|
expect(response.data.overview).toBeDefined();
|
|
});
|
|
});
|