mirror of https://github.com/grafana/grafana.git
Extensions: e2e test usePluginComponent hook (#91750)
* add simple test apps that use usePluginComponent hook and exposeComponent api * add e2e test * update readme * Update README.md * fix lint issue * pr feedback
This commit is contained in:
parent
b9cece8f9e
commit
2ed6ca360f
|
@ -17,3 +17,11 @@ apps:
|
|||
org_id: 1
|
||||
org_name: Main Org.
|
||||
disabled: false
|
||||
- type: myorg-componentconsumer-app
|
||||
org_id: 1
|
||||
org_name: Main Org.
|
||||
disabled: false
|
||||
- type: myorg-componentexposer-app
|
||||
org_id: 1
|
||||
org_name: Main Org.
|
||||
disabled: false
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# App with exposed components
|
||||
|
||||
This directory contains two apps - `myorg-componentconsumer-app` and `myorg-componentexposer-app` which is nested inside `myorg-componentconsumer-app`.
|
||||
|
||||
`myorg-componentconsumer-app` exposes a simple React component using the [`exposeComponent`](https://grafana.com/developers/plugin-tools/reference/ui-extensions#exposecomponent) api. `myorg-componentconsumer-app` in turn, consumes this compoment using the [`https://grafana.com/developers/plugin-tools/reference/ui-extensions#useplugincomponent`](https://grafana.com/developers/plugin-tools/reference/ui-extensions#useplugincomponent) hook.
|
||||
|
||||
To test this app:
|
||||
|
||||
```sh
|
||||
# start e2e test instance (it will install this plugin)
|
||||
PORT=3000 ./scripts/grafana-server/start-server
|
||||
# run Playwright tests using Playwright VSCode extension or with the following script
|
||||
yarn e2e:playwright
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
PORT=3000 ./scripts/grafana-server/start-server
|
||||
yarn start
|
||||
yarn e2e
|
||||
```
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 81.9 71.52"><defs><style>.cls-1{fill:#84aff1;}.cls-2{fill:#3865ab;}.cls-3{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="42.95" y1="16.88" x2="81.9" y2="16.88" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f2cc0c"/><stop offset="1" stop-color="#ff9830"/></linearGradient></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M55.46,62.43A2,2,0,0,1,54.07,59l4.72-4.54a2,2,0,0,1,2.2-.39l3.65,1.63,3.68-3.64a2,2,0,1,1,2.81,2.84l-4.64,4.6a2,2,0,0,1-2.22.41L60.6,58.26l-3.76,3.61A2,2,0,0,1,55.46,62.43Z"/><path class="cls-2" d="M37,0H2A2,2,0,0,0,0,2V31.76a2,2,0,0,0,2,2H37a2,2,0,0,0,2-2V2A2,2,0,0,0,37,0ZM4,29.76V8.84H35V29.76Z"/><path class="cls-3" d="M79.9,0H45a2,2,0,0,0-2,2V31.76a2,2,0,0,0,2,2h35a2,2,0,0,0,2-2V2A2,2,0,0,0,79.9,0ZM47,29.76V8.84h31V29.76Z"/><path class="cls-2" d="M37,37.76H2a2,2,0,0,0-2,2V69.52a2,2,0,0,0,2,2H37a2,2,0,0,0,2-2V39.76A2,2,0,0,0,37,37.76ZM4,67.52V46.6H35V67.52Z"/><path class="cls-2" d="M79.9,37.76H45a2,2,0,0,0-2,2V69.52a2,2,0,0,0,2,2h35a2,2,0,0,0,2-2V39.76A2,2,0,0,0,79.9,37.76ZM47,67.52V46.6h31V67.52Z"/><rect class="cls-1" x="10.48" y="56.95" width="4" height="5.79"/><rect class="cls-1" x="17.43" y="53.95" width="4" height="8.79"/><rect class="cls-1" x="24.47" y="50.95" width="4" height="11.79"/><path class="cls-1" d="M19.47,25.8a6.93,6.93,0,1,1,6.93-6.92A6.93,6.93,0,0,1,19.47,25.8Zm0-9.85a2.93,2.93,0,1,0,2.93,2.93A2.93,2.93,0,0,0,19.47,16Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,28 @@
|
|||
define(['@grafana/data', '@grafana/runtime', 'react'], function (grafanaData, grafanaRuntime, React) {
|
||||
var AppPlugin = grafanaData.AppPlugin;
|
||||
var usePluginComponent = grafanaRuntime.usePluginComponent;
|
||||
|
||||
var MyComponent = function () {
|
||||
var plugin = usePluginComponent('myorg-componentexposer-app/reusable-component/v1');
|
||||
var TestComponent = plugin.component;
|
||||
var isLoading = plugin.isLoading;
|
||||
|
||||
if (!TestComponent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return React.createElement(
|
||||
React.Fragment,
|
||||
null,
|
||||
React.createElement('div', null, 'Exposed component:'),
|
||||
isLoading ? 'Loading..' : React.createElement(TestComponent, { name: 'World' })
|
||||
);
|
||||
};
|
||||
|
||||
var App = function () {
|
||||
return React.createElement('div', null, 'Hello Grafana!', React.createElement(MyComponent, null));
|
||||
};
|
||||
|
||||
var plugin = new AppPlugin().setRootPage(App);
|
||||
return { plugin: plugin };
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/grafana/grafana/main/docs/sources/developers/plugins/plugin.schema.json",
|
||||
"type": "app",
|
||||
"name": "Extensions exposed component App",
|
||||
"id": "myorg-componentconsumer-app",
|
||||
"preload": true,
|
||||
"info": {
|
||||
"keywords": ["app"],
|
||||
"description": "Example on how to extend grafana ui from a plugin",
|
||||
"author": {
|
||||
"name": "Myorg"
|
||||
},
|
||||
"logos": {
|
||||
"small": "img/logo.svg",
|
||||
"large": "img/logo.svg"
|
||||
},
|
||||
"screenshots": [],
|
||||
"version": "1.0.0",
|
||||
"updated": "2024-08-09"
|
||||
},
|
||||
"includes": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "Default",
|
||||
"path": "/a/myorg-componentconsumer-app",
|
||||
"role": "Admin",
|
||||
"addToNav": true,
|
||||
"defaultNav": true
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"grafanaDependency": ">=10.3.3",
|
||||
"plugins": []
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 81.9 71.52"><defs><style>.cls-1{fill:#84aff1;}.cls-2{fill:#3865ab;}.cls-3{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="42.95" y1="16.88" x2="81.9" y2="16.88" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f2cc0c"/><stop offset="1" stop-color="#ff9830"/></linearGradient></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M55.46,62.43A2,2,0,0,1,54.07,59l4.72-4.54a2,2,0,0,1,2.2-.39l3.65,1.63,3.68-3.64a2,2,0,1,1,2.81,2.84l-4.64,4.6a2,2,0,0,1-2.22.41L60.6,58.26l-3.76,3.61A2,2,0,0,1,55.46,62.43Z"/><path class="cls-2" d="M37,0H2A2,2,0,0,0,0,2V31.76a2,2,0,0,0,2,2H37a2,2,0,0,0,2-2V2A2,2,0,0,0,37,0ZM4,29.76V8.84H35V29.76Z"/><path class="cls-3" d="M79.9,0H45a2,2,0,0,0-2,2V31.76a2,2,0,0,0,2,2h35a2,2,0,0,0,2-2V2A2,2,0,0,0,79.9,0ZM47,29.76V8.84h31V29.76Z"/><path class="cls-2" d="M37,37.76H2a2,2,0,0,0-2,2V69.52a2,2,0,0,0,2,2H37a2,2,0,0,0,2-2V39.76A2,2,0,0,0,37,37.76ZM4,67.52V46.6H35V67.52Z"/><path class="cls-2" d="M79.9,37.76H45a2,2,0,0,0-2,2V69.52a2,2,0,0,0,2,2h35a2,2,0,0,0,2-2V39.76A2,2,0,0,0,79.9,37.76ZM47,67.52V46.6h31V67.52Z"/><rect class="cls-1" x="10.48" y="56.95" width="4" height="5.79"/><rect class="cls-1" x="17.43" y="53.95" width="4" height="8.79"/><rect class="cls-1" x="24.47" y="50.95" width="4" height="11.79"/><path class="cls-1" d="M19.47,25.8a6.93,6.93,0,1,1,6.93-6.92A6.93,6.93,0,0,1,19.47,25.8Zm0-9.85a2.93,2.93,0,1,0,2.93,2.93A2.93,2.93,0,0,0,19.47,16Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,14 @@
|
|||
define(['@grafana/data', 'module', 'react'], function (grafanaData, amdModule, React) {
|
||||
const plugin = new grafanaData.AppPlugin().exposeComponent({
|
||||
id: 'myorg-componentexposer-app/reusable-component/v1',
|
||||
title: 'Reusable component',
|
||||
description: 'A component that can be reused by other app plugins.',
|
||||
component: function ({ name }) {
|
||||
return React.createElement('div', { 'data-testid': 'exposed-component' }, 'Hello ', name, '!');
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
plugin: plugin,
|
||||
};
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/grafana/grafana/main/docs/sources/developers/plugins/plugin.schema.json",
|
||||
"type": "app",
|
||||
"name": "A App",
|
||||
"id": "myorg-componentexposer-app",
|
||||
"preload": true,
|
||||
"info": {
|
||||
"keywords": ["app"],
|
||||
"description": "Will extend root app with ui extensions",
|
||||
"author": {
|
||||
"name": "Myorg"
|
||||
},
|
||||
"logos": {
|
||||
"small": "img/logo.svg",
|
||||
"large": "img/logo.svg"
|
||||
},
|
||||
"screenshots": [],
|
||||
"version": "%VERSION%",
|
||||
"updated": "%TODAY%"
|
||||
},
|
||||
"includes": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "Default",
|
||||
"path": "/a/myorg-componentexposer-app",
|
||||
"role": "Admin",
|
||||
"addToNav": false,
|
||||
"defaultNav": false
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"grafanaDependency": ">=10.3.3",
|
||||
"plugins": []
|
||||
}
|
||||
}
|
|
@ -32,7 +32,5 @@
|
|||
"grafanaDependency": ">=10.3.3",
|
||||
"plugins": []
|
||||
},
|
||||
"generated": {
|
||||
"extensions": []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
"grafanaDependency": ">=10.3.3",
|
||||
"plugins": []
|
||||
},
|
||||
"generated": {
|
||||
"extensions": [
|
||||
{
|
||||
"extensionPointId": "plugins/myorg-extensionpoint-app/actions",
|
||||
|
@ -41,5 +40,4 @@
|
|||
"type": "link"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { test, expect } from '@grafana/plugin-e2e';
|
||||
|
||||
const pluginId = 'myorg-componentconsumer-app';
|
||||
const exposedComponentTestId = 'exposed-component';
|
||||
|
||||
test('should display component exposed by another app', async ({ page }) => {
|
||||
await page.goto(`/a/${pluginId}`);
|
||||
await expect(await page.getByTestId(exposedComponentTestId)).toHaveText('Hello World!');
|
||||
});
|
Loading…
Reference in New Issue