@grafana/plugin-e2e 3.5.1 → 3.6.0-canary.2586.24780926778.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts
CHANGED
|
@@ -193,6 +193,17 @@ declare class Panel extends GrafanaPage {
|
|
|
193
193
|
clickOnMenuItem(item: string, options?: {
|
|
194
194
|
parentItem?: string;
|
|
195
195
|
}): Promise<void>;
|
|
196
|
+
/**
|
|
197
|
+
* Scrolls the panel into the viewport, triggering its query if not yet started.
|
|
198
|
+
*
|
|
199
|
+
* In Grafana 13.x+ with scenes, panels are lazy-rendered: the panel element does not
|
|
200
|
+
* exist in the DOM until its grid container enters the viewport. This method scrolls
|
|
201
|
+
* `.react-grid-item` containers progressively until the panel element appears, then
|
|
202
|
+
* scrolls the panel element precisely into view. In older Grafana versions the panel
|
|
203
|
+
* element is always in the DOM, so the loop exits early and delegates to the standard
|
|
204
|
+
* scroll path.
|
|
205
|
+
*/
|
|
206
|
+
scrollIntoView(): Promise<void>;
|
|
196
207
|
/**
|
|
197
208
|
* Returns the locator for the panel error (if any)
|
|
198
209
|
*/
|
|
@@ -342,11 +353,31 @@ declare class DashboardPage extends GrafanaPage {
|
|
|
342
353
|
readonly dashboard?: DashboardPageArgs | undefined;
|
|
343
354
|
dataSourcePicker: any;
|
|
344
355
|
timeRange: TimeRange;
|
|
356
|
+
private pendingQueryCount;
|
|
357
|
+
private hasSeenQuery;
|
|
345
358
|
constructor(ctx: PluginTestCtx, dashboard?: DashboardPageArgs | undefined);
|
|
346
359
|
/**
|
|
347
360
|
* Navigates to the dashboard page. If a dashboard uid was not provided, it's assumed that it's a new dashboard.
|
|
348
361
|
*/
|
|
349
362
|
goto(options?: NavigateOptions): Promise<void>;
|
|
363
|
+
/**
|
|
364
|
+
* Scrolls each panel container into view so that below-fold panels have their queries triggered.
|
|
365
|
+
* Targets .react-grid-item containers (always in the DOM, even before VizPanel renders) rather
|
|
366
|
+
* than panel title/content elements which only exist after lazy rendering. Playwright's native
|
|
367
|
+
* scrollIntoViewIfNeeded finds the correct scroll container automatically across Grafana versions.
|
|
368
|
+
*/
|
|
369
|
+
private scrollToRevealAllPanels;
|
|
370
|
+
/**
|
|
371
|
+
* Waits until all initiated panel queries have received responses.
|
|
372
|
+
*
|
|
373
|
+
* By default only waits for queries already triggered (panels in the viewport at navigation
|
|
374
|
+
* time or explicitly scrolled into view). Pass `scrollAll: true` to first scroll the full
|
|
375
|
+
* dashboard so that below-fold panels are also triggered before waiting.
|
|
376
|
+
*/
|
|
377
|
+
waitForPanelsQueriesToComplete({ timeout, scrollAll, }?: {
|
|
378
|
+
timeout?: number;
|
|
379
|
+
scrollAll?: boolean;
|
|
380
|
+
}): Promise<void>;
|
|
350
381
|
/**
|
|
351
382
|
* Navigates to the panel edit page for the given panel id
|
|
352
383
|
*
|
|
@@ -1384,6 +1415,10 @@ declare const expect: _playwright_test.Expect<{
|
|
|
1384
1415
|
toHaveChecked: typeof toHaveChecked;
|
|
1385
1416
|
toHaveColor: typeof toHaveColor;
|
|
1386
1417
|
toHaveNoA11yViolations: typeof toHaveNoA11yViolations;
|
|
1418
|
+
toHavePanelErrors: (dashboard: DashboardPage, expectedCount?: number) => Promise<{
|
|
1419
|
+
pass: boolean;
|
|
1420
|
+
message: () => string;
|
|
1421
|
+
}>;
|
|
1387
1422
|
}>;
|
|
1388
1423
|
|
|
1389
1424
|
declare global {
|
|
@@ -1456,6 +1491,12 @@ declare global {
|
|
|
1456
1491
|
* You can use this in conjunction with the .toHaveNoA11yViolations matcher to assert that there are no accessibility violations on the page.
|
|
1457
1492
|
*/
|
|
1458
1493
|
toHaveNoA11yViolations(results: AxeResults, options?: A11yViolationsOptions): Promise<R>;
|
|
1494
|
+
/**
|
|
1495
|
+
* Asserts that a dashboard has panel errors. Omit `count` to assert at least one error.
|
|
1496
|
+
* Pass `count` to assert exactly that many panels with errors.
|
|
1497
|
+
* Use `.not.toHavePanelErrors()` to assert no panel errors.
|
|
1498
|
+
*/
|
|
1499
|
+
toHavePanelErrors(this: Matchers<unknown, DashboardPage>, count?: number): Promise<R>;
|
|
1459
1500
|
}
|
|
1460
1501
|
}
|
|
1461
1502
|
}
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,7 @@ var toBeChecked = require('./matchers/toBeChecked.js');
|
|
|
42
42
|
var toHaveNoA11yViolations = require('./matchers/toHaveNoA11yViolations.js');
|
|
43
43
|
var toHaveChecked = require('./matchers/toHaveChecked.js');
|
|
44
44
|
var toHaveColor = require('./matchers/toHaveColor.js');
|
|
45
|
+
var toHavePanelErrors = require('./matchers/toHavePanelErrors.js');
|
|
45
46
|
var DataSourcePicker = require('./models/components/DataSourcePicker.js');
|
|
46
47
|
var Panel = require('./models/components/Panel.js');
|
|
47
48
|
var TimeRange = require('./models/components/TimeRange.js');
|
|
@@ -104,7 +105,8 @@ const expect = test$1.expect.extend({
|
|
|
104
105
|
toBeChecked: toBeChecked.toBeChecked,
|
|
105
106
|
toHaveChecked: toHaveChecked.toHaveChecked,
|
|
106
107
|
toHaveColor: toHaveColor.toHaveColor,
|
|
107
|
-
toHaveNoA11yViolations: toHaveNoA11yViolations.toHaveNoA11yViolations
|
|
108
|
+
toHaveNoA11yViolations: toHaveNoA11yViolations.toHaveNoA11yViolations,
|
|
109
|
+
toHavePanelErrors: toHavePanelErrors.toHavePanelErrors
|
|
108
110
|
});
|
|
109
111
|
|
|
110
112
|
Object.defineProperty(exports, "selectors", {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const toHavePanelErrors = async (dashboard, expectedCount) => {
|
|
4
|
+
const errorLocator = dashboard.getByGrafanaSelector(dashboard.ctx.selectors.components.Panels.Panel.status("error"));
|
|
5
|
+
const count = await errorLocator.count();
|
|
6
|
+
const pass = expectedCount === void 0 ? count >= 1 : count === expectedCount;
|
|
7
|
+
return {
|
|
8
|
+
pass,
|
|
9
|
+
message: () => expectedCount === void 0 ? `Expected at least 1 panel with errors but found ${count}` : `Expected exactly ${expectedCount} panel error(s) but found ${count}`
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
exports.toHavePanelErrors = toHavePanelErrors;
|
|
@@ -75,6 +75,31 @@ class Panel extends GrafanaPage.GrafanaPage {
|
|
|
75
75
|
options?.parentItem && await parentMenuItem.hover();
|
|
76
76
|
await menuItem.click();
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Scrolls the panel into the viewport, triggering its query if not yet started.
|
|
80
|
+
*
|
|
81
|
+
* In Grafana 13.x+ with scenes, panels are lazy-rendered: the panel element does not
|
|
82
|
+
* exist in the DOM until its grid container enters the viewport. This method scrolls
|
|
83
|
+
* `.react-grid-item` containers progressively until the panel element appears, then
|
|
84
|
+
* scrolls the panel element precisely into view. In older Grafana versions the panel
|
|
85
|
+
* element is always in the DOM, so the loop exits early and delegates to the standard
|
|
86
|
+
* scroll path.
|
|
87
|
+
*/
|
|
88
|
+
async scrollIntoView() {
|
|
89
|
+
if (await this.locator.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
90
|
+
await this.locator.scrollIntoViewIfNeeded();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const containers = this.ctx.page.locator(".react-grid-item");
|
|
94
|
+
const count = await containers.count();
|
|
95
|
+
for (let i = 0; i < count; i++) {
|
|
96
|
+
await containers.nth(i).scrollIntoViewIfNeeded();
|
|
97
|
+
if (await this.locator.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
await this.locator.scrollIntoViewIfNeeded();
|
|
102
|
+
}
|
|
78
103
|
/**
|
|
79
104
|
* Returns the locator for the panel error (if any)
|
|
80
105
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var semver = require('semver');
|
|
4
|
+
var test = require('@playwright/test');
|
|
4
5
|
var DataSourcePicker = require('../components/DataSourcePicker.js');
|
|
5
6
|
var GrafanaPage = require('./GrafanaPage.js');
|
|
6
7
|
var PanelEditPage = require('./PanelEditPage.js');
|
|
@@ -38,6 +39,8 @@ class DashboardPage extends GrafanaPage.GrafanaPage {
|
|
|
38
39
|
this.dashboard = dashboard;
|
|
39
40
|
__publicField(this, "dataSourcePicker");
|
|
40
41
|
__publicField(this, "timeRange");
|
|
42
|
+
__publicField(this, "pendingQueryCount", 0);
|
|
43
|
+
__publicField(this, "hasSeenQuery", false);
|
|
41
44
|
this.dataSourcePicker = new DataSourcePicker.DataSourcePicker(ctx);
|
|
42
45
|
this.timeRange = new TimeRange.TimeRange(ctx);
|
|
43
46
|
}
|
|
@@ -45,6 +48,17 @@ class DashboardPage extends GrafanaPage.GrafanaPage {
|
|
|
45
48
|
* Navigates to the dashboard page. If a dashboard uid was not provided, it's assumed that it's a new dashboard.
|
|
46
49
|
*/
|
|
47
50
|
async goto(options = {}) {
|
|
51
|
+
this.ctx.page.on("request", (req) => {
|
|
52
|
+
if (req.url().includes(this.ctx.selectors.apis.DataSource.query)) {
|
|
53
|
+
this.pendingQueryCount++;
|
|
54
|
+
this.hasSeenQuery = true;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
this.ctx.page.on("response", (res) => {
|
|
58
|
+
if (res.url().includes(this.ctx.selectors.apis.DataSource.query)) {
|
|
59
|
+
this.pendingQueryCount = Math.max(0, this.pendingQueryCount - 1);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
48
62
|
let url = this.dashboard?.uid ? this.ctx.selectors.pages.Dashboard.url(this.dashboard.uid) : this.ctx.selectors.pages.AddDashboard.url;
|
|
49
63
|
if (this.dashboard?.timeRange) {
|
|
50
64
|
options.queryParams = options?.queryParams ?? new URLSearchParams();
|
|
@@ -53,6 +67,39 @@ class DashboardPage extends GrafanaPage.GrafanaPage {
|
|
|
53
67
|
}
|
|
54
68
|
return super.navigate(url, options);
|
|
55
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Scrolls each panel container into view so that below-fold panels have their queries triggered.
|
|
72
|
+
* Targets .react-grid-item containers (always in the DOM, even before VizPanel renders) rather
|
|
73
|
+
* than panel title/content elements which only exist after lazy rendering. Playwright's native
|
|
74
|
+
* scrollIntoViewIfNeeded finds the correct scroll container automatically across Grafana versions.
|
|
75
|
+
*/
|
|
76
|
+
async scrollToRevealAllPanels() {
|
|
77
|
+
const containers = this.ctx.page.locator(".react-grid-item");
|
|
78
|
+
const count = await containers.count();
|
|
79
|
+
for (let i = 0; i < count; i++) {
|
|
80
|
+
await containers.nth(i).scrollIntoViewIfNeeded();
|
|
81
|
+
await this.ctx.page.waitForTimeout(500);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Waits until all initiated panel queries have received responses.
|
|
86
|
+
*
|
|
87
|
+
* By default only waits for queries already triggered (panels in the viewport at navigation
|
|
88
|
+
* time or explicitly scrolled into view). Pass `scrollAll: true` to first scroll the full
|
|
89
|
+
* dashboard so that below-fold panels are also triggered before waiting.
|
|
90
|
+
*/
|
|
91
|
+
async waitForPanelsQueriesToComplete({
|
|
92
|
+
timeout = 3e4,
|
|
93
|
+
scrollAll = false
|
|
94
|
+
} = {}) {
|
|
95
|
+
await test.expect.poll(() => this.hasSeenQuery, { timeout: 2e3 }).toBe(true).catch(() => {
|
|
96
|
+
});
|
|
97
|
+
await test.expect.poll(() => this.pendingQueryCount === 0, { timeout }).toBe(true);
|
|
98
|
+
if (scrollAll) {
|
|
99
|
+
await this.scrollToRevealAllPanels();
|
|
100
|
+
await test.expect.poll(() => this.pendingQueryCount === 0, { timeout }).toBe(true);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
56
103
|
/**
|
|
57
104
|
* Navigates to the panel edit page for the given panel id
|
|
58
105
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafana/plugin-e2e",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0-canary.2586.24780926778.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"uuid": "^13.0.0",
|
|
55
55
|
"yaml": "^2.3.4"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "e6e583d77ad8805571c805d035d49d06c6b2f823"
|
|
58
58
|
}
|