diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 13ee1a905..000000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -# These files should be considered handlebars templates and can cause eslint to error. -/packages/create-plugin/templates diff --git a/CHANGELOG.md b/CHANGELOG.md index e22dbd39f..7b9971dcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,30 @@ +# (Fri Jan 24 2025) + +#### πŸ› Bug Fix + +- `@grafana/plugin-e2e@1.16.2` + - fix(deps): update dependency @grafana/e2e-selectors to ^11.5.0-219238 [#1477](https://github.com/grafana/plugin-tools/pull/1477) ([@renovate[bot]](https://github.com/renovate[bot])) + +#### Authors: 1 + +- [@renovate[bot]](https://github.com/renovate[bot]) + +--- + +# (Fri Jan 24 2025) + +#### πŸ› Bug Fix + +- `@grafana/plugin-e2e@1.16.1` + - fix(deps): update dependency @grafana/e2e-selectors to ^11.5.0-218582 [#1469](https://github.com/grafana/plugin-tools/pull/1469) ([@renovate[bot]](https://github.com/renovate[bot]) [@sunker](https://github.com/sunker)) + +#### Authors: 2 + +- [@renovate[bot]](https://github.com/renovate[bot]) +- Erik Sundell ([@sunker](https://github.com/sunker)) + +--- + # (Wed Jan 22 2025) #### πŸš€ Enhancement diff --git a/docusaurus/docs/how-to-guides/runtime-checks.md b/docusaurus/docs/how-to-guides/runtime-checks.md new file mode 100644 index 000000000..fd04d3726 --- /dev/null +++ b/docusaurus/docs/how-to-guides/runtime-checks.md @@ -0,0 +1,126 @@ +--- +id: runtime-checks +title: Manage backwards compatibility with runtime checks +description: How to manage backwards compatibility with runtime checks. +keywords: + - grafana + - plugins + - plugin + - compatibility +--- + +# Manage backwards compatibility with runtime checks + +Most Grafana NPM dependencies used in plugins are shared with the Grafana application at runtime, as detailed in the Manage NPM Dependencies article. To take advantage of new Grafana features in plugins while maintaining compatibility with older versions, plugin authors need to implement conditional logic that checks for feature availability during runtime. Failing to account for backward compatibility can result in plugin crashes and a poor user experience. + +The method for performing these runtime checks varies depending on the feature and how it is made available to plugin developers. The following examples demonstrate best practices for handling these scenarios effectively. + +## Example: Conditionally invoke functions + +Grafana 10.1.0 introduced the `createDataFrame` function in the `@grafana/data` package, deprecatiing the `MutableDataFrame` class. To maintain compatibility with Grafana versions prior to 10.1.0, plugins must implement conditional logic to determine whether these APIs are available at runtime. + +```tsx +import { createDataFrame, DataFrameDTO, MutableDataFrame } from '@grafana/data'; + +function getDataFrame(data: DataFrameDTO) { + if (typeof createDataFrame === 'undefined') { + // fallback to the deprecated class for older versions + return new MutableDataFrame(data); + } else { + // use the new API if available + return createDataFrame(data); + } +} +``` + +## Example: Conditionally use React hooks + +In Grafana 11.1.0, the synchronous `getPluginLinkExtensions` function was deprecated and replaced by the reactive `usePluginLinks` hook. The following example demonstrates how to dynamically switch between the two APIs based on their availability. + +```tsx +import { useMemo } from 'react'; +import { PluginExtensionLink } from '@grafana/data'; +import { + GetPluginExtensionsOptions, + getPluginLinkExtensions, + usePluginLinks as usePluginLinksOriginal, +} from '@grafana/runtime'; + +function useLegacyLinkExtensions({ context, extensionPointId }: GetPluginExtensionsOptions): { + links: PluginExtensionLink[]; + isLoading: boolean; +} { + const { extensions } = useMemo( + () => + getPluginLinkExtensions({ + extensionPointId, + context, + }), + [context, extensionPointId] + ); + + return { + links: extensions, + isLoading: false, + }; +} + +// dynamically decide which API to use +const usePluginLinks = usePluginLinksOriginal !== undefined ? usePluginLinksOriginal : useLegacyLinkExtensions; + +export function ToolbarExtensionPoint() { + const { links, isLoading } = usePluginLinks({ extensionPointId: 'myorg-foo-app/toolbar/v1' }); + + // Your implementation here + ... +} +``` + +## Example: Conditionally render a React component + +The `UserIcon` component was introduced in Grafana 10.1.0 and has no equivalent in earlier versions. To maintain compatibility, render the UserIcon component only if it is available in the current runtime environment. + +```tsx +import React from 'react'; +import { Card, UserIcon, UserView } from '@grafana/ui'; + +export const Profile = ({ userView }: { userView: UserView }) => { + return ( + + Profile + {['Tag 1']} + {/* Conditionally render the UserIcon component if it exists */} + {UserIcon && } + + ); +}; +``` + +## Example: Cover conditional rendering in an end-to-end test + +When a feature is only available in certain Grafana versions, it’s a good practice to validate its conditional rendering through end-to-end (E2E) tests. These tests ensure that the plugin behaves correctly in both newer environments where the feature exists and older environments where it is unavailable. + +The following example tests whether the `UserIcon` component is rendered only in Grafana 10.1.0 or later, while ensuring that the rest of the user profile is always displayed. + +```tsx +import * as semver from 'semver'; +import { test, expect } from '@grafana/plugin-e2e'; + +test('should render profile', async ({ page, grafanaVersion }) => { + const userProfile = page.getByTestId('user-profile'); + + // verify the visibility of shared components + await expect(userProfile.getByText('Heading')).toBeVisible(); + await expect(userProfile.getByText('Tag 1')).toBeVisible(); + + // conditionally validate the rendering of the UserIcon component + if (semver.gte(grafanaVersion, '10.1.0')) { + await expect(userProfile.getByText('Jane Doe')).toBeVisible(); + } +}); +``` + +### Further reading + +- **end-to-end testing for plugins**: For comprehensive guidance on writing and running E2E tests for Grafana plugins, refer to the [documentation](../e2e-test-a-plugin/introduction.md). +- **Running end-to-end tests across multiple Grafana versions**: To learn how to configure your workflows to test plugins against different Grafana versions, see the [example workflows](../e2e-test-a-plugin/ci.md). diff --git a/eslint.config.js b/eslint.config.js index b7528ade8..d0db6435c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,20 +1,29 @@ // @ts-check const grafanaConfig = require('@grafana/eslint-config/flat'); +// If you edit this config consider running `npx -y @eslint/config-inspector@latest` first. + /** * @type {Array} */ module.exports = [ { - files: ['**/*.{ts,tsx,js}'], + name: 'plugin-tools/ignores', ignores: [ '.github', - '.yarn', + '.nx/**', '**/.*', // dotfiles aren't ignored by default in FlatConfig, + 'packages/**/dist/**', + 'packages/create-plugin/templates/**', ], }, + { + name: 'plugin-tools/defaults', + files: ['**/*.{ts,tsx,js}'], + }, grafanaConfig, { + name: 'plugin-e2e/overrides', rules: { 'react/prop-types': 'off', 'react-hooks/rules-of-hooks': 'off', diff --git a/nx.json b/nx.json index b61c9a729..c2eb46891 100644 --- a/nx.json +++ b/nx.json @@ -7,23 +7,21 @@ "cache": true }, "typecheck": { - "inputs": ["default", "{workspaceRoot}/tsconfig.base.json"], + "inputs": ["default", "{projectRoot}/tsconfig.json", "{workspaceRoot}/tsconfig.base.json"], "cache": true }, "lint": { - "inputs": ["default", "{workspaceRoot}/.eslintrc"], + "inputs": ["default", "{workspaceRoot}/eslint.config.js"], "cache": true }, "test": { - "inputs": ["default", "{projectRoot}/jest.config.js", "{workspaceRoot}/jest.config.base.js"], + "inputs": ["default", "{projectRoot}/vitest.config.ts", "{workspaceRoot}/vitest.config.base.ts"], "cache": true } }, "namedInputs": { "sharedGlobals": ["{workspaceRoot}/.github/workflows/ci.yml"] }, - "affected": { - "defaultBase": "main" - }, + "defaultBase": "main", "nxCloudAccessToken": "ZDU3OTNkMTItNWIwZi00N2U4LTk2MjYtNzJkYzA0YzgwNWNlfHJlYWQ=" } diff --git a/package-lock.json b/package-lock.json index dd26c9ea7..87580a163 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,22 +24,22 @@ "@swc/core": "^1.10.9", "@tsconfig/node20": "^20.1.4", "@tsconfig/recommended": "^1.0.8", - "@types/node": "22.10.9", + "@types/node": "22.10.10", "@typescript-eslint/eslint-plugin": "^8.21.0", "@typescript-eslint/parser": "^8.21.0", "auto": "11.3.0", - "eslint": "^9.18.0", + "eslint": "^9.19.0", "eslint-config-prettier": "^10.0.1", - "eslint-plugin-jsdoc": "^50.6.2", + "eslint-plugin-jsdoc": "^50.6.3", "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", "husky": "^9.1.7", "lerna": "^8.1.9", - "lint-staged": "^15.4.2", + "lint-staged": "^15.4.3", "nodemon": "^3.1.9", "prettier": "3.4.2", "typescript": "^5.7.3", - "vitest": "^3.0.3" + "vitest": "^3.0.4" }, "engines": { "node": ">=20" @@ -5550,9 +5550,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "devOptional": true, "license": "MIT", "engines": { @@ -5588,9 +5588,9 @@ "link": true }, "node_modules/@grafana/e2e-selectors": { - "version": "11.5.0-216908", - "resolved": "https://registry.npmjs.org/@grafana/e2e-selectors/-/e2e-selectors-11.5.0-216908.tgz", - "integrity": "sha512-UnA+8xpw0Ib1jwgpl0aovOG7F+DXgTlrDGj/I2ekapLizHqzQYsObx71t/d64wBEk8Y5ILrfk4h5DkC2r83x1A==", + "version": "11.5.0-219423", + "resolved": "https://registry.npmjs.org/@grafana/e2e-selectors/-/e2e-selectors-11.5.0-219423.tgz", + "integrity": "sha512-SO+XU9Sn7dTM+Lvpw/iFdFFSteLMp83iFtgJazVP5XV0HwX9guVHhC2esXO7KLvmxNHU4OdGZzOWEFFJofE3lg==", "license": "Apache-2.0", "dependencies": { "@grafana/tsconfig": "^2.0.0", @@ -8294,13 +8294,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", - "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.0.tgz", + "integrity": "sha512-ZGNXbt+d65EGjBORQHuYKj+XhCewlwpnSd/EDuLPZGSiEWmgOJB5RmMCCYGy5aMfTs9wx61RivfDKi8H/hcMvw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.1" + "playwright": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -9894,7 +9894,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.10", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "license": "MIT", "dependencies": { "@types/ms": "*" @@ -10107,9 +10109,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.9.tgz", - "integrity": "sha512-Ir6hwgsKyNESl/gLOcEz3krR4CBGgliDqBQ2ma4wIhEx0w+xnoeTq3tdrNw15kU3SxogDjOgv9sqdtLW8mIHaw==", + "version": "22.10.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz", + "integrity": "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -10529,14 +10531,14 @@ "license": "ISC" }, "node_modules/@vitest/expect": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz", - "integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.4.tgz", + "integrity": "sha512-Nm5kJmYw6P2BxhJPkO3eKKhGYKRsnqJqf+r0yOGRKpEP+bSCBDsjXgiu1/5QFrnPMEgzfC38ZEjvCFgaNBC0Eg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/spy": "3.0.4", + "@vitest/utils": "3.0.4", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" }, @@ -10545,13 +10547,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz", - "integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.4.tgz", + "integrity": "sha512-gEef35vKafJlfQbnyOXZ0Gcr9IBUsMTyTLXsEQwuyYAerpHqvXhzdBnDFuHLpFqth3F7b6BaFr4qV/Cs1ULx5A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", + "@vitest/spy": "3.0.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -10572,9 +10574,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz", - "integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.4.tgz", + "integrity": "sha512-ts0fba+dEhK2aC9PFuZ9LTpULHpY/nd6jhAQ5IMU7Gaj7crPCTdCFfgvXxruRBLFS+MLraicCuFXxISEq8C93g==", "dev": true, "license": "MIT", "dependencies": { @@ -10585,38 +10587,38 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz", - "integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.4.tgz", + "integrity": "sha512-dKHzTQ7n9sExAcWH/0sh1elVgwc7OJ2lMOBrAm73J7AH6Pf9T12Zh3lNE1TETZaqrWFXtLlx3NVrLRb5hCK+iw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.3", - "pathe": "^2.0.1" + "@vitest/utils": "3.0.4", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz", - "integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.4.tgz", + "integrity": "sha512-+p5knMLwIk7lTQkM3NonZ9zBewzVp9EVkVpvNta0/PlFWpiqLaRcF4+33L1it3uRUCh0BGLOaXPPGEjNKfWb4w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.4", "magic-string": "^0.30.17", - "pathe": "^2.0.1" + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz", - "integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.4.tgz", + "integrity": "sha512-sXIMF0oauYyUy2hN49VFTYodzEAu744MmGcPR3ZBsPM20G+1/cSW/n1U+3Yu/zHxX2bIDe1oJASOkml+osTU6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -10627,13 +10629,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz", - "integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.4.tgz", + "integrity": "sha512-8BqC1ksYsHtbWH+DfpOAKrFw3jl3Uf9J7yeFh85Pz52IWuh1hBBtyfEbRNNZNjl8H8A5yMLH9/t+k7HIKzQcZQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.4", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" }, @@ -15703,9 +15705,9 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -15714,7 +15716,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", + "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -15776,9 +15778,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.2.tgz", - "integrity": "sha512-n7GNZ4czMAAbDg7DsDA7PvHo1IPIUwAXYmxTx6j/hTlXbt5V0x5q/kGkiJ7s4wA9SpB/yaiK8jF7CO237lOLew==", + "version": "50.6.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.3.tgz", + "integrity": "sha512-NxbJyt1M5zffPcYZ8Nb53/8nnbIScmiLAMdoe0/FAszwb7lcSiX3iYBTsuF7RV84dZZJC8r3NghomrUXsmWvxQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -21892,9 +21894,9 @@ } }, "node_modules/lint-staged": { - "version": "15.4.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.2.tgz", - "integrity": "sha512-gCqzB/Li281uZJgReNci+oXXqUEdrFAQAzTE/LwoxxiEuP41vozNe4BATS+4ehdqkWn+Z6bGc3EDcBja3npBVw==", + "version": "15.4.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.3.tgz", + "integrity": "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==", "dev": true, "license": "MIT", "dependencies": { @@ -27137,9 +27139,9 @@ } }, "node_modules/pathe": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.1.tgz", - "integrity": "sha512-6jpjMpOth5S9ITVu5clZ7NOgHNsv5vRQdheL9ztp2vZmM6fRbLvyua1tiBIL4lk8SAe3ARzeXEly6siXCjDHDw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", "dev": true, "license": "MIT" }, @@ -27398,13 +27400,13 @@ } }, "node_modules/playwright": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", - "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.0.tgz", + "integrity": "sha512-+GinGfGTrd2IfX1TA4N2gNmeIksSb+IAe589ZH+FlmpV3MYTx6+buChGIuDLQwrGNCw2lWibqV50fU510N7S+w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.1" + "playwright-core": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -27417,9 +27419,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", - "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.0.tgz", + "integrity": "sha512-CXkSSlr4JaZs2tZHI40DsZUN/NIwgaUPsyLuOAaIZp2CyF2sN5MM5NJsyB188lFSSozFxQ5fPT4qM+f0tH/6wQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -33929,16 +33931,16 @@ } }, "node_modules/vite-node": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz", - "integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.4.tgz", + "integrity": "sha512-7JZKEzcYV2Nx3u6rlvN8qdo3QV7Fxyt6hx+CCKz9fbWxdX5IvUOmTWEAxMrWxaiSf7CKGLJQ5rFu8prb/jBjOA==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -33964,31 +33966,31 @@ } }, "node_modules/vitest": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz", - "integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.4.tgz", + "integrity": "sha512-6XG8oTKy2gnJIFTHP6LD7ExFeNLxiTkK3CfMvT7IfR8IN+BYICCf0lXUQmX7i7JoxUP8QmeP4mTnWXgflu4yjw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.3", - "@vitest/mocker": "3.0.3", - "@vitest/pretty-format": "^3.0.3", - "@vitest/runner": "3.0.3", - "@vitest/snapshot": "3.0.3", - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/expect": "3.0.4", + "@vitest/mocker": "3.0.4", + "@vitest/pretty-format": "^3.0.4", + "@vitest/runner": "3.0.4", + "@vitest/snapshot": "3.0.4", + "@vitest/spy": "3.0.4", + "@vitest/utils": "3.0.4", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.3", + "vite-node": "3.0.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -34002,9 +34004,10 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.3", - "@vitest/ui": "3.0.3", + "@vitest/browser": "3.0.4", + "@vitest/ui": "3.0.4", "happy-dom": "*", "jsdom": "*" }, @@ -34012,6 +34015,9 @@ "@edge-runtime/vm": { "optional": true }, + "@types/debug": { + "optional": true + }, "@types/node": { "optional": true }, @@ -35102,16 +35108,16 @@ }, "packages/plugin-e2e": { "name": "@grafana/plugin-e2e", - "version": "1.16.0", + "version": "1.16.2", "license": "Apache-2.0", "dependencies": { - "@grafana/e2e-selectors": "^11.5.0-216908", + "@grafana/e2e-selectors": "^11.5.0-219238", "semver": "^7.5.4", "uuid": "^11.0.2", "yaml": "^2.3.4" }, "devDependencies": { - "@playwright/test": "^1.49.1", + "@playwright/test": "^1.50.0", "@types/uuid": "^10.0.0", "dotenv": "^16.4.7" }, @@ -35124,7 +35130,7 @@ }, "packages/plugin-meta-extractor": { "name": "@grafana/plugin-meta-extractor", - "version": "0.1.0", + "version": "0.1.1", "license": "Apache-2.0", "dependencies": { "debug": "^4.3.4", @@ -35135,7 +35141,7 @@ }, "devDependencies": { "@grafana/data": "^11.3.0-199826", - "@types/node": "^22.10.9", + "@types/node": "^22.10.10", "react": "^18.2.0" } }, @@ -35234,12 +35240,12 @@ }, "packages/plugin-types-bundler": { "name": "@grafana/plugin-types-bundler", - "version": "0.2.2", + "version": "0.2.3", "license": "Apache-2.0", "dependencies": { "@grafana/levitate": "^0.15.0", "@types/minimist": "^1.2.2", - "@types/node": "22.10.6", + "@types/node": "22.10.10", "debug": "^4.3.4", "jackw-dts-bundle-gen-test": "^9.5.1", "minimist": "^1.2.8" @@ -35251,21 +35257,6 @@ "node": ">=18.8.0" } }, - "packages/plugin-types-bundler/node_modules/@types/node": { - "version": "22.10.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz", - "integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "packages/plugin-types-bundler/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, "packages/pme": { "name": "@grafana/pme", "version": "1.0.0", diff --git a/package.json b/package.json index 3755bfa08..5c369fa8b 100644 --- a/package.json +++ b/package.json @@ -31,22 +31,22 @@ "@swc/core": "^1.10.9", "@tsconfig/node20": "^20.1.4", "@tsconfig/recommended": "^1.0.8", - "@types/node": "22.10.9", + "@types/node": "22.10.10", "@typescript-eslint/eslint-plugin": "^8.21.0", "@typescript-eslint/parser": "^8.21.0", "auto": "11.3.0", - "eslint": "^9.18.0", + "eslint": "^9.19.0", "eslint-config-prettier": "^10.0.1", - "eslint-plugin-jsdoc": "^50.6.2", + "eslint-plugin-jsdoc": "^50.6.3", "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", "husky": "^9.1.7", "lerna": "^8.1.9", - "lint-staged": "^15.4.2", + "lint-staged": "^15.4.3", "nodemon": "^3.1.9", "prettier": "3.4.2", "typescript": "^5.7.3", - "vitest": "^3.0.3" + "vitest": "^3.0.4" }, "engines": { "node": ">=20" diff --git a/packages/plugin-e2e/CHANGELOG.md b/packages/plugin-e2e/CHANGELOG.md index ef280d707..775d67523 100644 --- a/packages/plugin-e2e/CHANGELOG.md +++ b/packages/plugin-e2e/CHANGELOG.md @@ -1,3 +1,28 @@ +# v1.16.2 (Fri Jan 24 2025) + +#### πŸ› Bug Fix + +- fix(deps): update dependency @grafana/e2e-selectors to ^11.5.0-219238 [#1477](https://github.com/grafana/plugin-tools/pull/1477) ([@renovate[bot]](https://github.com/renovate[bot])) + +#### Authors: 1 + +- [@renovate[bot]](https://github.com/renovate[bot]) + +--- + +# v1.16.1 (Fri Jan 24 2025) + +#### πŸ› Bug Fix + +- fix(deps): update dependency @grafana/e2e-selectors to ^11.5.0-218582 [#1469](https://github.com/grafana/plugin-tools/pull/1469) ([@renovate[bot]](https://github.com/renovate[bot]) [@sunker](https://github.com/sunker)) + +#### Authors: 2 + +- [@renovate[bot]](https://github.com/renovate[bot]) +- Erik Sundell ([@sunker](https://github.com/sunker)) + +--- + # v1.16.0 (Wed Jan 22 2025) #### πŸš€ Enhancement diff --git a/packages/plugin-e2e/package.json b/packages/plugin-e2e/package.json index f9bdaffbe..b1bf9e60d 100644 --- a/packages/plugin-e2e/package.json +++ b/packages/plugin-e2e/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/plugin-e2e", - "version": "1.16.0", + "version": "1.16.2", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ @@ -36,12 +36,12 @@ "@playwright/test": "^1.41.2" }, "devDependencies": { - "@playwright/test": "^1.49.1", + "@playwright/test": "^1.50.0", "@types/uuid": "^10.0.0", "dotenv": "^16.4.7" }, "dependencies": { - "@grafana/e2e-selectors": "^11.5.0-216908", + "@grafana/e2e-selectors": "^11.5.0-219238", "semver": "^7.5.4", "uuid": "^11.0.2", "yaml": "^2.3.4" diff --git a/packages/plugin-e2e/src/models/components/DataSourcePicker.ts b/packages/plugin-e2e/src/models/components/DataSourcePicker.ts index b45bc7886..178dd4991 100644 --- a/packages/plugin-e2e/src/models/components/DataSourcePicker.ts +++ b/packages/plugin-e2e/src/models/components/DataSourcePicker.ts @@ -1,9 +1,13 @@ +import * as semver from 'semver'; import { Locator } from '@playwright/test'; import { PluginTestCtx } from '../../types'; import { GrafanaPage } from '../pages/GrafanaPage'; export class DataSourcePicker extends GrafanaPage { - constructor(ctx: PluginTestCtx, private root?: Locator) { + constructor( + ctx: PluginTestCtx, + private root?: Locator + ) { super(ctx); } @@ -11,9 +15,15 @@ export class DataSourcePicker extends GrafanaPage { * Sets the data source picker to the provided name */ async set(name: string) { - await this.getByGrafanaSelector(this.ctx.selectors.components.DataSourcePicker.container, { root: this.root }) - .locator('input') - .fill(name); + let datasourcePicker = this.ctx.page.getByTestId(this.ctx.selectors.components.DataSourcePicker.inputV2); + + if (semver.lt(this.ctx.grafanaVersion, '10.1.0')) { + datasourcePicker = this.getByGrafanaSelector(this.ctx.selectors.components.DataSourcePicker.container, { + root: this.root, + }).locator('input'); + } + + await datasourcePicker.fill(name); // this is a hack to get the selection to work in 10.ish versions of Grafana. // TODO: investigate if the select component can somehow be refactored so that its easier to test with playwright diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts index 756b1ee95..16b80e5a3 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts @@ -38,6 +38,7 @@ test.describe('Test new alert rules', () => { alertRuleEditPage, selectors, readProvisionedDataSource, + page, }) => { test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); const { rows } = selectors.components.QueryEditorRows; @@ -45,6 +46,7 @@ test.describe('Test new alert rules', () => { const queryA = alertRuleEditPage.getAlertRuleQueryRow('A'); await queryA.datasource.set(ds.name); const rowCount = await alertRuleEditPage.getByGrafanaSelector(rows).count(); + semver.gte(grafanaVersion, '11.5.0') && (await page.getByLabel('Advanced options').nth(1).check()); await alertRuleEditPage.clickAddQueryRow(); await expect(alertRuleEditPage.getByGrafanaSelector(rows)).toHaveCount(rowCount + 1); await alertRuleEditPage.clickAddQueryRow(); diff --git a/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts b/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts index 1d2847a4e..3623c01f4 100644 --- a/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts @@ -141,7 +141,7 @@ test('select timezone in timezone picker', async ({ gotoPanelEditPage, grafanaVe }); test('collapse expanded options group', async ({ gotoPanelEditPage }) => { - const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'eda84f4d-0b3c-4e4d-815d-7fcb9aa702c2' }, id: '1' }); + const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'be6sir7o1iccgb' }, id: '1' }); const dataLinksOptions = panelEdit.getCustomOptions('Data links'); expect(await dataLinksOptions.isExpanded()).toBeTruthy(); @@ -150,7 +150,7 @@ test('collapse expanded options group', async ({ gotoPanelEditPage }) => { }); test('expand collapsed options group', async ({ gotoPanelEditPage }) => { - const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'eda84f4d-0b3c-4e4d-815d-7fcb9aa702c2' }, id: '1' }); + const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'be6sir7o1iccgb' }, id: '1' }); const dataLinksOptions = panelEdit.getCustomOptions('Data links'); expect(await dataLinksOptions.isExpanded()).toBeTruthy(); diff --git a/packages/plugin-meta-extractor/package.json b/packages/plugin-meta-extractor/package.json index 59eb090e5..906d5608f 100644 --- a/packages/plugin-meta-extractor/package.json +++ b/packages/plugin-meta-extractor/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/plugin-meta-extractor", - "version": "0.1.0", + "version": "0.1.1", "description": "Extract meta information from a Grafana plugin source code.", "types": "./dist/index.d.ts", "bin": "./dist/bin/run.js", @@ -38,7 +38,7 @@ }, "devDependencies": { "@grafana/data": "^11.3.0-199826", - "@types/node": "^22.10.9", + "@types/node": "^22.10.10", "react": "^18.2.0" } } diff --git a/packages/plugin-types-bundler/package.json b/packages/plugin-types-bundler/package.json index 1b218c0a6..7396f8845 100644 --- a/packages/plugin-types-bundler/package.json +++ b/packages/plugin-types-bundler/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/plugin-types-bundler", - "version": "0.2.2", + "version": "0.2.3", "description": "Bundle grafana plugin typescript types for sharing with other plugins", "bin": "./dist/bin/run.js", "type": "module", @@ -50,7 +50,7 @@ "dependencies": { "@grafana/levitate": "^0.15.0", "@types/minimist": "^1.2.2", - "@types/node": "22.10.6", + "@types/node": "22.10.10", "debug": "^4.3.4", "jackw-dts-bundle-gen-test": "^9.5.1", "minimist": "^1.2.8"