import { act, cleanup, waitFor } from '@testing-library/react'; import userEvents from '@testing-library/user-event'; import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; import { config, locationService, setPluginImportUtils } from '@grafana/runtime'; import { sceneGraph } from '@grafana/scenes'; import { getDashboardAPI, setDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; import { DashboardScene } from 'app/features/dashboard-scene/scene/DashboardScene'; import { initializeScopes, scopesDashboardsScene, scopesSelectorScene } from './instance'; import { buildTestScene, fetchNodesSpy, fetchScopeSpy, fetchSelectedScopesSpy, fetchSuggestedDashboardsSpy, getDashboard, getDashboardsExpand, getDashboardsSearch, getMock, getNotFoundForFilter, getNotFoundForFilterClear, getNotFoundForScope, getNotFoundNoScopes, getPersistedApplicationsSlothPictureFactorySelect, getPersistedApplicationsSlothPictureFactoryTitle, getPersistedApplicationsSlothVoteTrackerTitle, getResultApplicationsClustersExpand, getResultApplicationsClustersSelect, getResultApplicationsClustersSlothClusterNorthSelect, getResultApplicationsClustersSlothClusterSouthSelect, getResultApplicationsExpand, getResultApplicationsSlothPictureFactorySelect, getResultApplicationsSlothPictureFactoryTitle, getResultApplicationsSlothVoteTrackerSelect, getResultApplicationsSlothVoteTrackerTitle, getResultClustersExpand, getResultClustersSelect, getResultClustersSlothClusterEastRadio, getResultClustersSlothClusterNorthRadio, getResultClustersSlothClusterSouthRadio, getSelectorApply, getSelectorCancel, getSelectorInput, getTreeHeadline, getTreeSearch, mocksScopes, queryAllDashboard, queryDashboard, queryDashboardsContainer, queryDashboardsSearch, queryPersistedApplicationsSlothPictureFactoryTitle, queryPersistedApplicationsSlothVoteTrackerTitle, queryResultApplicationsClustersTitle, queryResultApplicationsSlothPictureFactoryTitle, queryResultApplicationsSlothVoteTrackerTitle, querySelectorApply, renderDashboard, resetScenes, } from './testUtils'; import { getClosestScopesFacade } from './utils'; jest.mock('@grafana/runtime', () => ({ __esModule: true, ...jest.requireActual('@grafana/runtime'), useChromeHeaderHeight: jest.fn(), getBackendSrv: () => ({ get: getMock, }), usePluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }), })); const panelPlugin = getPanelPlugin({ id: 'table', skipDataQuery: true, }); config.panels['table'] = panelPlugin.meta; setPluginImportUtils({ importPanelPlugin: (id: string) => Promise.resolve(panelPlugin), getPanelPluginFromCache: (id: string) => undefined, }); describe('Scopes', () => { describe('Feature flag off', () => { beforeAll(() => { config.featureToggles.scopeFilters = false; config.featureToggles.groupByVariable = true; initializeScopes(); }); it('Does not initialize', () => { const dashboardScene = buildTestScene(); dashboardScene.activate(); expect(scopesSelectorScene).toBeNull(); }); }); describe('Feature flag on', () => { let dashboardScene: DashboardScene; beforeAll(() => { config.featureToggles.scopeFilters = true; config.featureToggles.groupByVariable = true; }); beforeEach(() => { jest.spyOn(console, 'error').mockImplementation(jest.fn()); fetchNodesSpy.mockClear(); fetchScopeSpy.mockClear(); fetchSelectedScopesSpy.mockClear(); fetchSuggestedDashboardsSpy.mockClear(); getMock.mockClear(); initializeScopes(); dashboardScene = buildTestScene(); renderDashboard(dashboardScene); }); afterEach(() => { resetScenes(); cleanup(); }); describe('Tree', () => { it('Navigates through scopes nodes', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsClustersExpand()); await userEvents.click(getResultApplicationsExpand()); }); it('Fetches scope details on select', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await waitFor(() => expect(fetchScopeSpy).toHaveBeenCalledTimes(1)); }); it('Selects the proper scopes', async () => { await act(async () => scopesSelectorScene?.updateScopes([ { scopeName: 'slothPictureFactory', path: [] }, { scopeName: 'slothVoteTracker', path: [] }, ]) ); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); expect(getResultApplicationsSlothVoteTrackerSelect()).toBeChecked(); expect(getResultApplicationsSlothPictureFactorySelect()).toBeChecked(); }); it('Can select scopes from same level', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getResultApplicationsClustersSelect()); await userEvents.click(getSelectorApply()); expect(getSelectorInput().value).toBe('slothVoteTracker, slothPictureFactory, Cluster Index Helper'); }); it('Can select a node from an inner level', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getResultApplicationsClustersExpand()); await userEvents.click(getResultApplicationsClustersSlothClusterNorthSelect()); await userEvents.click(getSelectorApply()); expect(getSelectorInput().value).toBe('slothClusterNorth'); }); it('Can select a node from an upper level', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultClustersSelect()); await userEvents.click(getSelectorApply()); expect(getSelectorInput().value).toBe('Cluster Index Helper'); }); it('Respects only one select per container', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultClustersExpand()); await userEvents.click(getResultClustersSlothClusterNorthRadio()); expect(getResultClustersSlothClusterNorthRadio().checked).toBe(true); expect(getResultClustersSlothClusterSouthRadio().checked).toBe(false); await userEvents.click(getResultClustersSlothClusterSouthRadio()); expect(getResultClustersSlothClusterNorthRadio().checked).toBe(false); expect(getResultClustersSlothClusterSouthRadio().checked).toBe(true); }); it('Search works', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.type(getTreeSearch(), 'Clusters'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); expect(queryResultApplicationsSlothPictureFactoryTitle()).not.toBeInTheDocument(); expect(queryResultApplicationsSlothVoteTrackerTitle()).not.toBeInTheDocument(); expect(getResultApplicationsClustersSelect()).toBeInTheDocument(); await userEvents.clear(getTreeSearch()); await userEvents.type(getTreeSearch(), 'sloth'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(4)); expect(getResultApplicationsSlothPictureFactoryTitle()).toBeInTheDocument(); expect(getResultApplicationsSlothVoteTrackerSelect()).toBeInTheDocument(); expect(queryResultApplicationsClustersTitle()).not.toBeInTheDocument(); }); it('Opens to a selected scope', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultClustersExpand()); await userEvents.click(getSelectorApply()); await userEvents.click(getSelectorInput()); expect(queryResultApplicationsSlothPictureFactoryTitle()).toBeInTheDocument(); }); it('Persists a scope', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.type(getTreeSearch(), 'slothVoteTracker'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); expect(getPersistedApplicationsSlothPictureFactoryTitle()).toBeInTheDocument(); expect(queryPersistedApplicationsSlothVoteTrackerTitle()).not.toBeInTheDocument(); expect(queryResultApplicationsSlothPictureFactoryTitle()).not.toBeInTheDocument(); expect(getResultApplicationsSlothVoteTrackerTitle()).toBeInTheDocument(); }); it('Does not persist a retrieved scope', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.type(getTreeSearch(), 'slothPictureFactory'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); expect(queryPersistedApplicationsSlothPictureFactoryTitle()).not.toBeInTheDocument(); expect(getResultApplicationsSlothPictureFactoryTitle()).toBeInTheDocument(); }); it('Removes persisted nodes', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.type(getTreeSearch(), 'slothVoteTracker'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); await userEvents.clear(getTreeSearch()); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(4)); expect(queryPersistedApplicationsSlothPictureFactoryTitle()).not.toBeInTheDocument(); expect(queryPersistedApplicationsSlothVoteTrackerTitle()).not.toBeInTheDocument(); expect(getResultApplicationsSlothPictureFactoryTitle()).toBeInTheDocument(); expect(getResultApplicationsSlothVoteTrackerTitle()).toBeInTheDocument(); }); it('Persists nodes from search', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.type(getTreeSearch(), 'sloth'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.type(getTreeSearch(), 'slothunknown'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(4)); expect(getPersistedApplicationsSlothPictureFactoryTitle()).toBeInTheDocument(); expect(getPersistedApplicationsSlothVoteTrackerTitle()).toBeInTheDocument(); await userEvents.clear(getTreeSearch()); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(5)); expect(getResultApplicationsSlothPictureFactoryTitle()).toBeInTheDocument(); expect(getResultApplicationsSlothVoteTrackerTitle()).toBeInTheDocument(); }); it('Selects a persisted scope', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.type(getTreeSearch(), 'slothVoteTracker'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getSelectorApply()); expect(getSelectorInput().value).toBe('slothPictureFactory, slothVoteTracker'); }); it('Deselects a persisted scope', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.type(getTreeSearch(), 'slothVoteTracker'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getSelectorApply()); expect(getSelectorInput().value).toBe('slothPictureFactory, slothVoteTracker'); await userEvents.click(getSelectorInput()); await userEvents.click(getPersistedApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); expect(getSelectorInput().value).toBe('slothVoteTracker'); }); it('Shows the proper headline', async () => { await userEvents.click(getSelectorInput()); expect(getTreeHeadline()).toHaveTextContent('Recommended'); await userEvents.type(getTreeSearch(), 'Applications'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(2)); expect(getTreeHeadline()).toHaveTextContent('Results'); await userEvents.type(getTreeSearch(), 'unknown'); await waitFor(() => expect(fetchNodesSpy).toHaveBeenCalledTimes(3)); expect(getTreeHeadline()).toHaveTextContent('No results found for your query'); }); }); describe('Selector', () => { it('Opens', async () => { await userEvents.click(getSelectorInput()); expect(getSelectorApply()).toBeInTheDocument(); }); it('Fetches scope details on save', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultClustersSelect()); await userEvents.click(getSelectorApply()); await waitFor(() => expect(fetchSelectedScopesSpy).toHaveBeenCalled()); expect(getClosestScopesFacade(dashboardScene)?.value).toEqual( mocksScopes.filter(({ metadata: { name } }) => name === 'indexHelperCluster') ); }); it("Doesn't save the scopes on close", async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultClustersSelect()); await userEvents.click(getSelectorCancel()); await waitFor(() => expect(fetchSelectedScopesSpy).not.toHaveBeenCalled()); expect(getClosestScopesFacade(dashboardScene)?.value).toEqual([]); }); it('Shows selected scopes', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultClustersSelect()); await userEvents.click(getSelectorApply()); expect(getSelectorInput().value).toEqual('Cluster Index Helper'); }); }); describe('Dashboards list', () => { it('Toggles expanded state', async () => { await userEvents.click(getDashboardsExpand()); expect(getNotFoundNoScopes()).toBeInTheDocument(); }); it('Does not fetch dashboards list when the list is not expanded', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await waitFor(() => expect(fetchSuggestedDashboardsSpy).not.toHaveBeenCalled()); }); it('Fetches dashboards list when the list is expanded', async () => { await userEvents.click(getDashboardsExpand()); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await waitFor(() => expect(fetchSuggestedDashboardsSpy).toHaveBeenCalled()); }); it('Fetches dashboards list when the list is expanded after scope selection', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await userEvents.click(getDashboardsExpand()); await waitFor(() => expect(fetchSuggestedDashboardsSpy).toHaveBeenCalled()); }); it('Shows dashboards for multiple scopes', async () => { await userEvents.click(getDashboardsExpand()); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); expect(getDashboard('1')).toBeInTheDocument(); expect(getDashboard('2')).toBeInTheDocument(); expect(queryDashboard('3')).not.toBeInTheDocument(); expect(queryDashboard('4')).not.toBeInTheDocument(); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getSelectorApply()); expect(getDashboard('1')).toBeInTheDocument(); expect(getDashboard('2')).toBeInTheDocument(); expect(getDashboard('3')).toBeInTheDocument(); expect(getDashboard('4')).toBeInTheDocument(); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); expect(queryDashboard('1')).not.toBeInTheDocument(); expect(queryDashboard('2')).not.toBeInTheDocument(); expect(getDashboard('3')).toBeInTheDocument(); expect(getDashboard('4')).toBeInTheDocument(); }); it('Filters the dashboards list', async () => { await userEvents.click(getDashboardsExpand()); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); expect(getDashboard('1')).toBeInTheDocument(); expect(getDashboard('2')).toBeInTheDocument(); await userEvents.type(getDashboardsSearch(), '1'); expect(queryDashboard('2')).not.toBeInTheDocument(); }); it('Deduplicates the dashboards list', async () => { await userEvents.click(getDashboardsExpand()); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsClustersExpand()); await userEvents.click(getResultApplicationsClustersSlothClusterNorthSelect()); await userEvents.click(getResultApplicationsClustersSlothClusterSouthSelect()); await userEvents.click(getSelectorApply()); expect(queryAllDashboard('5')).toHaveLength(1); expect(queryAllDashboard('6')).toHaveLength(1); expect(queryAllDashboard('7')).toHaveLength(1); expect(queryAllDashboard('8')).toHaveLength(1); }); it('Does show a proper message when no scopes are selected', async () => { await userEvents.click(getDashboardsExpand()); expect(getNotFoundNoScopes()).toBeInTheDocument(); expect(queryDashboardsSearch()).not.toBeInTheDocument(); }); it('Does not show the input when there are no dashboards found for scope', async () => { await userEvents.click(getDashboardsExpand()); await userEvents.click(getSelectorInput()); await userEvents.click(getResultClustersExpand()); await userEvents.click(getResultClustersSlothClusterEastRadio()); await userEvents.click(getSelectorApply()); expect(getNotFoundForScope()).toBeInTheDocument(); expect(queryDashboardsSearch()).not.toBeInTheDocument(); }); it('Does show the input and a message when there are no dashboards found for filter', async () => { await userEvents.click(getDashboardsExpand()); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await userEvents.type(getDashboardsSearch(), 'unknown'); expect(queryDashboardsSearch()).toBeInTheDocument(); expect(getNotFoundForFilter()).toBeInTheDocument(); await userEvents.click(getNotFoundForFilterClear()); expect(getDashboardsSearch().value).toBe(''); }); }); describe('View mode', () => { it('Enters view mode', async () => { await act(async () => dashboardScene.onEnterEditMode()); expect(scopesSelectorScene?.state?.isReadOnly).toEqual(true); expect(scopesDashboardsScene?.state?.isPanelOpened).toEqual(false); }); it('Closes selector on enter', async () => { await userEvents.click(getSelectorInput()); await act(async () => dashboardScene.onEnterEditMode()); expect(querySelectorApply()).not.toBeInTheDocument(); }); it('Closes dashboards list on enter', async () => { await userEvents.click(getDashboardsExpand()); await act(async () => dashboardScene.onEnterEditMode()); expect(queryDashboardsContainer()).not.toBeInTheDocument(); }); it('Does not open selector when view mode is active', async () => { await act(async () => dashboardScene.onEnterEditMode()); await userEvents.click(getSelectorInput()); expect(querySelectorApply()).not.toBeInTheDocument(); }); it('Disables the expand button when view mode is active', async () => { await act(async () => dashboardScene.onEnterEditMode()); expect(getDashboardsExpand()).toBeDisabled(); }); }); describe('Enrichers', () => { it('Data requests', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await waitFor(() => { const queryRunner = sceneGraph.findObject(dashboardScene, (o) => o.state.key === 'data-query-runner')!; expect(dashboardScene.enrichDataRequest(queryRunner).scopes).toEqual( mocksScopes.filter(({ metadata: { name } }) => name === 'slothPictureFactory') ); }); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getSelectorApply()); await waitFor(() => { const queryRunner = sceneGraph.findObject(dashboardScene, (o) => o.state.key === 'data-query-runner')!; expect(dashboardScene.enrichDataRequest(queryRunner).scopes).toEqual( mocksScopes.filter( ({ metadata: { name } }) => name === 'slothPictureFactory' || name === 'slothVoteTracker' ) ); }); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await waitFor(() => { const queryRunner = sceneGraph.findObject(dashboardScene, (o) => o.state.key === 'data-query-runner')!; expect(dashboardScene.enrichDataRequest(queryRunner).scopes).toEqual( mocksScopes.filter(({ metadata: { name } }) => name === 'slothVoteTracker') ); }); }); it('Filters requests', async () => { await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsExpand()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await waitFor(() => { expect(dashboardScene.enrichFiltersRequest().scopes).toEqual( mocksScopes.filter(({ metadata: { name } }) => name === 'slothPictureFactory') ); }); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsSlothVoteTrackerSelect()); await userEvents.click(getSelectorApply()); await waitFor(() => { expect(dashboardScene.enrichFiltersRequest().scopes).toEqual( mocksScopes.filter( ({ metadata: { name } }) => name === 'slothPictureFactory' || name === 'slothVoteTracker' ) ); }); await userEvents.click(getSelectorInput()); await userEvents.click(getResultApplicationsSlothPictureFactorySelect()); await userEvents.click(getSelectorApply()); await waitFor(() => { expect(dashboardScene.enrichFiltersRequest().scopes).toEqual( mocksScopes.filter(({ metadata: { name } }) => name === 'slothVoteTracker') ); }); }); }); }); describe('Dashboards API', () => { describe('Feature flag off', () => { beforeAll(() => { config.featureToggles.scopeFilters = true; config.featureToggles.passScopeToDashboardApi = false; }); beforeEach(() => { setDashboardAPI(undefined); locationService.push('/?scopes=scope1&scopes=scope2&scopes=scope3'); }); afterEach(() => { resetScenes(); cleanup(); }); it('Legacy API should not pass the scopes', async () => { config.featureToggles.kubernetesDashboards = false; getDashboardAPI().getDashboardDTO('1'); await waitFor(() => expect(getMock).toHaveBeenCalledWith('/api/dashboards/uid/1', undefined)); }); it('K8s API should not pass the scopes', async () => { config.featureToggles.kubernetesDashboards = true; getDashboardAPI().getDashboardDTO('1'); await waitFor(() => expect(getMock).toHaveBeenCalledWith( '/apis/dashboard.grafana.app/v0alpha1/namespaces/default/dashboards/1/dto' ) ); }); }); describe('Feature flag on', () => { beforeAll(() => { config.featureToggles.scopeFilters = true; config.featureToggles.passScopeToDashboardApi = true; }); beforeEach(() => { setDashboardAPI(undefined); locationService.push('/?scopes=scope1&scopes=scope2&scopes=scope3'); initializeScopes(); }); afterEach(() => { resetScenes(); cleanup(); }); it('Legacy API should pass the scopes', async () => { config.featureToggles.kubernetesDashboards = false; getDashboardAPI().getDashboardDTO('1'); await waitFor(() => expect(getMock).toHaveBeenCalledWith('/api/dashboards/uid/1', { scopes: ['scope1', 'scope2', 'scope3'] }) ); }); it('K8s API should not pass the scopes', async () => { config.featureToggles.kubernetesDashboards = true; getDashboardAPI().getDashboardDTO('1'); await waitFor(() => expect(getMock).toHaveBeenCalledWith( '/apis/dashboard.grafana.app/v0alpha1/namespaces/default/dashboards/1/dto' ) ); }); }); }); });