diff --git a/docs/html-reporter/html-reporter-plugins-api.mdx b/docs/html-reporter/html-reporter-plugins-api.mdx
new file mode 100644
index 0000000..0346d08
--- /dev/null
+++ b/docs/html-reporter/html-reporter-plugins-api.mdx
@@ -0,0 +1,271 @@
+---
+sidebar_position: 3
+sidebar_label: Plugins SDK
+sidebar_class_name: hidden
+---
+
+# Plugins SDK for HTML Reporter
+
+Reference for available dependencies, SDK components, and extension points for plugin development.
+
+## Available Dependencies
+
+Plugins can use the following dependencies provided by HTML Reporter at runtime. These dependencies do not need to be included in the bundle — they will be passed through the wrapper function.
+
+| Dependency | Description |
+| ------------------------------ | ---------------------------------------- |
+| `@gravity-ui/icons` | [Gravity UI Icons][gravity-ui-icons] |
+| `@gravity-ui/uikit` | [Gravity UI][gravity-ui] components |
+| `axios` | HTTP client for server requests |
+| `classnames` | Utility for working with CSS classes |
+| `html-reporter/plugins-sdk` | SDK for server part (ExtensionPointName) |
+| `html-reporter/plugins-sdk/ui` | SDK for UI components |
+| `immer` | Immutable state updates |
+| `lodash` | Data manipulation utilities |
+| `react` | React 18 |
+| `react-dom` | React DOM |
+| `react-redux` | React bindings for Redux |
+| `react/jsx-runtime` | JSX Runtime |
+| `redux` | Redux for state management |
+| `redux-thunk` | Middleware for async actions (built-in) |
+| `reselect` | Memoized selectors for Redux |
+
+## Plugins SDK UI {#plugins-sdk-ui}
+
+The `html-reporter/plugins-sdk/ui` module exports components and types for creating plugin UIs.
+
+### CollapsibleSection
+
+A collapsible section integrated with the report's Redux state.
+
+```typescript
+import { CollapsibleSection } from "html-reporter/plugins-sdk/ui";
+
+interface CollapsibleSectionProps {
+ /** Unique section identifier */
+ id: string;
+ /** Section title */
+ title: string;
+ /** Section content */
+ children?: ReactNode;
+ /** CSS class */
+ className?: string;
+ /** Whether the section is expanded by default */
+ defaultExpanded?: boolean;
+ /** Callback when state changes */
+ onUpdate?: (expanded: boolean) => void;
+}
+```
+
+Usage example:
+
+```tsx
+ {
+ if (expanded) {
+ // Load data when expanded
+ }
+ }}
+>
+
Section content
+
+```
+
+### PanelSection
+
+Section for the settings panel.
+
+```typescript
+import { PanelSection } from "html-reporter/plugins-sdk/ui";
+
+interface PanelSectionProps {
+ /** Section title */
+ title: ReactNode;
+ /** Description */
+ description?: ReactNode;
+ /** Content */
+ children?: ReactNode;
+}
+```
+
+### State
+
+Type of the root Redux store state.
+
+```typescript
+import { State } from "html-reporter/plugins-sdk/ui";
+
+// Use for typing selectors
+const mySelector = (state: State) => state.tree.results.byId;
+```
+
+### Features
+
+Flags for available report features.
+
+```typescript
+import { Features } from "html-reporter/plugins-sdk/ui";
+
+const availableFeatures = useSelector(state => {
+ return state.app.availableFeatures;
+});
+if (!availableFeatures.some(feature => feature.name === Features.RunTestsFeature.name)) {
+ return null;
+}
+```
+
+## The pluginOptions Object {#plugin-options}
+
+A global `pluginOptions` object is available in the plugin UI component:
+
+```typescript
+declare const pluginOptions: {
+ /** Plugin name (from configuration) */
+ pluginName: string;
+ /** Plugin configuration (config field from configuration) */
+ pluginConfig: object;
+ /** Prefix for server endpoints: /plugin-routes/{pluginName}/ */
+ pluginServerEndpointPrefix: string;
+ /** Report Redux actions */
+ actions: object;
+ /** Report action names */
+ actionNames: object;
+ /** Redux Store selectors, see html-reporter/lib/static/modules/selectors */
+ selectors: object;
+};
+```
+
+## Extension Points {#extension-points}
+
+Extension points determine where in the report interface the plugin component will be placed.
+
+| Point | Description | Component Props |
+| ------------------ | ------------------------------------------ | ---------------------------- |
+| `result_meta` | Test result area, near meta information | `result: ReporterTestResult` |
+| `settings-panel` | Settings panel | — |
+| `run-test-options` | Test run options, near the run test button | — |
+
+### ExtensionPointName
+
+Use enum to specify the extension point in the preset:
+
+```typescript
+import { ExtensionPointName } from "html-reporter/plugins-sdk";
+
+// Available values:
+ExtensionPointName.ResultMeta; // "result_meta"
+ExtensionPointName.MenuBar; // "menu-bar"
+ExtensionPointName.Root; // "root"
+```
+
+### Positioning
+
+The `position` parameter determines the component placement relative to the extension point:
+
+| Value | Description |
+| ---------- | ---------------------------------- |
+| `"before"` | Before the extension point content |
+| `"after"` | After the extension point content |
+| `"wrap"` | Wrap the extension point content |
+
+## CSS and Styling {#css-styling}
+
+### CSS Modules
+
+It is recommended to use CSS Modules for style isolation:
+
+```css title="Plugin.module.css"
+.container {
+ padding: 16px;
+}
+
+.result {
+ display: flex;
+ gap: 8px;
+}
+```
+
+```tsx
+import styles from "./Plugin.module.css";
+
+
+
...
+
;
+```
+
+### Gravity UI CSS Variables
+
+HTML Reporter uses the [Gravity UI theme][gravity-ui-theme]. You can use CSS variables for style consistency:
+
+```css
+.myElement {
+ /* Text colors */
+ color: var(--g-color-text-primary);
+ color: var(--g-color-text-secondary);
+ color: var(--g-color-text-brand);
+ color: var(--g-color-text-danger);
+
+ /* Background colors */
+ background: var(--g-color-base-background);
+ background: var(--g-color-base-brand);
+
+ /* Borders */
+ border-color: var(--g-color-line-generic);
+
+ /* Spacing and sizes */
+ padding: var(--g-spacing-2); /* 8px */
+ padding: var(--g-spacing-4); /* 16px */
+}
+```
+
+### CSS Injection into Bundle
+
+Use the `vite-plugin-css-injected-by-js` plugin to include CSS in the JavaScript bundle:
+
+```typescript title="vite.config.ts"
+import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
+
+export default defineConfig({
+ plugins: [cssInjectedByJsPlugin()],
+});
+```
+
+## Typing {#typing}
+
+### Extending DefaultRootState
+
+To type the plugin state in Redux, extend `DefaultRootState`:
+
+```typescript title="types.d.ts"
+import type { State } from "html-reporter/plugins-sdk/ui";
+
+interface MyPluginState {
+ data: Record;
+}
+
+declare module "react-redux" {
+ export interface DefaultRootState extends State {
+ plugins: {
+ myPlugin: MyPluginState;
+ };
+ }
+}
+```
+
+### Global pluginOptions
+
+```typescript title="types.d.ts"
+declare global {
+ const pluginOptions: {
+ pluginConfig: MyPluginConfig;
+ pluginServerEndpointPrefix: string;
+ };
+}
+```
+
+[gravity-ui]: https://gravity-ui.com/
+[gravity-ui-icons]: https://gravity-ui.com/icons
+[gravity-ui-theme]: https://gravity-ui.com/design/themes
diff --git a/docs/html-reporter/html-reporter-plugins.mdx b/docs/html-reporter/html-reporter-plugins.mdx
index c731011..60184b8 100644
--- a/docs/html-reporter/html-reporter-plugins.mdx
+++ b/docs/html-reporter/html-reporter-plugins.mdx
@@ -1,301 +1,255 @@
-# HTML Reporter Plugins
+import Admonition from "@theme/Admonition";
-## Overview {#overview}
+# Developing Plugins
-Use the `plugins` option in the `html-reporter` plugin config to extend the functionality of the report using your own plugins to the report.
+Plugins allow you to add custom UI components to the HTML Reporter interface. For example, you can display test stability statistics or add a button for integration with an external service. HTML Reporter has several extension points where the plugin UI can be displayed — for example, on the settings panel or on the test result page.
-To make your plugins work in the report, enable the [pluginsEnabled][plugins-enabled] option in the `html-reporter` plugin config by setting its value to `true`.
+## Quick Start
-The list of plugins is set as an array with their descriptions. By default, the list is considered empty: `[]`.
+A fully working plugin with configured build and using the main features of the plugin system is available in the [HTML Reporter repository](https://github.com/gemini-testing/html-reporter/tree/master/examples/random-number-plugin-example/).
-Plugins allow you to add your own UI components to the report (both for a static report and for GUI mode), as well as server "handles" _(routes)_ (for GUI mode).
+We recommend using this example as a template for your plugin.
-## Setup {#setup}
+## How Plugins Work
-The description of plugins looks like this:
+Plugins are connected to HTML Reporter in the config, for example:
-```javascript
-plugins: [
- {
- name: "plugin-name",
- component: "PluginReactComponentName",
- point: "extension-point-name",
- position: "wrap",
- config: { param: "value" },
+```typescript title="testplane.config.ts"
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ pluginsEnabled: true,
+ plugins: [
+ {
+ name: "my-plugin-package",
+ component: "MyPlugin",
+ point: "result_meta",
+ position: "after",
+ },
+ ],
+ },
},
- {
- name: "plugin-name",
- component: "AnotherPluginReactComponentName",
- point: "extension-point-name",
- position: "before",
- },
-
- // ...
-];
+};
```
-### Description of configuration parameters {#setup_description}
+In this case, HTML Reporter will look for the plugin in the npm package `my-plugin-package`, specifically:
-
-
-
**Parameter**
**Type**
**Description**
-
-
-
[name](#name)
String
Required parameter. The name of the package with the plugin for the report. It is assumed that the plugin can be connected using _require(name)_.
-
[component](#component)
String
The name of the React component from the plugin.
-
[point](#point)
String
The name of the extension point in the _html-reporter_ plugin.
-
[position](#position)
String
Defines the method by which the component will be placed at the extension point.
-
[config](#config)
Object
Plugin configuration.
+- In `my-plugin-package/plugin.js` HTML Reporter will look for the implementation of the `MyPlugin` component, which will be displayed at the `result_meta` extension point
+- In `my-plugin-package/middleware.js` HTML Reporter will look for the implementation of server endpoints
-
-
+Therefore, a typical plugin consists of three parts:
-A plugin for which only the `name` parameter is set can be used to override an existing GUI server middleware.
+```
+my-plugin/
+├── ui/ # Plugin UI — built into plugin.js bundle using Vite
+├── server/ # Server part of the plugin (optional) — entry point expected in middleware.js
+└── preset-for-config/ # Preset for convenient connection (optional)
+```
-A plugin can define more than one component. Each component can be applied to multiple extension points and/or multiple times to the same point (with separate configuration entries). The order in which components are applied is determined by the configuration order.
+## Creating Plugin UI
-### name
+### 1. Build Setup
-Required parameter. The name of the package with the plugin for the report. It is assumed that the plugin can be connected using _require(name)_.
+#### Output File Format
-### component
+The result of building the plugin UI should be 1 file — a `plugin.js` bundle in the following format:
-The name of the React component from the plugin.
+```javascript title="ui/build/plugin.js"
+__testplane_html_reporter_register_plugin__([
+ "react",
+ function (React, options) {
+ // ...
+ return { MyPlugin, reducers: [] };
+ },
+]);
+```
-### point
+The file should contain only a call to the `__testplane_html_reporter_register_plugin__` function.
-The name of the extension point in the _html-reporter_ plugin.
+The only argument of the function is an array. It declares the dependencies needed by the plugin (see available dependencies in the [Plugins SDK reference][plugins-sdk-reference]). The last element of the array is a function that will be called with the listed dependencies and should return an object with the component and reducers.
-Defines the specific location of the specified component inside the html-reporter user interface.
+For more details on what exactly this function is called with, see the [HTML Reporter source code](https://github.com/gemini-testing/html-reporter/blob/885b2208e3fa2aeb1888d4a674e302b072c67e26/lib/static/modules/load-plugin.js#L107).
-For more information, see the section "[Extension points](#extension_points)".
+#### Reusing Dependencies
-### position
+For React and hooks to work correctly, it is critical that dependencies are not duplicated, and the same instances are used everywhere — both in HTML Reporter and in the plugin.
-Defines the method by which the component will be placed at the extension point of the html-report user interface.
+HTML Reporter provides a number of dependencies available for reuse, including React and Gravity UI.
-The following values are available:
+To reuse these dependencies, you need to specify them in `external` in the Vite configuration.
-
-
-
**Value**
**Description**
-
-
-
wrap
wrap the extension point in the UI
-
before
place the component before the extension point
-
after
place the component after the extension point
+#### Vite Configuration Example
-
-
+In practice, the required bundle characteristics are achieved by building through Vite with `external` dependencies and a special wrapper. You can see an example in the [HTML Reporter repository](https://github.com/gemini-testing/html-reporter/tree/master/examples/random-number-plugin-example/ui/vite.config.ts).
-### config
+### 2. Component Implementation
-Plugin configuration.
+Depending on which extension point is used, HTML Reporter may pass some data in props, for example, the current test run result (see more in the Plugins SDK reference):
-## Plugin code for the report {#plugins_code}
+```tsx title="ui/Plugin.tsx"
+import { Button } from "@gravity-ui/uikit";
-Examples of plugins can be [viewed in functional tests][html-reporter-plugins].
+export const MyPlugin = ({ result }: { result: { id: string; suitePath: string[] } }) => {
+ const fullName = result.suitePath.join(" ");
-The `html-reporter` plugin is an object with some set of React components specified as its keys, and an optional `reducers` key with an array of redux-reducers to control the state of components, which are later combined using [reduce-reducers][reduce-reducers].
+ return (
+
+
Test Full Name: {fullName}
+
+
+ );
+};
+```
-The plugin for the report is expected to have the following module files in the root of its package: `plugin.js` and/or `middleware.js`.
+The main plugin file can be organized like this:
-### plugin.js
+```typescript title="ui/index.tsx"
+import { MyPlugin } from "./Plugin";
-Optional module. A file that should export an object (or a set of named exports) or a function that returns such an object or array with some specific structure.
+export default {
+ MyPlugin,
+ reducers: [],
+};
+```
-You can reuse the `html-reporter` dependencies in plugins (React, Redux, etc.). To do this, an array with a list of necessary dependencies must be exported from the module, followed by a function with the corresponding dependencies passed to it, and returning the plugin itself.
+When developing plugins, it is recommended to use Gravity UI and components from the Plugins SDK for visual consistency with the rest of the HTML Reporter interface.
-For example:
+#### Working with Redux (Optional)
-```javascript
-import "plugin-styles.css";
+Use Redux to store and retrieve plugin data.
-export default [
- "react",
- function (React, options) {
- class PluginComponent extends React.Component {
- // component implementation
- }
+##### Creating Actions
- return {
- PluginComponent,
- reducers: [],
- };
- },
-];
+Define action types with a unique prefix:
+
+```typescript title="ui/actions.ts"
+export const actions = {
+ LOADING: "plugins/myPlugin/loading",
+ LOADED: "plugins/myPlugin/loaded",
+ ERROR: "plugins/myPlugin/error",
+} as const;
```
-Styles for the plugin must be loaded together with `plugin.js`, and the resulting file should be one bundle.
+##### Creating Thunk for Requests
-Value exported from `plugin.js`, should be passed to `__testplane_html_reporter_register_plugin__`.
+Use thunk actions for asynchronous operations:
-There are two ways to do this.
+```typescript title="ui/actions.ts"
+export const fetchData = (resultId: string) => async dispatch => {
+ dispatch({ type: actions.LOADING, payload: { resultId } });
-For example, configure the build by _webpack_ so that it creates the corresponding `jsonp` library:
+ const endpoint = `${pluginOptions.pluginServerEndpointPrefix}/data`;
+ const { data } = await axios.get(endpoint);
-```javascript
-// ...
-output: {
- filename: 'plugin.js',
- path: __dirname,
- library: '__testplane_html_reporter_register_plugin__',
- libraryTarget: 'jsonp'
-},
-// ...
+ dispatch({ type: actions.LOADED, payload: { resultId, data } });
+};
```
-Or pass the value exported from `plugin.js`, clearly:
+The global variable `pluginOptions.pluginServerEndpointPrefix` contains the base URL for requests to the plugin server.
-```javascript
-__testplane_html_reporter_register_plugin__([
- "react",
- function (React, options) {
+##### Creating Reducer
+
+The reducer updates the plugin state. Use Immer for immutable updates:
+
+```typescript title="ui/reducers.ts"
+import produce from "immer";
+
+export default produce((draft, action) => {
+ if (!draft.plugins.myPlugin) {
+ draft.plugins.myPlugin = { byResultId: {} };
+ }
+
+ switch (action.type) {
+ case actions.LOADING: {
+ const { resultId } = action.payload;
+ draft.plugins.myPlugin.byResultId[resultId] = {
+ ...defaultResultState,
+ status: "loading",
+ };
+ break;
+ }
// ...
- return { PluginComponent };
- },
-]);
+ }
+});
+```
+
+##### Reading State
+
+Use `useSelector` to read data from the store:
+
+```tsx
+const data = useSelector(state => state.plugins.myPlugin?.byResultId[result.id]);
```
-### middleware.js
+For more details on the Redux store structure, see the [HTML Reporter source code](https://github.com/gemini-testing/html-reporter/blob/885b2208e3fa2aeb1888d4a674e302b072c67e26/lib/static/new-ui/types/store.ts#L257).
-Optional module. Exports a function that accepts `Router` from [express][express]. It is expected that the "routes" of the plugin will be connected to the router. And the router then connects to the "route" `/plugin-routes/:PluginName/`.
+The component name (`MyPlugin`) must match the `component` field in the plugin configuration.
-```javascript
-module.exports = function (pluginRouter) {
- pluginRouter.get("/plugin-route", function (req, res) {
- // "route" implementation
+### 3. Server Part (Optional)
+
+The server part receives an Express Router with the prefix `/plugin-routes/{plugin-name}/`:
+
+```typescript title="server/index.ts"
+import type { Router } from "express";
+
+export = function (router: Router) {
+ router.get("/data", (req, res) => {
+ res.json({ value: 42 });
});
};
```
-Then the "routes" can be called from the React components of the plugin defined in `plugin.js`. For convenience, the plugin name is always passed with options called `pluginName` when a function or an array of functions is used for export:
+This endpoint will be available at `/plugin-routes/my-plugin/data`.
-```javascript
-export default ['react', 'axios', function(React, axios, { pluginName, pluginConfig, actions, actionNames, selectors }) {
- class PluginComponent extends React.Component {
- // ... somewhere inside the component ...
- const result = await axios.get(`/plugin-routes/${pluginName}/plugin-route`);
- }
+It is recommended to get the server part address from the global variable `pluginOptions.pluginServerEndpointPrefix`, as the plugin name is transformed on the HTML Reporter side and may not match the package name.
- return {
- PluginComponent,
- reducers: []
- };
-}
-```
+### 4. Configuration Preset (Optional)
-In this example, you can also see the following properties:
-
-
-
-
**Property**
**Description**
-
-
-
pluginName
plugin name
-
pluginConfig
plugin configuration
-
actions
Redux-actions
-
actionNames
action names in _html-reporter_ that are used in Redux-actions, allow to subscribe to report events
-
selectors
cached report selectors that were created using the [reselect][redux-reselect] library
-
-
-
-
-### Available dependencies {#available_deps}
-
-The following dependencies are available in plugins:
-
-- [react][react]
-- [redux][redux]
-- [react-redux][react-redux]
-- [lodash][lodash]
-- [prop-types][prop-types]
-- [classnames][classnames]
-- [semantic-ui-react][semantic-ui-react]
-- [react-markdown][react-markdown]
-- [reduce-reducers][reduce-reducers]
-- [immer][immer]
-- [reselect][redux-reselect]
-- [axios][axios]
-
-### Available components {#available_components}
-
-#### ``
-
-A component with which you can switch the display of content.
-
-Usage example:
-
-```javascript
-// ...inside your React component
-
-render() {
- return console.log('clicked')} // as well as your handler
- />
-}
-```
+The preset simplifies plugin connection for users:
-where:
+```typescript title="preset-for-config/index.ts"
+import { ExtensionPointName } from "html-reporter/plugins-sdk";
-
-
-
**Property**
**Type**
**Description**
-
-
-
title
String or JSX.Element
Required parameter. A header describing the information hidden under it.
-
content
Function or String or String[] or JSX.Element
Required parameter. The content that will appear when you click on the title.
-
extendClassNames
String or String[]
CSS classes to add to the component. Optional parameter.
-
onClick
Function
The handler that will be called by clicking on the header. Optional parameter.
+Thanks to the preset, instead of specifying the full plugin descriptor in the config, users can import this object and use it.
-## Extension points {#extension_points}
+### 5. Connecting the Plugin
-Extension points are places in the user interface of the report that are available for extension using React components exported by _plugins for the report_.
+After publishing, users connect the plugin like this:
-Each extension point can pass certain props to plugin components depending on the point itself. Since some plugins may rely on a specific placement and, therefore, on specific props, it is possible to restrict plugin components to certain extension points by specifying a static `point` property for such plugin components:
+```typescript title="testplane.config.ts"
+import myPlugin from "my-plugin-package";
-```javascript
-class PluginComponent extends React.Component {
- static point = "result";
- // ...
-}
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ pluginsEnabled: true,
+ plugins: myPlugin(),
+ },
+ },
+};
```
-The following extension points are currently available:
-
-
-
-
**Point**
**Description**
-
-
-
result
Allows you to extend each test result. Adds the _resultId_ and _testName_ props to the plugin component.
-
result_meta
Allows you to extend the meta information for each test result. Adds the _resultId_ and _testName_ props to the plugin component.
-
menu-bar
Allows you to extend the menu.
-
root
Allows you to add floating elements such as a modal window or a popup.
-
-
-
-
-An extension point can be extended by more than one component. In this case, the order in which components are applied is determined by the order in which plugins are configured. Each subsequent component is applied to all previously composed components at the extension point.
-
-[plugins-enabled]: ../html-reporter-setup#pluginsenabled
-[html-reporter-plugins]: https://github.com/gemini-testing/html-reporter/blob/master/test/func/fixtures/plugins/.testplane.conf.js
-[reduce-reducers]: https://github.com/redux-utilities/reduce-reducers
-[express]: https://github.com/expressjs/express
-[redux-reselect]: https://github.com/reduxjs/reselect
-[react]: https://github.com/facebook/react
-[redux]: https://github.com/reduxjs/redux
-[react-redux]: https://github.com/reduxjs/react-redux
-[lodash]: https://github.com/lodash/lodash
-[prop-types]: https://github.com/facebook/prop-types
-[classnames]: https://github.com/JedWatson/classnames
-[semantic-ui-react]: https://github.com/Semantic-Org/Semantic-UI-React
-[react-markdown]: https://github.com/remarkjs/react-markdown
-[immer]: https://github.com/immerjs/immer
-[axios]: https://github.com/axios/axios
+### Additional Materials
+
+- [API Reference](../html-reporter-plugins-api) — dependencies, SDK components, extension points
+- [Plugin Configuration](../html-reporter-setup#plugins) — connection parameters
+- [Plugin Example][example-plugin] — full working code
+
+[example-plugin]: https://github.com/gemini-testing/html-reporter/tree/master/examples/random-number-plugin-example
+[gravity-ui]: https://gravity-ui.com/
+[plugins-sdk-reference]: ../html-reporter-plugins-api
diff --git a/docs/html-reporter/html-reporter-setup.mdx b/docs/html-reporter/html-reporter-setup.mdx
index 2f6e6f9..1ac002f 100644
--- a/docs/html-reporter/html-reporter-setup.mdx
+++ b/docs/html-reporter/html-reporter-setup.mdx
@@ -1,13 +1,12 @@
-import Version from "../_partials/specs/version.mdx";
-
---
-
-## sidebar_position: 2
+sidebar_position: 2
+---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Admonition from "@theme/Admonition";
import ConfigExamples from "/docs/_partials/html-reporter-config-examples.mdx";
+import Version from "../_partials/specs/version.mdx";
# Configuration
@@ -240,13 +239,103 @@ See more in the section "[Customizing GUI](../html-reporter-custom-gui)".
### pluginsEnabled
-Enable plugins for `html-reporter`.
+Enable plugins for `html-reporter`. Default: `false`.
### plugins
-A list of plugins with their settings.
+A list of plugins with their settings. Default: `[]`.
+
+Plugins allow you to extend the report interface with custom UI components. For more information about developing plugins, see the section "[Developing Plugins](../html-reporter-plugins)".
+
+#### Using with Preset {#plugins-with-preset}
+
+If the plugin provides a configuration preset, the connection looks like this:
+
+```typescript title="testplane.config.ts"
+import myPlugin from "my-plugin-package";
+
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ enabled: true,
+ pluginsEnabled: true,
+ plugins: myPlugin({
+ /* plugin options */
+ }),
+ },
+ },
+};
+```
+
+#### Manual Configuration {#plugins-manual-config}
+
+Plugins can be configured manually by specifying an array of objects:
+
+```typescript title="testplane.config.ts"
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ enabled: true,
+ pluginsEnabled: true,
+ plugins: [
+ {
+ name: "my-plugin-package",
+ component: "MyPluginComponent",
+ point: "result_meta",
+ position: "after",
+ config: {
+ /* options */
+ },
+ },
+ ],
+ },
+ },
+};
+```
+
+#### Plugin Parameters {#plugin-params}
+
+
+
+
+
**Parameter**
+
**Type**
+
**Description**
+
+
+
+
+
name
+
`string`
+
Required. The name of the plugin npm package.
+
+
+
component
+
`string`
+
The name of the React component exported from the plugin.
+
+
+
point
+
`string`
+
+ Extension point — the place in the interface for the component. See [extension
+ points](../html-reporter-plugins-api#extension-points).
+
+
+
+
position
+
`string`
+
Position relative to the extension point: `"wrap"`, `"before"`, or `"after"`.
+
+
+
config
+
`object`
+
Configuration object passed to the plugin via `pluginOptions.pluginConfig`.
+
+
+
-See more details in the section "[Plugins](../html-reporter-plugins)".
+A plugin with only `name` specified can be used to add server middleware without a UI component.
### customScripts
diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-plugins-api.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-plugins-api.mdx
new file mode 100644
index 0000000..c6c3c32
--- /dev/null
+++ b/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-plugins-api.mdx
@@ -0,0 +1,271 @@
+---
+sidebar_position: 3
+sidebar_label: Plugins SDK
+sidebar_class_name: hidden
+---
+
+# Plugins SDK для HTML Reporter
+
+Справочник по доступным зависимостям, компонентам SDK и точкам расширения для разработки плагинов.
+
+## Доступные зависимости
+
+Плагины могут использовать следующие зависимости, предоставляемые HTML Reporter во время выполнения. Эти зависимости не нужно включать в бандл — они будут переданы через wrapper-функцию.
+
+| Зависимость | Описание |
+| ------------------------------ | --------------------------------------------- |
+| `@gravity-ui/icons` | [Иконки Gravity UI][gravity-ui-icons] |
+| `@gravity-ui/uikit` | Компоненты [Gravity UI][gravity-ui] |
+| `axios` | HTTP-клиент для запросов к серверу |
+| `classnames` | Утилита для работы с CSS-классами |
+| `html-reporter/plugins-sdk` | SDK для серверной части (ExtensionPointName) |
+| `html-reporter/plugins-sdk/ui` | SDK для UI-компонентов |
+| `immer` | Иммутабельные обновления состояния |
+| `lodash` | Утилиты для работы с данными |
+| `react` | React 18 |
+| `react-dom` | React DOM |
+| `react-redux` | React-биндинги для Redux |
+| `react/jsx-runtime` | JSX Runtime |
+| `redux` | Redux для управления состоянием |
+| `redux-thunk` | Middleware для асинхронных действий (встроен) |
+| `reselect` | Мемоизированные селекторы для Redux |
+
+## Plugins SDK UI {#plugins-sdk-ui}
+
+Модуль `html-reporter/plugins-sdk/ui` экспортирует компоненты и типы для создания UI плагинов.
+
+### CollapsibleSection
+
+Раскрывающаяся секция, интегрированная с Redux-состоянием отчета.
+
+```typescript
+import { CollapsibleSection } from "html-reporter/plugins-sdk/ui";
+
+interface CollapsibleSectionProps {
+ /** Уникальный идентификатор секции */
+ id: string;
+ /** Заголовок секции */
+ title: string;
+ /** Содержимое секции */
+ children?: ReactNode;
+ /** CSS-класс */
+ className?: string;
+ /** Раскрыта ли секция по умолчанию */
+ defaultExpanded?: boolean;
+ /** Колбэк при изменении состояния */
+ onUpdate?: (expanded: boolean) => void;
+}
+```
+
+Пример использования:
+
+```tsx
+ {
+ if (expanded) {
+ // Загрузить данные при раскрытии
+ }
+ }}
+>
+
Содержимое секции
+
+```
+
+### PanelSection
+
+Секция для панели настроек.
+
+```typescript
+import { PanelSection } from "html-reporter/plugins-sdk/ui";
+
+interface PanelSectionProps {
+ /** Заголовок секции */
+ title: ReactNode;
+ /** Описание */
+ description?: ReactNode;
+ /** Содержимое */
+ children?: ReactNode;
+}
+```
+
+### State
+
+Тип корневого состояния Redux store.
+
+```typescript
+import { State } from "html-reporter/plugins-sdk/ui";
+
+// Используйте для типизации селекторов
+const mySelector = (state: State) => state.tree.results.byId;
+```
+
+### Features
+
+Флаги доступных функций отчета.
+
+```typescript
+import { Features } from "html-reporter/plugins-sdk/ui";
+
+const availableFeatures = useSelector(state => {
+ return state.app.availableFeatures;
+});
+if (!availableFeatures.some(feature => feature.name === Features.RunTestsFeature.name)) {
+ return null;
+}
+```
+
+## Объект pluginOptions {#plugin-options}
+
+В UI-компоненте плагина доступен глобальный объект `pluginOptions`:
+
+```typescript
+declare const pluginOptions: {
+ /** Имя плагина (из конфигурации) */
+ pluginName: string;
+ /** Конфигурация плагина (поле config из конфигурации) */
+ pluginConfig: object;
+ /** Префикс для серверных эндпоинтов: /plugin-routes/{pluginName}/ */
+ pluginServerEndpointPrefix: string;
+ /** Redux actions отчета */
+ actions: object;
+ /** Имена actions отчета */
+ actionNames: object;
+ /** Селекторы Redux Store, см. html-reporter/lib/static/modules/selectors */
+ selectors: object;
+};
+```
+
+## Точки расширения {#extension-points}
+
+Точки расширения определяют, где в интерфейсе отчета будет размещен компонент плагина.
+
+| Точка | Описание | Props компонента |
+| ------------------ | ----------------------------------------------- | ---------------------------- |
+| `result_meta` | Область результата теста, возле мета-информации | `result: ReporterTestResult` |
+| `settings-panel` | Панель настроек | — |
+| `run-test-options` | Опции запуска теста, возле кнопки запуска теста | — |
+
+### ExtensionPointName
+
+Используйте enum для указания точки расширения в пресете:
+
+```typescript
+import { ExtensionPointName } from "html-reporter/plugins-sdk";
+
+// Доступные значения:
+ExtensionPointName.ResultMeta; // "result_meta"
+ExtensionPointName.MenuBar; // "menu-bar"
+ExtensionPointName.Root; // "root"
+```
+
+### Позиционирование
+
+Параметр `position` определяет размещение компонента относительно точки расширения:
+
+| Значение | Описание |
+| ---------- | ------------------------------------ |
+| `"before"` | Перед содержимым точки расширения |
+| `"after"` | После содержимого точки расширения |
+| `"wrap"` | Обернуть содержимое точки расширения |
+
+## CSS и стилизация {#css-styling}
+
+### CSS Modules
+
+Рекомендуется использовать CSS Modules для изоляции стилей:
+
+```css title="Plugin.module.css"
+.container {
+ padding: 16px;
+}
+
+.result {
+ display: flex;
+ gap: 8px;
+}
+```
+
+```tsx
+import styles from "./Plugin.module.css";
+
+
+
...
+
;
+```
+
+### CSS-переменные Gravity UI
+
+HTML Reporter использует [тему Gravity UI][gravity-ui-theme]. Вы можете использовать CSS-переменные для согласованности стилей:
+
+```css
+.myElement {
+ /* Цвета текста */
+ color: var(--g-color-text-primary);
+ color: var(--g-color-text-secondary);
+ color: var(--g-color-text-brand);
+ color: var(--g-color-text-danger);
+
+ /* Цвета фона */
+ background: var(--g-color-base-background);
+ background: var(--g-color-base-brand);
+
+ /* Границы */
+ border-color: var(--g-color-line-generic);
+
+ /* Отступы и размеры */
+ padding: var(--g-spacing-2); /* 8px */
+ padding: var(--g-spacing-4); /* 16px */
+}
+```
+
+### Инъекция CSS в бандл
+
+Используйте плагин `vite-plugin-css-injected-by-js` для включения CSS в JavaScript-бандл:
+
+```typescript title="vite.config.ts"
+import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
+
+export default defineConfig({
+ plugins: [cssInjectedByJsPlugin()],
+});
+```
+
+## Типизация {#typing}
+
+### Расширение DefaultRootState
+
+Для типизации состояния плагина в Redux, расширьте `DefaultRootState`:
+
+```typescript title="types.d.ts"
+import type { State } from "html-reporter/plugins-sdk/ui";
+
+interface MyPluginState {
+ data: Record;
+}
+
+declare module "react-redux" {
+ export interface DefaultRootState extends State {
+ plugins: {
+ myPlugin: MyPluginState;
+ };
+ }
+}
+```
+
+### Глобальный pluginOptions
+
+```typescript title="types.d.ts"
+declare global {
+ const pluginOptions: {
+ pluginConfig: MyPluginConfig;
+ pluginServerEndpointPrefix: string;
+ };
+}
+```
+
+[gravity-ui]: https://gravity-ui.com/
+[gravity-ui-icons]: https://gravity-ui.com/icons
+[gravity-ui-theme]: https://gravity-ui.com/design/themes
diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-plugins.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-plugins.mdx
index 6c373c8..5bc2fa1 100644
--- a/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-plugins.mdx
+++ b/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-plugins.mdx
@@ -1,301 +1,255 @@
-# Плагины для отчета
+import Admonition from "@theme/Admonition";
-## Обзор {#overview}
+# Разработка плагинов
-Используйте опцию `plugins` в конфиге плагина `html-reporter`, чтобы расширить функциональность отчета с помощью собственных плагинов к отчету.
+Плагины позволяют добавлять собственные UI-компоненты в интерфейс HTML Reporter. Например, вы можете показать статистику стабильности теста или добавить кнопку для интеграции с внешним сервисом. В HTML Reporter есть несколько точек расширения, в которых может отображаться UI плагина — например, на панели настроек или на странице результатов прогона теста.
-Чтобы ваши плагины в отчете заработали, включите опцию [pluginsEnabled][plugins-enabled] в конфиге плагина `html-reporter`, установив её значение в `true`.
+## Быстрый старт
-Список плагинов задается в виде массива с их описаниями. По умолчанию список считается пустым: `[]`.
+Полностью рабочий плагин, в котором настроена сборка и используются основные возможности плагинной системы, доступен в [репозитории HTML Reporter](https://github.com/gemini-testing/html-reporter/tree/master/examples/random-number-plugin-example/).
-Плагины позволяют добавить в отчет собственные UI-компоненты (как для статического отчета, так и для GUI-режима), а также серверные «ручки» _(routes)_ (для GUI-режима).
+Мы рекомендуем использовать этот пример как шаблон для своего плагина.
-## Настройка {#setup}
+## Как работают плагины
-Описание плагинов выглядит следующим образом:
+Плагины подключаются к HTML Reporter в конфиге, например:
-```javascript
-plugins: [
- {
- name: "plugin-name",
- component: "PluginReactComponentName",
- point: "extension-point-name",
- position: "wrap",
- config: { param: "value" },
+```typescript title="testplane.config.ts"
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ pluginsEnabled: true,
+ plugins: [
+ {
+ name: "my-plugin-package",
+ component: "MyPlugin",
+ point: "result_meta",
+ position: "after",
+ },
+ ],
+ },
},
- {
- name: "plugin-name",
- component: "AnotherPluginReactComponentName",
- point: "extension-point-name",
- position: "before",
- },
-
- // ...
-];
+};
```
-### Расшифровка параметров конфигурации {#setup_description}
+В этом случае HTML Reporter будет искать плагин в npm-пакете `my-plugin-package`, а именно:
-
-
-
**Параметр**
**Тип**
**Описание**
-
-
-
[name](#name)
String
Обязательный параметр. Имя пакета с плагином для отчета. Предполагается, что плагин можно будет подключить с помощью _require(name)_.
-
[component](#component)
String
Имя React-компонента из плагина.
-
[point](#point)
String
Имя точки расширения в плагине _html-reporter_.
-
[position](#position)
String
Определяет способ, с помощью которого компонент будет размещен в точке расширения.
-
[config](#config)
Object
Конфигурация плагина.
+- В `my-plugin-package/plugin.js` HTML Reporter будет искать реализацию компонента `MyPlugin`, который будет отображаться в точке расширения `result_meta`
+- В `my-plugin-package/middleware.js` HTML Reporter будет искать реализацию серверных эндпоинтов
-
-
+Поэтому типичный плагин состоит из трёх частей:
-Плагин, для которого задан только параметр `name`, может быть использован для переопределения существующей мидлвари GUI-сервера.
+```
+my-plugin/
+├── ui/ # UI плагина — собирается в бандл plugin.js с помощью Vite
+├── server/ # Серверная часть плагина (опционально) — входная точка ожидается в файле middleware.js
+└── preset-for-config/ # Пресет для удобного подключения (опционально)
+```
-Плагин может определять больше одного компонента. Каждый компонент может быть применен к нескольким точкам расширения и/или несколько раз к одной и той же точке (с отдельными конфигурационными записями). Порядок применения компонентов определяется порядком конфигурации.
+## Создание UI плагина
-### name
+### 1. Настройка сборки
-Обязательный параметр. Имя пакета с плагином для отчета. Предполагается, что плагин можно будет подключить с помощью _require(name)_.
+#### Формат выходного файла
-### component
+Результатом сборки UI плагина должен быть 1 файл — бандл `plugin.js` следующего формата:
-Имя React-компонента из плагина.
+```javascript title="ui/build/plugin.js"
+__testplane_html_reporter_register_plugin__([
+ "react",
+ function (React, options) {
+ // ...
+ return { MyPlugin, reducers: [] };
+ },
+]);
+```
-### point
+Файл должен содержать только вызов функции `__testplane_html_reporter_register_plugin__`.
-Имя точки расширения в плагине _html-reporter_.
+Единственный аргумент функции — массив. В нём декларируются нужные плагину зависимости (доступные зависимости см. в [справочнике по Plugins SDK][plugins-sdk-reference]), последний элемент массива — функция, она будет вызвана с перечисленными зависимостями и должна вернуть объект с компонентом и редьюсерами.
-Определяет конкретное месторасположение указанного компонента внутри пользовательского интерфейса html-отчета.
+Подробнее о том, с чем именно вызывается эта функция, см. в [исходном коде HTML Reporter](https://github.com/gemini-testing/html-reporter/blob/885b2208e3fa2aeb1888d4a674e302b072c67e26/lib/static/modules/load-plugin.js#L107).
-Подробнее смотрите в разделе «Точки расширения».
+#### Переиспользование зависимостей
-### position
+Для корректной работы React и хуков критично, чтобы зависимости не дублировались, а везде использовались одни и те же экземпляры — и в HTML Reporter, и в плагине.
-Определяет способ, с помощью которого компонент будет размещен в точке расширения пользовательского интерфейса html-отчета.
+HTML Reporter ряд зависимостей, доступных для переиспользования, включая React и Gravity UI.
-Доступны следующие значение:
+Чтобы переиспользовать эти зависимости, нужно указать их в `external` в конфигурации Vite.
-
-
-
**Значение**
**Описание**
-
-
-
wrap
обернуть точку расширения в UI
-
before
разместить компонент перед точкой расширения
-
after
разместить компонент после точки расширения
+#### Пример конфигурации Vite
-
-
+На практике нужные характеристики бандла достигаются с помощью сборки через Vite с `external` зависимостями и специальной обёрткой, пример можно посмотреть в [репозитории HTML Reporter](https://github.com/gemini-testing/html-reporter/tree/master/examples/random-number-plugin-example/ui/vite.config.ts).
-### config
+### 2. Реализация компонента
-Конфигурация плагина.
+В зависимости от того, какая точка расширения используется, HTML Reporter может передавать в props некоторые данные, например, текущий результат прогона теста (см. подробнее в справочнике по Plugins SDK):
-## Код плагинов для отчета {#plugins_code}
+```tsx title="ui/Plugin.tsx"
+import { Button } from "@gravity-ui/uikit";
-Примеры плагинов можно [посмотреть в функциональных тестах][html-reporter-plugins].
+export const MyPlugin = ({ result }: { result: { id: string; suitePath: string[] } }) => {
+ const fullName = result.suitePath.join(" ");
-Плагин `html-reporter` — это объект с некоторым набором React-компонентов, заданных в виде его ключей, и необязательным ключом `reducers` с массивом redux-редьюсеров для управления состоянием компонентов, которые позже объединяются с помощью [reduce-reducers][reduce-reducers].
+ return (
+
+
Test Full Name: {fullName}
+
+
+ );
+};
+```
-Ожидается, что плагин для отчета будет иметь следующие модульные файлы в корне своего пакета: `plugin.js` и/или `middleware.js`.
+Главный файл плагина можно организовать так:
-### plugin.js
+```typescript title="ui/index.tsx"
+import { MyPlugin } from "./Plugin";
-Опциональный модуль. Файл, который должен экспортировать объект (или набор именованных экспортов) или функцию, возвращающую такой объект или массив с некоторой определенной структурой.
+export default {
+ MyPlugin,
+ reducers: [],
+};
+```
-Можно повторно использовать зависимости `html-reporter` в плагинах (React, Redux и др.). Для этого из модуля должен быть экспортирован массив со списком необходимых зависимостей, за которым следует функция, с переданными ей соответствующими зависимостями, и возвращающая сам плагин.
+При разработке плагинов рекомендуется использовать Gravity UI и компоненты из Plugins SDK для визуальной консистентности с остальной частью интерфейса HTML Reporter.
-Например:
+#### Работа с Redux (опционально)
-```javascript
-import "plugin-styles.css";
+Для хранения и получения данных плагина используйте Redux.
-export default [
- "react",
- function (React, options) {
- class PluginComponent extends React.Component {
- // реализация компонента
- }
+##### Создание actions
- return {
- PluginComponent,
- reducers: [],
- };
- },
-];
+Определите типы действий с уникальным префиксом:
+
+```typescript title="ui/actions.ts"
+export const actions = {
+ LOADING: "plugins/myPlugin/loading",
+ LOADED: "plugins/myPlugin/loaded",
+ ERROR: "plugins/myPlugin/error",
+} as const;
```
-Стили для плагина должны загружаться вместе с `plugin.js`, и итоговый файл должен быть одним бандлом.
+##### Создание thunk для запросов
-Значение, экспортируемое из `plugin.js`, должно передаваться в `__testplane_html_reporter_register_plugin__`.
+Для асинхронных операций используйте thunk-действия:
-Это можно сделать двумя способами.
+```typescript title="ui/actions.ts"
+export const fetchData = (resultId: string) => async dispatch => {
+ dispatch({ type: actions.LOADING, payload: { resultId } });
-Например, настроить сборку _webpack_ так, чтобы она создавала соответствующую библиотеку `jsonp`:
+ const endpoint = `${pluginOptions.pluginServerEndpointPrefix}/data`;
+ const { data } = await axios.get(endpoint);
-```javascript
-// ...
-output: {
- filename: 'plugin.js',
- path: __dirname,
- library: '__testplane_html_reporter_register_plugin__',
- libraryTarget: 'jsonp'
-},
-// ...
+ dispatch({ type: actions.LOADED, payload: { resultId, data } });
+};
```
-Или передать значение, экспортируемое из `plugin.js`, явно:
+Глобальная переменная `pluginOptions.pluginServerEndpointPrefix` содержит базовый URL для запросов к серверу плагина.
-```javascript
-__testplane_html_reporter_register_plugin__([
- "react",
- function (React, options) {
+##### Создание reducer
+
+Reducer обновляет состояние плагина. Используйте Immer для иммутабельных обновлений:
+
+```typescript title="ui/reducers.ts"
+import produce from "immer";
+
+export default produce((draft, action) => {
+ if (!draft.plugins.myPlugin) {
+ draft.plugins.myPlugin = { byResultId: {} };
+ }
+
+ switch (action.type) {
+ case actions.LOADING: {
+ const { resultId } = action.payload;
+ draft.plugins.myPlugin.byResultId[resultId] = {
+ ...defaultResultState,
+ status: "loading",
+ };
+ break;
+ }
// ...
- return { PluginComponent };
- },
-]);
+ }
+});
+```
+
+##### Чтение состояния
+
+Используйте `useSelector` для чтения данных из store:
+
+```tsx
+const data = useSelector(state => state.plugins.myPlugin?.byResultId[result.id]);
```
-### middleware.js
+Подробнее о структуре Redux store см. в [исходном коде HTML Reporter](https://github.com/gemini-testing/html-reporter/blob/885b2208e3fa2aeb1888d4a674e302b072c67e26/lib/static/new-ui/types/store.ts#L257).
-Опциональный модуль. Экспортирует функцию, принимающую `Router` от [express][express]. Ожидается, что «ручки» плагина будут подключены к роутеру. А роутер затем подключается к «ручке» `/plugin-routes/:pluginName/`.
+Имя компонента (`MyPlugin`) должно совпадать с полем `component` в конфигурации плагина.
-```javascript
-module.exports = function (pluginRouter) {
- pluginRouter.get("/plugin-route", function (req, res) {
- // реализация «ручки»
+### 3. Серверная часть (опционально)
+
+Серверная часть получает Express Router с префиксом `/plugin-routes/{plugin-name}/`:
+
+```typescript title="server/index.ts"
+import type { Router } from "express";
+
+export = function (router: Router) {
+ router.get("/data", (req, res) => {
+ res.json({ value: 42 });
});
};
```
-Затем «ручки» могут быть вызваны из React-компонентов плагина, определенных в `plugin.js `. Для удобства имя плагина всегда передается с опциями под названием `pluginName`, когда для экспорта используется функция или массив функций:
+Этот эндпоинт будет доступен по адресу `/plugin-routes/my-plugin/data`.
-```javascript
-export default ['react', 'axios', function(React, axios, { pluginName, pluginConfig, actions, actionNames, selectors }) {
- class PluginComponent extends React.Component {
- // ... где-то внутри компонента ...
- const result = await axios.get(`/plugin-routes/${pluginName}/plugin-route`);
- }
+Рекомендуется получать адрес серверной части из глобальной переменной `pluginOptions.pluginServerEndpointPrefix`, так название плагина трансформируется на стороне HTML Reporter и может не совпадать с именем пакета.
- return {
- PluginComponent,
- reducers: []
- };
-}
-```
+### 4. Пресет конфигурации (опционально)
-В этом примере также можно увидеть следующие свойства:
-
-
-
-
**Свойство**
**Описание**
-
-
-
pluginName
имя плагина
-
pluginConfig
конфигурация плагина
-
actions
Redux-действия
-
actionNames
имена действий в _html-reporter_, которые используются в Redux-действиях, чтобы иметь возможность подписаться на события отчета
-
selectors
закэшированные селекторы отчета, которые были созданы с помощью библиотеки [reselect][redux-reselect]
-
-
-
-
-### Доступные зависимости {#available_deps}
-
-В плагинах доступны следующие зависимости:
-
-- [react][react]
-- [redux][redux]
-- [react-redux][react-redux]
-- [lodash][lodash]
-- [prop-types][prop-types]
-- [classnames][classnames]
-- [semantic-ui-react][semantic-ui-react]
-- [react-markdown][react-markdown]
-- [reduce-reducers][reduce-reducers]
-- [immer][immer]
-- [reselect][redux-reselect]
-- [axios][axios]
-
-### Доступные компоненты {#available_components}
-
-#### ``
-
-Компонент, с помощью которого можно переключать отображение контента (аналог ката).
-
-Пример использования:
-
-```javascript
-// ...внутри вашего React-компонента
-
-render() {
- return console.log('clicked')} // а также свой обработчик
- />
-}
-```
+Пресет упрощает подключение плагина для пользователей:
-где:
+```typescript title="preset-for-config/index.ts"
+import { ExtensionPointName } from "html-reporter/plugins-sdk";
-
-
-
**Свойство**
**Тип**
**Описание**
-
-
-
title
String или JSX.Element
Обязательный параметр. Заголовок, описывающий информацию, скрытую под ним.
-
content
Function или String или String[] или JSX.Element
Обязательный параметр. Контент, который будет появляться по нажатию на заголовок.
-
extendClassNames
String или String[]
Css-классы, которые нужно добавить к компоненту. Необязательный параметр.
-
onClick
Function
Обработчик, который будет вызван по нажатию на заголовок. Необязательный параметр.
+Благодаря пресету вместо того, чтобы указывать в конфиге полный дескриптор плагина, пользователи смогут импортировать этот объект и использовать его.
-## Точки расширения {#extension_points}
+### 5. Подключение плагина
-Точки расширения — это места в пользовательском интерфейсе отчета, которые доступны для расширения с помощью React-компонентов, экспортируемых _плагинами для отчета_.
+После публикации пользователи подключают плагин так:
-Каждая точка расширения может передавать определенные props'ы компонентам плагина в зависимости от самой точки. Поскольку некоторые плагины могут полагаться на конкретное размещение и, следовательно, на конкретные props'ы, то можно ограничить компоненты плагина определенными точками расширения, указав статическое свойство `point` для таких компонентов плагина:
+```typescript title="testplane.config.ts"
+import myPlugin from "my-plugin-package";
-```javascript
-class PluginComponent extends React.Component {
- static point = "result";
- // ...
-}
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ pluginsEnabled: true,
+ plugins: myPlugin(),
+ },
+ },
+};
```
-В данный момент доступны следующие точки расширения:
-
-
-
-
**Точка**
**Описание**
-
-
-
result
Позволяет расширить каждый результат теста. Добавляет props'ы _resultId_ и _testName_ в компонент плагина.
-
result_meta
Позволяет расширить мета-информацию для каждого результата теста. Добавляет props'ы _resultId_ и _testName_ в компонент плагина.
-
menu-bar
Позволяет расширить меню.
-
root
Позволяет добавить такие плавающие элементы, как модальное окно или попап.
-
-
-
-
-Точка расширения может быть расширена более чем одним компонентом. В этом случае порядок применения компонентов определяется порядком настройки плагинов. Каждый следующий компонент применяется ко всем ранее составленным компонентам в точке расширения.
-
-[plugins-enabled]: ../html-reporter-setup#pluginsenabled
-[html-reporter-plugins]: https://github.com/gemini-testing/html-reporter/blob/master/test/func/fixtures/plugins
-[reduce-reducers]: https://github.com/redux-utilities/reduce-reducers
-[express]: https://github.com/expressjs/express
-[redux-reselect]: https://github.com/reduxjs/reselect
-[react]: https://github.com/facebook/react
-[redux]: https://github.com/reduxjs/redux
-[react-redux]: https://github.com/reduxjs/react-redux
-[lodash]: https://github.com/lodash/lodash
-[prop-types]: https://github.com/facebook/prop-types
-[classnames]: https://github.com/JedWatson/classnames
-[semantic-ui-react]: https://github.com/Semantic-Org/Semantic-UI-React
-[react-markdown]: https://github.com/remarkjs/react-markdown
-[immer]: https://github.com/immerjs/immer
-[axios]: https://github.com/axios/axios
+### Дополнительные материалы
+
+- [API-справочник](../html-reporter-plugins-api) — зависимости, компоненты SDK, точки расширения
+- [Конфигурация плагинов](../html-reporter-setup#plugins) — параметры подключения
+- [Пример плагина][example-plugin] — полный рабочий код
+
+[example-plugin]: https://github.com/gemini-testing/html-reporter/tree/master/examples/random-number-plugin-example
+[gravity-ui]: https://gravity-ui.com/
+[plugins-sdk-reference]: ../html-reporter-plugins-api
diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-setup.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-setup.mdx
index 9d462dc..22945ae 100644
--- a/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-setup.mdx
+++ b/i18n/ru/docusaurus-plugin-content-docs/current/html-reporter/html-reporter-setup.mdx
@@ -1,11 +1,10 @@
-import Version from "../_partials/specs/version.mdx";
-
---
-
-## sidebar_position: 2
+sidebar_position: 2
+---
import Admonition from "@theme/Admonition";
import ConfigExamples from "../_partials/html-reporter-config-examples.mdx";
+import Version from "../_partials/specs/version.mdx";
# Конфигурация
@@ -238,13 +237,103 @@ throw err;
### pluginsEnabled
-Включить плагины для `html-reporter`.
+Включить плагины для `html-reporter`. По умолчанию: `false`.
### plugins
-Список плагинов с их настройками.
+Список плагинов с их настройками. По умолчанию: `[]`.
+
+Плагины позволяют расширять интерфейс отчета собственными UI-компонентами. Подробнее о разработке плагинов — в разделе «[Разработка плагинов](../html-reporter-plugins)».
+
+#### Использование с пресетом {#plugins-with-preset}
+
+Если плагин предоставляет пресет конфигурации, подключение выглядит так:
+
+```typescript title="testplane.config.ts"
+import myPlugin from "my-plugin-package";
+
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ enabled: true,
+ pluginsEnabled: true,
+ plugins: myPlugin({
+ /* опции плагина */
+ }),
+ },
+ },
+};
+```
+
+#### Ручная конфигурация {#plugins-manual-config}
+
+Плагины можно настроить вручную, указав массив объектов:
+
+```typescript title="testplane.config.ts"
+export default {
+ plugins: {
+ "html-reporter/testplane": {
+ enabled: true,
+ pluginsEnabled: true,
+ plugins: [
+ {
+ name: "my-plugin-package",
+ component: "MyPluginComponent",
+ point: "result_meta",
+ position: "after",
+ config: {
+ /* опции */
+ },
+ },
+ ],
+ },
+ },
+};
+```
+
+#### Параметры плагина {#plugin-params}
+
+
+
+
+
**Параметр**
+
**Тип**
+
**Описание**
+
+
+
+
+
name
+
`string`
+
Обязательный. Имя npm-пакета плагина.
+
+
+
component
+
`string`
+
Имя React-компонента, экспортируемого из плагина.
+
+
+
point
+
`string`
+
+ Точка расширения — место в интерфейсе для размещения компонента. См. [точки
+ расширения](../html-reporter-plugins-api#extension-points).
+
+
+
+
position
+
`string`
+
Позиция относительно точки расширения: `"wrap"`, `"before"` или `"after"`.
+
+
+
config
+
`object`
+
Объект конфигурации, передаваемый в плагин через `pluginOptions.pluginConfig`.
+
+
+
-Смотрите подробнее в разделе «[Плагины для отчета](../html-reporter-plugins)».
+Плагин с указанным только `name` может использоваться для добавления серверного middleware без UI-компонента.
### customScripts
diff --git a/sidebars.ts b/sidebars.ts
index ed01678..a1db8c9 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -88,6 +88,7 @@ const sidebars: SidebarsConfig = {
items: [
{ type: "doc", id: "html-reporter/html-reporter-api" },
{ type: "doc", id: "html-reporter/html-reporter-events" },
+ { type: "doc", id: "html-reporter/html-reporter-plugins-api" },
],
},
],