oncall-engine/grafana-plugin/e2e-tests/utils/clients/grafana.ts
Matthew Thorning 051a344d7d
test: added test for the personal webhook (#5457)
Adds a test for the new personal webhooks functionality.

Relates to https://github.com/grafana/irm/issues/332
2025-02-20 08:45:16 +00:00

142 lines
4.4 KiB
TypeScript

import { OrgRole } from '@grafana/data';
import { expect, APIRequestContext, APIResponse } from '@playwright/test';
import { BASE_URL, GRAFANA_ADMIN_PASSWORD, GRAFANA_ADMIN_USERNAME } from '../constants';
type UsersLookupResponse = {
id: number;
};
type CreateUserResponse = {
id: number;
};
type GetSettingsResponse = {
buildInfo: {
version: string;
};
};
class GrafanaApiException extends Error {
constructor(message: string) {
super(message);
this.name = this.constructor.name;
}
}
class GrafanaAPIClient {
userName: string;
password: string;
constructor(userName: string, password: string) {
this.userName = userName;
this.password = password;
}
get requestHeaders() {
const base64encodedCredentials = Buffer.from(`${this.userName}:${this.password}`).toString('base64');
return {
Authorization: `Basic ${base64encodedCredentials}`,
};
}
/**
* check that the grafana instance is available. If HTTP 503 is returned it means the
* instance is currently unavailable. Poll until it is available
*/
pollInstanceUntilItIsHealthy = async (request: APIRequestContext): Promise<boolean> => {
console.log('Polling the grafana instance to make sure it is healthy');
const res = await request.get(`${BASE_URL}/api/health`);
if (!res.ok()) {
console.log(`Grafana instance is unavailable. Got HTTP ${res.status()}. Will wait 5 seconds and then try again`);
await new Promise((resolve) => setTimeout(resolve, 5000));
return this.pollInstanceUntilItIsHealthy(request);
}
console.log('Grafana instance is available');
return true;
};
getUserIdByUsername = async (request: APIRequestContext, userName: string): Promise<number> => {
const res = await request.get(`${BASE_URL}/api/users/lookup?loginOrEmail=${userName}`, {
headers: this.requestHeaders,
});
expect(res.ok()).toBeTruthy();
const responseData: UsersLookupResponse = await res.json();
return responseData.id;
};
updateUserRole = async (request: APIRequestContext, userId: number, role: OrgRole): Promise<void> => {
const res = await request.patch(`${BASE_URL}/api/org/users/${userId}`, {
data: { role },
headers: this.requestHeaders,
});
expect(res.ok()).toBeTruthy();
};
/**
* Should return one of the following two responses:
* - HTTP 200 - user successfully created
* - HTTP 412 - user w/ this username already exists (fine to ignore this)
*/
idempotentlyCreateUserWithRole = async (
request: APIRequestContext,
userName: string,
password: string,
role: OrgRole
) => {
const res = await request.post(`${BASE_URL}/api/admin/users`, {
data: {
name: `e2e user - ${userName}`,
login: userName,
password,
},
});
let userId: number;
const responseCode = res.status();
if (responseCode === 200) {
// user was just created
const respJson: CreateUserResponse = await res.json();
userId = respJson.id;
} else if (responseCode === 412) {
// user already exists, go fetch their user id
userId = await this.getUserIdByUsername(request, userName);
} else {
throw new GrafanaApiException(
`Received unexpected status code while trying to idempotently create user - HTTP${responseCode}: ${await res.body()}`
);
}
await this.updateUserRole(request, userId, role);
};
login = async (request: APIRequestContext, userName: string, password: string) => {
const res = await request.post(`${BASE_URL}/login`, {
data: { user: userName, password },
});
expect(res.ok()).toBeTruthy();
};
// https://grafana.com/docs/grafana/latest/developers/http_api/other/#get-settings
getGrafanaVersion = async (request: APIRequestContext): Promise<string> => {
const res = await request.get(`${BASE_URL}/api/frontend/settings`);
expect(res.ok()).toBeTruthy();
const data: GetSettingsResponse = await res.json();
return data.buildInfo.version;
};
makeRequest = async (request: APIRequestContext, path: string, method: 'get' | 'post' | 'put' | 'delete' = 'post'): Promise<APIResponse> => {
const res = await request[method](`${BASE_URL}/api/plugins/grafana-oncall-app/${path.replace(/^\//, '')}`, {
headers: this.requestHeaders,
});
expect(res.ok()).toBeTruthy();
return res;
}
}
const grafanaAPIClient = new GrafanaAPIClient(GRAFANA_ADMIN_USERNAME, GRAFANA_ADMIN_PASSWORD);
export default grafanaAPIClient;