alerting/msw-scenarios
Gilles De Mey 2 months ago
parent 5e240c49cb
commit 788ea5d624
No known key found for this signature in database
  1. 4
      packages/grafana-test-utils/src/index.ts
  2. 33
      packages/grafana-test-utils/src/registry.ts
  3. 4
      packages/grafana-test-utils/src/unstable.ts
  4. 22
      packages/grafana-test-utils/src/useScenarioRegistry.ts
  5. 5
      public/app/app.ts
  6. 4
      public/app/features/commandPalette/actions/staticActions.ts
  7. 6
      public/app/features/plugins/extensions/useScenarioRegistry.ts
  8. 25
      public/app/mock-api-utils.ts

@ -5,4 +5,6 @@
* @packageDocumentation
*/
export {};
import { Scenario, ScenarioRegistry } from './registry';
export { type Scenario, ScenarioRegistry };

@ -0,0 +1,33 @@
import { HttpHandler } from 'msw';
import { SetupWorker } from 'msw/browser';
import worker from './worker';
export type Scenario = HttpHandler[];
type ScenarioRegistryOptions = {
worker?: SetupWorker; // optionally use a worker that is different from the default one
};
export class ScenarioRegistry {
scenarios: Map<string, Scenario>;
worker: SetupWorker;
constructor(options?: ScenarioRegistryOptions) {
this.scenarios = new Map();
this.worker = options?.worker ?? worker;
}
registerScenario(name: string, scenario: Scenario) {
this.scenarios.set(name, scenario);
}
// return an array of handlers from the registry of scenarios so we can pass this into the MSW worker
handlers(): HttpHandler[] {
return Array.from(this.scenarios.values()).flat();
}
availableScenarios(): string[] {
return Array.from(this.scenarios.keys());
}
}

@ -1 +1,3 @@
export {};
import { setScenarioRegistryHook, useScenarioRegistry } from './useScenarioRegistry';
export { useScenarioRegistry, setScenarioRegistryHook };

@ -0,0 +1,22 @@
import { ScenarioRegistry } from './registry';
export type UseScenarioRegistryOptions = {};
export type UseScenarioRegistry = (options: UseScenarioRegistryOptions) => ScenarioRegistry;
let singleton: UseScenarioRegistry | undefined;
export function setScenarioRegistryHook(hook: UseScenarioRegistry): void {
// We allow overriding the hook in tests
if (singleton && process.env.NODE_ENV !== 'test') {
throw new Error('setScenarioRegistryHook() function should only be called once, when Grafana is starting.');
}
singleton = hook;
}
export function useScenarioRegistry(options: UseScenarioRegistryOptions): ScenarioRegistry {
if (!singleton) {
throw new Error('setScenarioRegistryHook(options) can only be used after the Grafana instance has started.');
}
return singleton(options);
}

@ -49,6 +49,7 @@ import {
setPanelRenderer,
setPluginPage,
} from '@grafana/runtime/internal';
import { setScenarioRegistryHook } from '@grafana/test-utils/unstable';
import config, { updateConfig } from 'app/core/config';
import { getStandardTransformers } from 'app/features/transformers/standardTransformers';
@ -92,6 +93,7 @@ import { usePluginComponent } from './features/plugins/extensions/usePluginCompo
import { usePluginComponents } from './features/plugins/extensions/usePluginComponents';
import { usePluginFunctions } from './features/plugins/extensions/usePluginFunctions';
import { usePluginLinks } from './features/plugins/extensions/usePluginLinks';
import { useScenarioRegistry } from './features/plugins/extensions/useScenarioRegistry';
import { getAppPluginsToAwait, getAppPluginsToPreload } from './features/plugins/extensions/utils';
import { importPanelPlugin, syncGetPanelPlugin } from './features/plugins/importPanelPlugin';
import { preloadPlugins } from './features/plugins/pluginPreloader';
@ -177,6 +179,9 @@ export class GrafanaApp {
initAlerting();
// create and register the scenarios registry
setScenarioRegistryHook(useScenarioRegistry);
standardEditorsRegistry.setInit(getAllOptionEditors);
standardFieldConfigEditorRegistry.setInit(getAllStandardFieldConfigs);
standardTransformersRegistry.setInit(getStandardTransformers);

@ -5,7 +5,7 @@ import { t } from '@grafana/i18n/internal';
import { enrichHelpItem } from 'app/core/components/AppChrome/MegaMenu/utils';
import { performInviteUserClick, shouldRenderInviteUserButton } from 'app/core/components/InviteUserButton/utils';
import { changeTheme } from 'app/core/services/theme';
import { currentMockApiState, toggleMockApiAndReload } from 'app/mock-api-utils';
import { getMockEnabledStateFromLocalstorage, toggleMockApiAndReload } from 'app/mock-api-utils';
import { useSelector } from '../../../types';
import { CommandPaletteAction } from '../types';
@ -105,7 +105,7 @@ function getGlobalActions(): CommandPaletteAction[] {
if (process.env.NODE_ENV === 'development') {
// eslint-disable @grafana/no-untranslated-strings
const section = 'Dev tooling';
const currentState = currentMockApiState();
const currentState = getMockEnabledStateFromLocalstorage();
const mockApiAction = currentState ? 'Disable' : 'Enable';
actions.push({
id: 'preferences/dev/toggle-mock-api',

@ -0,0 +1,6 @@
import { ScenarioRegistry } from '@grafana/test-utils';
export function useScenarioRegistry(): ScenarioRegistry {
const registry = new ScenarioRegistry();
return registry;
}

@ -6,26 +6,25 @@ import { AppNotificationSeverity } from './types';
export const STORAGE_MOCK_API_KEY = 'grafana.dev.mockApi';
export const SCENARIO_SEARCH_PARAM = '__scenario';
export const currentMockApiState = () => {
return store.getBool(STORAGE_MOCK_API_KEY, false);
};
export const getMockEnabledStateFromLocalstorage = () => store.getBool(STORAGE_MOCK_API_KEY, false);
export const toggleMockApiAndReload = () => {
const currentState = currentMockApiState();
const currentState = getMockEnabledStateFromLocalstorage();
store.set(STORAGE_MOCK_API_KEY, String(!currentState));
const action = currentState ? 'Disabling' : 'Enabling';
sendAppNotification(`${action} Mock API`, 'Reloading...', AppNotificationSeverity.Info);
setTimeout(() => {
window.location.reload();
}, 200);
};
export const potentiallySetupMockApi = async () => {
const mockApiEnabled = currentMockApiState();
if (process.env.NODE_ENV === 'development' && mockApiEnabled) {
const scenarioNames = new URLSearchParams(window.location.search).getAll(SCENARIO_SEARCH_PARAM);
const scenarioNames = new URLSearchParams(window.location.search).getAll(SCENARIO_SEARCH_PARAM);
if (wantsMockingEnabled()) {
const { default: worker } = await import('@grafana/test-utils/worker');
// TODO: Generalise and move Alerting handlers into @grafana/test-utils or @grafana/alerting package
@ -45,8 +44,16 @@ export const potentiallySetupMockApi = async () => {
}
};
function wantsMockingEnabled() {
const isDevEnv = process.env.NODE_ENV === 'development';
const enabledInLocalStorage = getMockEnabledStateFromLocalstorage();
const scenarioNames = new URLSearchParams(window.location.search).getAll(SCENARIO_SEARCH_PARAM);
return isDevEnv && (enabledInLocalStorage || scenarioNames.length > 0);
}
export const notifyIfMockApiEnabled = () => {
if (process.env.NODE_ENV === 'development' && currentMockApiState()) {
if (wantsMockingEnabled()) {
sendAppNotification(
'Mock API currently enabled',
'Some network requests will be intercepted',

Loading…
Cancel
Save