Skip to content

Commit

Permalink
e2e updated
Browse files Browse the repository at this point in the history
  • Loading branch information
vitPinchuk committed Nov 8, 2024
1 parent eea576c commit acf7665
Show file tree
Hide file tree
Showing 13 changed files with 967 additions and 22 deletions.
738 changes: 727 additions & 11 deletions provisioning/dashboards/e2e.json

Large diffs are not rendered by default.

157 changes: 146 additions & 11 deletions test/panel.spec.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,165 @@
import { test, expect } from '@grafana/plugin-e2e';
import { TEST_IDS } from '../src/constants/tests';
import { PanelHelper } from './utils';

test.describe('Business Charts Panel', () => {
test('Check grafana version', async ({ grafanaVersion }) => {
console.log('Grafana version: ', grafanaVersion);
expect(grafanaVersion).toEqual(grafanaVersion);
});

test('should display empty chart without data and Bar Chart', async ({ gotoDashboardPage, dashboardPage }) => {
test('Should add empty default chart', async ({ readProvisionedDashboard, gotoDashboardPage }) => {
/**
* Go To E2E dashboard
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
await gotoDashboardPage({ uid: 'fdd5dbe3-794c-4441-9d1c-024a537bbe99' });
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Find panel by title with chart
* Should be visible
* Add new visualization
*/
await expect(dashboardPage.getPanelByTitle('Bar Chart').locator).toBeVisible();
const editPage = await dashboardPage.addPanel();
await editPage.setVisualization('Business Charts');
await editPage.setPanelTitle('Business Chart Test');
await editPage.backToDashboard();

/**
* Check and compare image
* Should add empty visualization without errors
*/
await expect(dashboardPage.getPanelByTitle('Bar Chart').locator.getByTestId(TEST_IDS.panel.chart)).toHaveScreenshot(
'actual-screenshot.png'
);
const panel = new PanelHelper(dashboardPage, 'Business Chart Test');
await panel.checkIfNoErrors();
await panel.checkPresence();

await panel.compareScreenshot('empty.png');
});

test('Should display error message', async ({ readProvisionedDashboard, gotoDashboardPage }) => {
/**
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Check Presence
*/
const panel = new PanelHelper(dashboardPage, 'Error panel');

await panel.checkIfNoErrors();
await panel.checkPresence();
await panel.checkAlert();
});

test.describe('Chart types', () => {
test('Should display Line Chart', async ({ gotoDashboardPage, readProvisionedDashboard }) => {
/**
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Check Presence
*/
const panel = new PanelHelper(dashboardPage, 'Line Chart (code editor)');

await panel.checkIfNoErrors();
await panel.checkPresence();
await panel.compareScreenshot('line-screenshot.png');
});

test('Should display Radar Chart', async ({ gotoDashboardPage, readProvisionedDashboard }) => {
/**
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Check Presence
*/
const panel = new PanelHelper(dashboardPage, 'Radar Chart (visual editor)');

await panel.checkIfNoErrors();
await panel.checkPresence();
await panel.compareScreenshot('radar-screenshot.png');
});

test('Should display Bar Chart', async ({ gotoDashboardPage, readProvisionedDashboard }) => {
/**
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Check Presence
*/
const panel = new PanelHelper(dashboardPage, 'Bar Chart (code editor)');

await panel.checkIfNoErrors();
await panel.checkPresence();
await panel.compareScreenshot('bar-screenshot.png');
});

test('Should display Boxplot Chart', async ({ gotoDashboardPage, readProvisionedDashboard }) => {
/**
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Check Presence
*/
const panel = new PanelHelper(dashboardPage, 'Boxplot (visual editor)');

await panel.checkIfNoErrors();
await panel.checkPresence();
await panel.compareScreenshot('boxplot-screenshot.png');
});

test('Should display Boxplot Chart code editor', async ({ gotoDashboardPage, readProvisionedDashboard }) => {
/**
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Check Presence
*/
const panel = new PanelHelper(dashboardPage, 'Boxplot (code editor)');

await panel.checkIfNoErrors();
await panel.checkPresence();
await panel.compareScreenshot('boxplot-code-screenshot.png');
});

test('Should display Scatter Chart ', async ({ gotoDashboardPage, readProvisionedDashboard, page }) => {
/**
* Go To Panels dashboard e2e.json
* return dashboardPage
*/
const dashboard = await readProvisionedDashboard({ fileName: 'e2e.json' });
const dashboardPage = await gotoDashboardPage({ uid: dashboard.uid });

/**
* Check Presence
*/
const panel = new PanelHelper(dashboardPage, 'Scatter');

await page.waitForTimeout(500);

await panel.checkIfNoErrors();
await panel.checkPresence();
await panel.compareScreenshot('scatter-screenshot.png');
});
});
});
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions test/utils/charts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Locator } from '@playwright/test';
import { DashboardPage, expect, Panel } from '@grafana/plugin-e2e';
import { TEST_IDS } from '../../src/constants/tests';
import { getLocatorSelectors, LocatorSelectors } from './selectors';

/**
* Panel Helper
*/
export class PanelHelper {
private readonly locator: Locator;
private readonly panel: Panel;
private readonly title: string;
private readonly selectors: LocatorSelectors<typeof TEST_IDS.panel>;

constructor(dashboardPage: DashboardPage, panelTitle: string) {
this.panel = dashboardPage.getPanelByTitle(panelTitle);
this.title = panelTitle;
this.locator = this.panel.locator;
this.selectors = getLocatorSelectors(TEST_IDS.panel)(this.locator);
}

private getMsg(msg: string): string {
return `Panel: ${msg}`;
}

public async checkIfNoErrors() {
return expect(this.panel.getErrorIcon(), this.getMsg('Check If No Errors')).not.toBeVisible();
}

public async checkPresence() {
return expect(this.selectors.chart(), this.getMsg(`Check ${this.title} Presence`)).toBeVisible();
}

public async compareScreenshot(name: string) {
return expect(this.selectors.chart(), this.getMsg(`Check ${this.title} Screenshot`)).toHaveScreenshot(name);
}

public async checkAlert() {
return expect(this.selectors.error(), this.getMsg(`Check ${this.title} Alert`)).toBeVisible();
}
}
2 changes: 2 additions & 0 deletions test/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './selectors';
export * from './charts';
51 changes: 51 additions & 0 deletions test/utils/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Locator } from '@playwright/test';

/**
* Selector
*/
type LocatorSelector<TArgs extends unknown[]> = (...args: TArgs) => ReturnType<() => Locator>;

/**
* Check If Selector Object
*/
type IsSelectorObject<TCandidate> = TCandidate extends {
selector: (...args: unknown[]) => void;
apply: (...args: unknown[]) => void;
}
? TCandidate & { selector: TCandidate['selector']; apply: TCandidate['apply'] }
: never;

/**
* Selectors
*/
export type LocatorSelectors<T> = {
[K in keyof T]: T[K] extends (...args: infer Args) => void
? LocatorSelector<Args>
: T[K] extends IsSelectorObject<T[K]>
? LocatorSelector<Parameters<T[K]['selector']>>
: LocatorSelector<[]>;
};

export const getLocatorSelectors =
<TSelectors extends Record<keyof TSelectors, TSelectors[keyof TSelectors]>>(
selectors: TSelectors
): ((locator: Locator) => LocatorSelectors<TSelectors>) =>
(locator) => {
return Object.entries(selectors).reduce((acc, [key, selector]) => {
const getElement = (...args: unknown[]): Locator => {
const getValue = typeof selector === 'object' && 'selector' in selector! ? selector.selector : selector;
const value = typeof getValue === 'function' ? getValue(...args) : getValue;

if (value.startsWith('data-testid')) {
return locator.getByTestId(value);
}

return locator.getByLabel(value);
};

return {
...acc,
[key]: getElement,
};
}, {} as LocatorSelectors<TSelectors>);
};

0 comments on commit acf7665

Please sign in to comment.