grafana/e2e-playwright/dashboard-cujs/utils.ts

138 lines
3.7 KiB
TypeScript

import { Page } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
const USE_LIVE_DATA = Boolean(process.env.API_CONFIG_PATH);
const API_CONFIG_PATH = process.env.API_CONFIG_PATH ?? '../dashboards/cujs/config.json';
const RELOADABLE_DASHBOARD_REQUEST_NO = 2;
async function loadApiConfig() {
const configPath = path.resolve(__dirname, API_CONFIG_PATH);
if (configPath.endsWith('.json')) {
const configContent = await fs.promises.readFile(configPath, 'utf-8');
return JSON.parse(configContent);
} else {
const apiConfigModule = await import(configPath);
return apiConfigModule.default || apiConfigModule;
}
}
export async function getConfigDashboards() {
const config = await loadApiConfig();
return config.dashboards || [];
}
export async function prepareAPIMocks(page: Page) {
const apiConfig = await loadApiConfig();
if (USE_LIVE_DATA) {
return apiConfig;
}
const keys = Object.keys(apiConfig);
if (keys.includes('labels')) {
// mock the API call to get the labels
const labels = ['asserts_env', 'cluster', 'job'];
await page.route(apiConfig.labels, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
status: 'success',
data: labels,
}),
});
});
}
if (keys.includes('values')) {
// mock the API call to get the values
const values = ['value1', 'value2', 'test1', 'test2'];
await page.route(apiConfig.values, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
status: 'success',
data: values,
}),
});
});
}
return apiConfig;
}
interface DashboardRequest {
url: string;
timestamp: number;
response: { metadata: { annotations: string[] } };
}
export async function trackDashboardReloadRequests(page: Page): Promise<{
getRequests: () => DashboardRequest[];
waitForExpectedRequests: () => Promise<void>;
}> {
const dashboardRequests: DashboardRequest[] = [];
let resolveWhenComplete: () => void;
let expectedRequestCount = 1; //initial request that gives us the meta param
const completionPromise = new Promise<void>((resolve) => {
resolveWhenComplete = resolve;
});
const handler = async (route) => {
const response = await route.fetch();
const responseJson = await response.json();
const isFirstRequest = dashboardRequests.length === 0;
dashboardRequests.push({
url: route.request().url(),
timestamp: Date.now(),
response: responseJson,
});
// After first request, check if we should expect more
if (isFirstRequest) {
const hasReloadAnnotation = responseJson?.metadata?.annotations?.['grafana.app/reloadOnParamsChange'] === 'true';
if (hasReloadAnnotation) {
expectedRequestCount = RELOADABLE_DASHBOARD_REQUEST_NO;
}
}
// Resolve if we've reached the expected count
if (dashboardRequests.length >= expectedRequestCount) {
resolveWhenComplete();
}
await route.fulfill({ response });
};
await page.route('**/dashboards/**/dto?**', handler);
return {
getRequests: () => dashboardRequests,
waitForExpectedRequests: () => completionPromise,
};
}
export function checkDashboardReloadBehavior(requests: DashboardRequest[]): boolean {
if (requests.length === 0) {
return false;
}
const firstRequest = requests[0];
const hasReloadAnnotation =
firstRequest?.response?.metadata?.annotations?.['grafana.app/reloadOnParamsChange'] === 'true';
if (hasReloadAnnotation) {
return requests.length === RELOADABLE_DASHBOARD_REQUEST_NO;
} else {
return requests.length === 1;
}
}