@grafana/plugin-e2e 3.1.3 → 3.2.0-canary.2408.21202715809.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/fixtures/bootData.js +25 -0
- package/dist/fixtures/grafanaVersion.js +3 -7
- package/dist/fixtures/namespace.js +7 -0
- package/dist/fixtures/page.js +84 -2
- package/dist/index.d.ts +68 -18
- package/dist/index.js +7 -1
- package/dist/options.js +1 -0
- package/dist/selectors/versionedAPIs.js +14 -0
- package/package.json +2 -2
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const bootData = async ({ context }, use) => {
|
|
4
|
+
const tempPage = await context.newPage();
|
|
5
|
+
try {
|
|
6
|
+
await tempPage.goto("/");
|
|
7
|
+
const bootDataSettings = await tempPage.evaluate(() => {
|
|
8
|
+
return {
|
|
9
|
+
version: window.grafanaBootData.settings.buildInfo.version,
|
|
10
|
+
namespace: window.grafanaBootData.settings.namespace
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
await use({
|
|
14
|
+
version: bootDataSettings.version,
|
|
15
|
+
namespace: bootDataSettings.namespace
|
|
16
|
+
});
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error("@grafana/plugin-e2e: Failed to fetch boot data", error);
|
|
19
|
+
await use({ version: void 0, namespace: void 0 });
|
|
20
|
+
} finally {
|
|
21
|
+
await tempPage.close();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
exports.bootData = bootData;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const grafanaVersion = async ({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
await page.goto("/");
|
|
7
|
-
grafanaVersion2 = await page.evaluate("window.grafanaBootData.settings.buildInfo.version");
|
|
8
|
-
}
|
|
9
|
-
await use(grafanaVersion2.replace(/\-.*/, ""));
|
|
3
|
+
const grafanaVersion = async ({ bootData }, use) => {
|
|
4
|
+
const version = process.env.GRAFANA_VERSION || bootData.version || "";
|
|
5
|
+
await use(version.replace(/\-.*/, ""));
|
|
10
6
|
};
|
|
11
7
|
|
|
12
8
|
exports.grafanaVersion = grafanaVersion;
|
package/dist/fixtures/page.js
CHANGED
|
@@ -2,14 +2,96 @@
|
|
|
2
2
|
|
|
3
3
|
var overrideGrafanaBootData = require('./scripts/overrideGrafanaBootData.js');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
function delay(ms) {
|
|
6
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7
|
+
}
|
|
8
|
+
async function handleBulkEvaluationRoute(route, featureToggles, latency) {
|
|
9
|
+
try {
|
|
10
|
+
const response = await route.fetch();
|
|
11
|
+
if (!response.ok()) {
|
|
12
|
+
await route.fulfill({ response });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const body = await response.json();
|
|
16
|
+
for (const flag of body.flags) {
|
|
17
|
+
if (flag.key in featureToggles) {
|
|
18
|
+
flag.value = featureToggles[flag.key];
|
|
19
|
+
flag.reason = "STATIC";
|
|
20
|
+
flag.variant = "playwright-override";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const [key, value] of Object.entries(featureToggles)) {
|
|
24
|
+
const exists = body.flags.some((f) => f.key === key);
|
|
25
|
+
if (!exists) {
|
|
26
|
+
body.flags.push({
|
|
27
|
+
key,
|
|
28
|
+
value,
|
|
29
|
+
reason: "STATIC",
|
|
30
|
+
variant: "playwright-override"
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (latency > 0) {
|
|
35
|
+
await delay(latency);
|
|
36
|
+
}
|
|
37
|
+
await route.fulfill({
|
|
38
|
+
response,
|
|
39
|
+
body: JSON.stringify(body),
|
|
40
|
+
headers: { "content-type": "application/json" }
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error("@grafana/plugin-e2e: Failed to intercept OFREP bulk evaluation", error);
|
|
44
|
+
await route.continue();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function handleSingleFlagRoute(route, featureToggles, latency) {
|
|
48
|
+
try {
|
|
49
|
+
const url = new URL(route.request().url());
|
|
50
|
+
const flagKey = url.pathname.split("/").pop();
|
|
51
|
+
if (flagKey && flagKey in featureToggles) {
|
|
52
|
+
if (latency > 0) {
|
|
53
|
+
await delay(latency);
|
|
54
|
+
}
|
|
55
|
+
await route.fulfill({
|
|
56
|
+
status: 200,
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
key: flagKey,
|
|
59
|
+
value: featureToggles[flagKey],
|
|
60
|
+
reason: "STATIC",
|
|
61
|
+
variant: "playwright-override"
|
|
62
|
+
}),
|
|
63
|
+
headers: { "content-type": "application/json" }
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
await route.continue();
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error("@grafana/plugin-e2e: Failed to intercept OFREP single flag evaluation", error);
|
|
70
|
+
await route.continue();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function setupOpenFeatureRoutes(page2, featureToggles, latency, selectors) {
|
|
74
|
+
console.log("@grafana/plugin-e2e: setting up OpenFeature OFREP interception", { featureToggles, latency });
|
|
75
|
+
await page2.route(selectors.apis.OpenFeature.ofrepBulkPattern, async (route) => {
|
|
76
|
+
await handleBulkEvaluationRoute(route, featureToggles, latency);
|
|
77
|
+
});
|
|
78
|
+
await page2.route(selectors.apis.OpenFeature.ofrepSinglePattern, async (route) => {
|
|
79
|
+
await handleSingleFlagRoute(route, featureToggles, latency);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const page = async ({ page: page2, featureToggles, userPreferences, openFeatureLatency, selectors }, use) => {
|
|
83
|
+
const hasFeatureToggles = Object.keys(featureToggles).length > 0;
|
|
84
|
+
const hasUserPreferences = Object.keys(userPreferences).length > 0;
|
|
85
|
+
if (hasFeatureToggles || hasUserPreferences) {
|
|
7
86
|
try {
|
|
8
87
|
await page2.addInitScript(overrideGrafanaBootData.overrideGrafanaBootData, { featureToggles, userPreferences });
|
|
9
88
|
} catch (error) {
|
|
10
89
|
console.error("Failed to set feature toggles", error);
|
|
11
90
|
}
|
|
12
91
|
}
|
|
92
|
+
if (hasFeatureToggles) {
|
|
93
|
+
await setupOpenFeatureRoutes(page2, featureToggles, openFeatureLatency, selectors);
|
|
94
|
+
}
|
|
13
95
|
await page2.goto("/");
|
|
14
96
|
await use(page2);
|
|
15
97
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -521,6 +521,20 @@ declare const versionedAPIs: {
|
|
|
521
521
|
"8.0.0": (pluginId: string) => string;
|
|
522
522
|
};
|
|
523
523
|
};
|
|
524
|
+
OpenFeature: {
|
|
525
|
+
ofrepBulkPattern: {
|
|
526
|
+
'12.1.0': string;
|
|
527
|
+
};
|
|
528
|
+
ofrepSinglePattern: {
|
|
529
|
+
'12.1.0': string;
|
|
530
|
+
};
|
|
531
|
+
ofrepBulkPath: {
|
|
532
|
+
'12.1.0': (namespace?: string) => string;
|
|
533
|
+
};
|
|
534
|
+
ofrepSinglePath: {
|
|
535
|
+
'12.1.0': (namespace?: string) => string;
|
|
536
|
+
};
|
|
537
|
+
};
|
|
524
538
|
};
|
|
525
539
|
type VersionedAPIs = typeof versionedAPIs;
|
|
526
540
|
|
|
@@ -563,25 +577,31 @@ type PluginOptions = {
|
|
|
563
577
|
provisioningRootDir: string;
|
|
564
578
|
/**
|
|
565
579
|
* Optionally, you can add or override feature toggles.
|
|
566
|
-
* The feature toggles you specify here will
|
|
567
|
-
*
|
|
580
|
+
* The feature toggles you specify here will work for both legacy feature toggles (via `window.grafanaBootData.settings.featureToggles`)
|
|
581
|
+
* and OpenFeature flags (via OFREP API interception).
|
|
582
|
+
*
|
|
583
|
+
* If you need a feature toggle to work across the entire stack, you need to enable the feature in the Grafana config.
|
|
584
|
+
* Also see https://grafana.com/developers/plugin-tools/e2e-test-a-plugin/feature-toggles
|
|
568
585
|
*
|
|
569
|
-
*
|
|
586
|
+
* @example
|
|
587
|
+
* ```typescript
|
|
588
|
+
* // Override feature toggles globally in playwright.config.ts
|
|
570
589
|
* export default defineConfig({
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
590
|
+
* use: {
|
|
591
|
+
* featureToggles: {
|
|
592
|
+
* exploreMixedDatasource: true,
|
|
593
|
+
* redshiftAsyncQueryDataSupport: false
|
|
594
|
+
* },
|
|
595
|
+
* },
|
|
596
|
+
* });
|
|
578
597
|
*
|
|
579
|
-
*
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
598
|
+
* // Override feature toggles for tests in a specific file
|
|
599
|
+
* test.use({
|
|
600
|
+
* featureToggles: {
|
|
601
|
+
* exploreMixedDatasource: true,
|
|
602
|
+
* },
|
|
584
603
|
* });
|
|
604
|
+
* ```
|
|
585
605
|
*/
|
|
586
606
|
featureToggles: Record<string, boolean>;
|
|
587
607
|
/**
|
|
@@ -619,6 +639,20 @@ type PluginOptions = {
|
|
|
619
639
|
* If no credentials are provided, the server default admin:admin credentials will be used.
|
|
620
640
|
*/
|
|
621
641
|
grafanaAPICredentials: Credentials;
|
|
642
|
+
/**
|
|
643
|
+
* Artificial latency in milliseconds to add to OpenFeature OFREP API responses.
|
|
644
|
+
* Useful for testing how the UI behaves with slow network conditions when fetching feature flags.
|
|
645
|
+
*
|
|
646
|
+
* @default 0
|
|
647
|
+
* @example
|
|
648
|
+
* ```typescript
|
|
649
|
+
* // Simulate 500ms network latency for OpenFeature flag fetching
|
|
650
|
+
* test.use({
|
|
651
|
+
* openFeatureLatency: 500,
|
|
652
|
+
* });
|
|
653
|
+
* ```
|
|
654
|
+
*/
|
|
655
|
+
openFeatureLatency: number;
|
|
622
656
|
};
|
|
623
657
|
type PluginFixture = {
|
|
624
658
|
/**
|
|
@@ -628,6 +662,13 @@ type PluginFixture = {
|
|
|
628
662
|
* the version will be picked from window.grafanaBootData.settings.buildInfo.version.
|
|
629
663
|
*/
|
|
630
664
|
grafanaVersion: string;
|
|
665
|
+
/**
|
|
666
|
+
* The Grafana namespace/tenant id that was detected when the test runner was started.
|
|
667
|
+
*
|
|
668
|
+
* The namespace will be picked from window.grafanaBootData.settings.namespace.
|
|
669
|
+
* Defaults to 'default' if not available.
|
|
670
|
+
*/
|
|
671
|
+
namespace: string;
|
|
631
672
|
/**
|
|
632
673
|
* The E2E selectors to use for the current version of Grafana.
|
|
633
674
|
* See https://grafana.com/developers/plugin-tools/e2e-test-a-plugin/selecting-elements#grafana-end-to-end-selectors for more information.
|
|
@@ -842,10 +883,15 @@ type PluginTestCtx = {
|
|
|
842
883
|
selectors: E2ESelectorGroups;
|
|
843
884
|
testInfo: TestInfo;
|
|
844
885
|
} & Pick<PlaywrightTestArgs, 'page' | 'request'>;
|
|
886
|
+
/**
|
|
887
|
+
* Internal fixtures that are not exposed in the test API.
|
|
888
|
+
* These fixtures can be used by other fixtures but not by tests directly.
|
|
889
|
+
*/
|
|
890
|
+
type InternalFixtures = {};
|
|
845
891
|
/**
|
|
846
892
|
* Playwright args used when defining fixtures
|
|
847
893
|
*/
|
|
848
|
-
type PlaywrightArgs = PluginFixture & PluginOptions & PlaywrightTestArgs & PlaywrightTestOptions & PlaywrightWorkerArgs & PlaywrightWorkerOptions;
|
|
894
|
+
type PlaywrightArgs = PluginFixture & PluginOptions & InternalFixtures & PlaywrightTestArgs & PlaywrightTestOptions & PlaywrightWorkerArgs & PlaywrightWorkerOptions;
|
|
849
895
|
/**
|
|
850
896
|
* The data source settings
|
|
851
897
|
*/
|
|
@@ -1203,7 +1249,7 @@ declare class AnnotationPage extends GrafanaPage {
|
|
|
1203
1249
|
clickAddNew(): Promise<AnnotationEditPage>;
|
|
1204
1250
|
}
|
|
1205
1251
|
|
|
1206
|
-
declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PluginFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & PluginOptions>;
|
|
1252
|
+
declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & InternalFixtures & PluginFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & PluginOptions>;
|
|
1207
1253
|
declare const expect: _playwright_test.Expect<{
|
|
1208
1254
|
toHaveAlert: (grafanaPage: GrafanaPage, severity: AlertVariant, options?: AlertPageOptions) => Promise<{
|
|
1209
1255
|
message: () => any;
|
|
@@ -1239,6 +1285,10 @@ declare global {
|
|
|
1239
1285
|
grafanaBootData: {
|
|
1240
1286
|
settings: {
|
|
1241
1287
|
featureToggles: Record<string, boolean>;
|
|
1288
|
+
buildInfo: {
|
|
1289
|
+
version: string;
|
|
1290
|
+
};
|
|
1291
|
+
namespace: string;
|
|
1242
1292
|
};
|
|
1243
1293
|
};
|
|
1244
1294
|
}
|
|
@@ -1288,4 +1338,4 @@ declare global {
|
|
|
1288
1338
|
}
|
|
1289
1339
|
|
|
1290
1340
|
export { AnnotationEditPage, AnnotationPage, AppConfigPage, AppPage, DashboardPage, DataSourceConfigPage, DataSourcePicker, ExplorePage, GrafanaPage, Panel, PanelEditPage, PluginConfigPage, TimeRange, VariableEditPage, VariablePage, expect, test };
|
|
1291
|
-
export type { AlertPageOptions, AlertRule, AlertRuleArgs, AlertVariant$1 as AlertVariant, AppPageNavigateOptions, ContainTextOptions, CreateDataSourceArgs, CreateDataSourcePageArgs, Credentials, Dashboard, DashboardEditViewArgs, DashboardPageArgs, DataSourceSettings, E2ESelectorGroups, GotoAppConfigPageArgs, GotoAppPageArgs, GrafanaPageArgs, NavigateOptions, OrgRole, PlaywrightArgs, PluginFixture, PluginOptions, PluginPageArgs, PluginTestCtx, ReadProvisionedAlertRuleArgs, ReadProvisionedDashboardArgs, ReadProvisionedDataSourceArgs, RequestOptions, TimeRangeArgs, TriggerRequestOptions, User, UserPreferences, Visualization, getByGrafanaSelectorOptions };
|
|
1341
|
+
export type { AlertPageOptions, AlertRule, AlertRuleArgs, AlertVariant$1 as AlertVariant, AppPageNavigateOptions, ContainTextOptions, CreateDataSourceArgs, CreateDataSourcePageArgs, Credentials, Dashboard, DashboardEditViewArgs, DashboardPageArgs, DataSourceSettings, E2ESelectorGroups, GotoAppConfigPageArgs, GotoAppPageArgs, GrafanaPageArgs, InternalFixtures, NavigateOptions, OrgRole, PlaywrightArgs, PluginFixture, PluginOptions, PluginPageArgs, PluginTestCtx, ReadProvisionedAlertRuleArgs, ReadProvisionedDashboardArgs, ReadProvisionedDataSourceArgs, RequestOptions, TimeRangeArgs, TriggerRequestOptions, User, UserPreferences, Visualization, getByGrafanaSelectorOptions };
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,9 @@ var readProvisionedDataSource = require('./fixtures/commands/readProvisionedData
|
|
|
20
20
|
var readProvisionedAlertRule = require('./fixtures/commands/readProvisionedAlertRule.js');
|
|
21
21
|
var dashboardPage = require('./fixtures/dashboardPage.js');
|
|
22
22
|
var explorePage = require('./fixtures/explorePage.js');
|
|
23
|
+
var bootData = require('./fixtures/bootData.js');
|
|
23
24
|
var grafanaVersion = require('./fixtures/grafanaVersion.js');
|
|
25
|
+
var namespace = require('./fixtures/namespace.js');
|
|
24
26
|
var isFeatureToggleEnabled = require('./fixtures/isFeatureToggleEnabled.js');
|
|
25
27
|
var page = require('./fixtures/page.js');
|
|
26
28
|
var panelEditPage = require('./fixtures/panelEditPage.js');
|
|
@@ -53,9 +55,13 @@ var AppConfigPage = require('./models/pages/AppConfigPage.js');
|
|
|
53
55
|
var PluginConfigPage = require('./models/pages/PluginConfigPage.js');
|
|
54
56
|
var AppPage = require('./models/pages/AppPage.js');
|
|
55
57
|
|
|
56
|
-
const
|
|
58
|
+
const testWithInternal = test$1.test.extend({
|
|
59
|
+
bootData: bootData.bootData
|
|
60
|
+
});
|
|
61
|
+
const test = testWithInternal.extend({
|
|
57
62
|
selectors: selectors.selectors,
|
|
58
63
|
grafanaVersion: grafanaVersion.grafanaVersion,
|
|
64
|
+
namespace: namespace.namespace,
|
|
59
65
|
login: login.login,
|
|
60
66
|
grafanaAPIClient: grafanaAPIClient.grafanaAPIClient,
|
|
61
67
|
createDataSourceConfigPage: createDataSourceConfigPage.createDataSourceConfigPage,
|
package/dist/options.js
CHANGED
|
@@ -8,6 +8,7 @@ const DEFAULT_ADMIN_USER = {
|
|
|
8
8
|
const options = {
|
|
9
9
|
userPreferences: [{}, { option: true, scope: "worker" }],
|
|
10
10
|
featureToggles: [{}, { option: true, scope: "worker" }],
|
|
11
|
+
openFeatureLatency: [0, { option: true, scope: "worker" }],
|
|
11
12
|
provisioningRootDir: [path.join(process.cwd(), "provisioning"), { option: true, scope: "worker" }],
|
|
12
13
|
user: [DEFAULT_ADMIN_USER, { option: true, scope: "worker" }],
|
|
13
14
|
grafanaAPICredentials: [DEFAULT_ADMIN_USER, { option: true, scope: "worker" }]
|
|
@@ -43,6 +43,20 @@ const versionedAPIs = {
|
|
|
43
43
|
settings: {
|
|
44
44
|
[minGrafanaVersion.MIN_GRAFANA_VERSION]: (pluginId) => `/api/plugins/${pluginId}/settings`
|
|
45
45
|
}
|
|
46
|
+
},
|
|
47
|
+
OpenFeature: {
|
|
48
|
+
ofrepBulkPattern: {
|
|
49
|
+
"12.1.0": "**/apis/features.grafana.app/**/ofrep/v*/evaluate/flags"
|
|
50
|
+
},
|
|
51
|
+
ofrepSinglePattern: {
|
|
52
|
+
"12.1.0": "**/apis/features.grafana.app/**/ofrep/v*/evaluate/flags/*"
|
|
53
|
+
},
|
|
54
|
+
ofrepBulkPath: {
|
|
55
|
+
"12.1.0": (namespace = "default") => `/apis/features.grafana.app/v0alpha1/namespaces/${namespace}/ofrep/v1/evaluate/flags`
|
|
56
|
+
},
|
|
57
|
+
ofrepSinglePath: {
|
|
58
|
+
"12.1.0": (namespace = "default") => `/apis/features.grafana.app/v0alpha1/namespaces/${namespace}/ofrep/v1/evaluate/flags`
|
|
59
|
+
}
|
|
46
60
|
}
|
|
47
61
|
};
|
|
48
62
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafana/plugin-e2e",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-canary.2408.21202715809.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"uuid": "^13.0.0",
|
|
48
48
|
"yaml": "^2.3.4"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "043c6c46215cc086eb03bedf1ea92a11cd94d2dc"
|
|
51
51
|
}
|