2023-11-17 11:07:12 +01:00
|
|
|
import { OrgRole } from '@grafana/data';
|
2023-07-04 11:19:14 +02:00
|
|
|
import { test as setup, chromium, expect, Page, BrowserContext, FullConfig, APIRequestContext } from '@playwright/test';
|
|
|
|
|
|
2023-12-15 09:58:25 +01:00
|
|
|
import { getOnCallApiUrl } from 'utils/consts';
|
|
|
|
|
|
2023-11-17 11:07:12 +01:00
|
|
|
import { VIEWER_USER_STORAGE_STATE, EDITOR_USER_STORAGE_STATE, ADMIN_USER_STORAGE_STATE } from '../playwright.config';
|
|
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
import GrafanaAPIClient from './utils/clients/grafana';
|
|
|
|
|
import {
|
|
|
|
|
GRAFANA_ADMIN_PASSWORD,
|
|
|
|
|
GRAFANA_ADMIN_USERNAME,
|
|
|
|
|
GRAFANA_EDITOR_PASSWORD,
|
|
|
|
|
GRAFANA_EDITOR_USERNAME,
|
|
|
|
|
GRAFANA_VIEWER_PASSWORD,
|
|
|
|
|
GRAFANA_VIEWER_USERNAME,
|
|
|
|
|
IS_CLOUD,
|
|
|
|
|
IS_OPEN_SOURCE,
|
|
|
|
|
} from './utils/constants';
|
2023-03-28 09:34:03 +02:00
|
|
|
import { clickButton, getInputByName } from './utils/forms';
|
|
|
|
|
import { goToGrafanaPage } from './utils/navigation';
|
|
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
const grafanaApiClient = new GrafanaAPIClient(GRAFANA_ADMIN_USERNAME, GRAFANA_ADMIN_PASSWORD);
|
2023-05-23 20:20:46 -04:00
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
type UserCreationSettings = {
|
|
|
|
|
adminAuthedRequest: APIRequestContext;
|
|
|
|
|
role: OrgRole;
|
|
|
|
|
};
|
2023-06-29 12:48:23 +02:00
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
const generateLoginStorageStateAndOptionallCreateUser = async (
|
|
|
|
|
config: FullConfig,
|
|
|
|
|
userName: string,
|
|
|
|
|
password: string,
|
|
|
|
|
storageStateFileLocation: string,
|
|
|
|
|
userCreationSettings?: UserCreationSettings,
|
|
|
|
|
closeContext = false
|
|
|
|
|
): Promise<BrowserContext> => {
|
|
|
|
|
if (userCreationSettings !== undefined && IS_OPEN_SOURCE) {
|
|
|
|
|
const { adminAuthedRequest, role } = userCreationSettings;
|
|
|
|
|
await grafanaApiClient.idempotentlyCreateUserWithRole(adminAuthedRequest, userName, password, role);
|
|
|
|
|
}
|
2023-06-29 12:48:23 +02:00
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
const { headless } = config.projects[0]!.use;
|
|
|
|
|
const browser = await chromium.launch({ headless, slowMo: headless ? 0 : 100 });
|
|
|
|
|
const browserContext = await browser.newContext();
|
2023-06-29 12:48:23 +02:00
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
await grafanaApiClient.login(browserContext.request, userName, password);
|
|
|
|
|
await browserContext.storageState({ path: storageStateFileLocation });
|
|
|
|
|
|
|
|
|
|
if (closeContext) {
|
|
|
|
|
await browserContext.close();
|
2023-06-29 12:48:23 +02:00
|
|
|
}
|
2023-07-04 11:19:14 +02:00
|
|
|
return browserContext;
|
2023-06-29 12:48:23 +02:00
|
|
|
};
|
|
|
|
|
|
2023-03-28 09:34:03 +02:00
|
|
|
/**
|
2023-07-04 11:19:14 +02:00
|
|
|
go to config page and wait for plugin icon to be available on left-hand navigation
|
2023-03-28 09:34:03 +02:00
|
|
|
*/
|
2023-05-23 17:26:12 -04:00
|
|
|
const configureOnCallPlugin = async (page: Page): Promise<void> => {
|
2023-03-28 09:34:03 +02:00
|
|
|
/**
|
|
|
|
|
* go to the oncall plugin configuration page and wait for the page to be loaded
|
|
|
|
|
*/
|
|
|
|
|
await goToGrafanaPage(page, '/plugins/grafana-oncall-app');
|
2023-12-15 09:58:25 +01:00
|
|
|
await page.waitForTimeout(2000);
|
2023-03-28 09:34:03 +02:00
|
|
|
|
2023-12-15 09:58:25 +01:00
|
|
|
// if plugin is configured, go to OnCall
|
|
|
|
|
const isConfigured = (await page.getByText('Connected to OnCall').count()) >= 1;
|
|
|
|
|
if (isConfigured) {
|
|
|
|
|
await page.getByRole('link', { name: 'Open Grafana OnCall' }).click();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-03-28 09:34:03 +02:00
|
|
|
|
2023-12-15 09:58:25 +01:00
|
|
|
// otherwise we may need to reconfigure the plugin
|
|
|
|
|
const needToReconfigure = (await page.getByText('try removing your plugin configuration').count()) >= 1;
|
|
|
|
|
if (needToReconfigure) {
|
|
|
|
|
await clickButton({ page, buttonText: 'Remove current configuration' });
|
|
|
|
|
await clickButton({ page, buttonText: /^Remove$/ });
|
|
|
|
|
}
|
|
|
|
|
await page.waitForTimeout(2000);
|
|
|
|
|
|
|
|
|
|
const needToEnterOnCallApiUrl = await page.getByText(/Connected to OnCall/).isHidden();
|
|
|
|
|
if (needToEnterOnCallApiUrl) {
|
|
|
|
|
await getInputByName(page, 'onCallApiUrl').fill(getOnCallApiUrl() || 'http://oncall-dev-engine:8080');
|
2023-03-28 09:34:03 +02:00
|
|
|
await clickButton({ page, buttonText: 'Connect' });
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-23 17:26:12 -04:00
|
|
|
/**
|
|
|
|
|
* wait for the "Connected to OnCall" message to know that everything is properly configured
|
|
|
|
|
*
|
|
|
|
|
* Regarding increasing the timeout for the "plugin configured" assertion:
|
|
|
|
|
* This is because it can sometimes take a bit longer for the backend sync to finish. The default assertion
|
|
|
|
|
* timeout is 5s, which is sometimes not enough if the backend is under load
|
|
|
|
|
*/
|
|
|
|
|
await expect(page.getByTestId('status-message-block')).toHaveText(/Connected to OnCall.*/, { timeout: 25_000 });
|
2023-03-28 09:34:03 +02:00
|
|
|
};
|
2023-03-10 06:45:15 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Borrowed from our friends on the Incident team
|
|
|
|
|
* https://github.com/grafana/incident/blob/main/plugin/e2e/global-setup.ts
|
|
|
|
|
*/
|
2023-07-04 11:19:14 +02:00
|
|
|
setup('Configure Grafana OnCall plugin', async ({ request }, { config }) => {
|
2023-06-29 12:48:23 +02:00
|
|
|
if (IS_CLOUD) {
|
2023-07-04 11:19:14 +02:00
|
|
|
await grafanaApiClient.pollInstanceUntilItIsHealthy(request);
|
2023-06-29 12:48:23 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
const adminBrowserContext = await generateLoginStorageStateAndOptionallCreateUser(
|
|
|
|
|
config,
|
|
|
|
|
GRAFANA_ADMIN_USERNAME,
|
|
|
|
|
GRAFANA_ADMIN_PASSWORD,
|
|
|
|
|
ADMIN_USER_STORAGE_STATE
|
|
|
|
|
);
|
|
|
|
|
const adminPage = await adminBrowserContext.newPage();
|
|
|
|
|
const { request: adminAuthedRequest } = adminBrowserContext;
|
|
|
|
|
|
|
|
|
|
await generateLoginStorageStateAndOptionallCreateUser(
|
|
|
|
|
config,
|
|
|
|
|
GRAFANA_EDITOR_USERNAME,
|
|
|
|
|
GRAFANA_EDITOR_PASSWORD,
|
|
|
|
|
EDITOR_USER_STORAGE_STATE,
|
|
|
|
|
{
|
|
|
|
|
adminAuthedRequest,
|
|
|
|
|
role: OrgRole.Editor,
|
|
|
|
|
},
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await generateLoginStorageStateAndOptionallCreateUser(
|
|
|
|
|
config,
|
|
|
|
|
GRAFANA_VIEWER_USERNAME,
|
|
|
|
|
GRAFANA_VIEWER_PASSWORD,
|
|
|
|
|
VIEWER_USER_STORAGE_STATE,
|
|
|
|
|
{
|
|
|
|
|
adminAuthedRequest,
|
|
|
|
|
role: OrgRole.Viewer,
|
|
|
|
|
},
|
|
|
|
|
true
|
|
|
|
|
);
|
2023-06-29 12:48:23 +02:00
|
|
|
|
|
|
|
|
if (IS_OPEN_SOURCE) {
|
|
|
|
|
// plugin configuration can safely be skipped for cloud environments
|
2023-07-04 11:19:14 +02:00
|
|
|
await configureOnCallPlugin(adminPage);
|
2023-05-23 20:20:46 -04:00
|
|
|
}
|
2023-06-29 12:48:23 +02:00
|
|
|
|
2023-07-04 11:19:14 +02:00
|
|
|
await adminBrowserContext.close();
|
2023-06-29 12:48:23 +02:00
|
|
|
});
|