fix(tests): fix test failures
- Fix Prettier formatting in 8 files - Fix useProvisionedRequestHandler.test.ts by mocking config.bootData - Ensures ContextSrv can be instantiated in tests
This commit is contained in:
@@ -65,8 +65,12 @@ export function BrowseActions({ folderDTO }: Props) {
|
||||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
const selectedDashboards = Object.keys(selectedItemsForActions.dashboard).filter((uid) => selectedItemsForActions.dashboard[uid]);
|
||||
const selectedFolders = Object.keys(selectedItemsForActions.folder).filter((uid) => selectedItemsForActions.folder[uid]);
|
||||
const selectedDashboards = Object.keys(selectedItemsForActions.dashboard).filter(
|
||||
(uid) => selectedItemsForActions.dashboard[uid]
|
||||
);
|
||||
const selectedFolders = Object.keys(selectedItemsForActions.folder).filter(
|
||||
(uid) => selectedItemsForActions.folder[uid]
|
||||
);
|
||||
await deleteDashboards({ dashboardUIDs: selectedDashboards });
|
||||
await deleteFolders({ folderUIDs: selectedFolders });
|
||||
trackAction('delete', selectedItemsForActions);
|
||||
@@ -74,8 +78,12 @@ export function BrowseActions({ folderDTO }: Props) {
|
||||
};
|
||||
|
||||
const onMove = async (destinationUID: string) => {
|
||||
const selectedDashboards = Object.keys(selectedItemsForActions.dashboard).filter((uid) => selectedItemsForActions.dashboard[uid]);
|
||||
const selectedFolders = Object.keys(selectedItemsForActions.folder).filter((uid) => selectedItemsForActions.folder[uid]);
|
||||
const selectedDashboards = Object.keys(selectedItemsForActions.dashboard).filter(
|
||||
(uid) => selectedItemsForActions.dashboard[uid]
|
||||
);
|
||||
const selectedFolders = Object.keys(selectedItemsForActions.folder).filter(
|
||||
(uid) => selectedItemsForActions.folder[uid]
|
||||
);
|
||||
|
||||
await moveFolders({ folderUIDs: selectedFolders, destinationUID });
|
||||
await moveDashboards({ dashboardUIDs: selectedDashboards, destinationUID });
|
||||
|
||||
@@ -133,13 +133,13 @@ export function FolderActionsButton({ folder, repoType, isReadOnlyRepo }: Props)
|
||||
try {
|
||||
// Collect all dashboards under this folder and its children
|
||||
const dashboardUIDs = await collectAllDashboardsUnderFolder(folder.uid);
|
||||
|
||||
|
||||
// Create selected items object with all dashboards
|
||||
const selectedDashboards: Record<string, boolean> = {};
|
||||
dashboardUIDs.forEach((uid) => {
|
||||
selectedDashboards[uid] = true;
|
||||
});
|
||||
|
||||
|
||||
setExportSelectedDashboards(selectedDashboards);
|
||||
setShowExportFolderDrawer(true);
|
||||
} catch (error) {
|
||||
@@ -183,9 +183,7 @@ export function FolderActionsButton({ folder, repoType, isReadOnlyRepo }: Props)
|
||||
label={deleteLabel}
|
||||
/>
|
||||
)}
|
||||
{provisioningEnabled && isUnmanagedFolder && (
|
||||
<MenuItem onClick={handleExportFolder} label={exportLabel} />
|
||||
)}
|
||||
{provisioningEnabled && isUnmanagedFolder && <MenuItem onClick={handleExportFolder} label={exportLabel} />}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
|
||||
@@ -91,10 +91,7 @@ export const refetchChildren = createAsyncThunk(
|
||||
|
||||
export const selectFolderWithAllDashboards = createAsyncThunk(
|
||||
'browseDashboards/selectFolderWithAllDashboards',
|
||||
async (
|
||||
{ folderUID, isSelected }: { folderUID: string; isSelected: boolean },
|
||||
{ dispatch, getState }
|
||||
) => {
|
||||
async ({ folderUID, isSelected }: { folderUID: string; isSelected: boolean }, { dispatch, getState }) => {
|
||||
const state = getState().browseDashboards;
|
||||
|
||||
// Find the folder item to get its parentUID and managedBy
|
||||
@@ -102,15 +99,17 @@ export const selectFolderWithAllDashboards = createAsyncThunk(
|
||||
|
||||
if (!isSelected) {
|
||||
// When deselecting, use the normal action - it will handle deselecting all children recursively
|
||||
dispatch(setItemSelectionState({
|
||||
item: {
|
||||
kind: 'folder',
|
||||
uid: folderUID,
|
||||
parentUID: folderItem?.parentUID,
|
||||
managedBy: folderItem?.managedBy
|
||||
},
|
||||
isSelected: false
|
||||
}));
|
||||
dispatch(
|
||||
setItemSelectionState({
|
||||
item: {
|
||||
kind: 'folder',
|
||||
uid: folderUID,
|
||||
parentUID: folderItem?.parentUID,
|
||||
managedBy: folderItem?.managedBy,
|
||||
},
|
||||
isSelected: false,
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -119,15 +118,17 @@ export const selectFolderWithAllDashboards = createAsyncThunk(
|
||||
const dashboardUIDs = await collectAllDashboardsUnderFolder(folderUID);
|
||||
|
||||
// First, select the folder itself
|
||||
dispatch(setItemSelectionState({
|
||||
item: {
|
||||
kind: 'folder',
|
||||
uid: folderUID,
|
||||
parentUID: folderItem?.parentUID,
|
||||
managedBy: folderItem?.managedBy
|
||||
},
|
||||
isSelected: true
|
||||
}));
|
||||
dispatch(
|
||||
setItemSelectionState({
|
||||
item: {
|
||||
kind: 'folder',
|
||||
uid: folderUID,
|
||||
parentUID: folderItem?.parentUID,
|
||||
managedBy: folderItem?.managedBy,
|
||||
},
|
||||
isSelected: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Then select all dashboards found
|
||||
// We need to get the parentUID for each dashboard from the state
|
||||
@@ -136,15 +137,17 @@ export const selectFolderWithAllDashboards = createAsyncThunk(
|
||||
const dashboardItem = findItem(state.rootItems?.items ?? [], state.childrenByParentUID, dashboardUID);
|
||||
// Even if dashboard isn't in state, we can still select it by UID
|
||||
// The reducer will handle setting selectedItems.dashboard[dashboardUID] = true
|
||||
dispatch(setItemSelectionState({
|
||||
item: {
|
||||
kind: 'dashboard',
|
||||
uid: dashboardUID,
|
||||
parentUID: dashboardItem?.parentUID ?? folderUID, // Fallback to folderUID if not found
|
||||
managedBy: dashboardItem?.managedBy
|
||||
},
|
||||
isSelected: true
|
||||
}));
|
||||
dispatch(
|
||||
setItemSelectionState({
|
||||
item: {
|
||||
kind: 'dashboard',
|
||||
uid: dashboardUID,
|
||||
parentUID: dashboardItem?.parentUID ?? folderUID, // Fallback to folderUID if not found
|
||||
managedBy: dashboardItem?.managedBy,
|
||||
},
|
||||
isSelected: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -29,4 +29,3 @@ function ExportToRepositoryRenderer({ model }: SceneComponentProps<ExportToRepos
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,10 +57,7 @@ export function RepositoryList({ items }: Props) {
|
||||
}
|
||||
onRemove={unmanagedCount > 0 ? handlePushUnmanaged : undefined}
|
||||
>
|
||||
<Trans
|
||||
i18nKey="provisioning.folder-repository-list.partial-managed"
|
||||
values={{ managedCount, resourceCount }}
|
||||
>
|
||||
<Trans i18nKey="provisioning.folder-repository-list.partial-managed" values={{ managedCount, resourceCount }}>
|
||||
{{ managedCount }}/{{ resourceCount }} resources managed by Git sync.
|
||||
</Trans>
|
||||
{unmanagedCount > 0 && (
|
||||
|
||||
+14
-16
@@ -60,17 +60,15 @@ function FormContent({ initialValues, selectedItems, workflowOptions, onDismiss
|
||||
}, [repositories, selectedRepositoryName, isLoadingRepos]);
|
||||
|
||||
// Get selected repository
|
||||
const repositoryView: RepositoryView | undefined = repositories.find(
|
||||
(repo) => repo.name === selectedRepositoryName
|
||||
);
|
||||
const repositoryView: RepositoryView | undefined = repositories.find((repo) => repo.name === selectedRepositoryName);
|
||||
|
||||
// Compute workflow options based on selected repository
|
||||
const selectedWorkflowOptions = repositoryView ? getWorkflowOptions(repositoryView) : workflowOptions;
|
||||
const selectedDefaultWorkflow = repositoryView
|
||||
? getDefaultWorkflow(repositoryView)
|
||||
: (workflowOptions[0]?.value === 'branch' || workflowOptions[0]?.value === 'write'
|
||||
? workflowOptions[0].value
|
||||
: undefined);
|
||||
: workflowOptions[0]?.value === 'branch' || workflowOptions[0]?.value === 'write'
|
||||
? workflowOptions[0].value
|
||||
: undefined;
|
||||
|
||||
// Update workflow, branch, and path when repository changes
|
||||
useEffect(() => {
|
||||
@@ -216,13 +214,14 @@ function FormContent({ initialValues, selectedItems, workflowOptions, onDismiss
|
||||
</Box>
|
||||
|
||||
{/* Show form-level errors */}
|
||||
{errors.root && (
|
||||
<Alert severity="error" title={String(errors.root.message)} />
|
||||
)}
|
||||
{errors.root && <Alert severity="error" title={String(errors.root.message)} />}
|
||||
|
||||
{/* Info if folders are selected */}
|
||||
{Object.keys(selectedItems.folder || {}).filter((uid) => selectedItems.folder[uid]).length > 0 && (
|
||||
<Alert severity="info" title={t('browse-dashboards.bulk-export-resources-form.folders-info', 'Folders in selection')}>
|
||||
<Alert
|
||||
severity="info"
|
||||
title={t('browse-dashboards.bulk-export-resources-form.folders-info', 'Folders in selection')}
|
||||
>
|
||||
{t(
|
||||
'browse-dashboards.bulk-export-resources-form.folders-info-description',
|
||||
'Folders will be left behind. New folders will be created in the repository based on the resource folder structure.'
|
||||
@@ -297,7 +296,10 @@ function FormContent({ initialValues, selectedItems, workflowOptions, onDismiss
|
||||
<Input
|
||||
type="text"
|
||||
{...methods.register('path')}
|
||||
placeholder={t('browse-dashboards.bulk-export-resources-form.path-placeholder', 'e.g., dashboards/')}
|
||||
placeholder={t(
|
||||
'browse-dashboards.bulk-export-resources-form.path-placeholder',
|
||||
'e.g., dashboards/'
|
||||
)}
|
||||
/>
|
||||
</Field>
|
||||
)}
|
||||
@@ -318,10 +320,7 @@ function FormContent({ initialValues, selectedItems, workflowOptions, onDismiss
|
||||
<Button variant="secondary" fill="outline" onClick={onDismiss} disabled={isCreatingJob}>
|
||||
<Trans i18nKey="browse-dashboards.bulk-export-resources-form.button-cancel">Cancel</Trans>
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!!job || isCreatingJob || hasSubmitted || !selectedRepositoryName}
|
||||
>
|
||||
<Button type="submit" disabled={!!job || isCreatingJob || hasSubmitted || !selectedRepositoryName}>
|
||||
{isCreatingJob
|
||||
? t('browse-dashboards.bulk-export-resources-form.button-exporting', 'Exporting...')
|
||||
: t('browse-dashboards.bulk-export-resources-form.button-export', 'Export')}
|
||||
@@ -382,4 +381,3 @@ const getPathPrefixStyles = (theme: GrafanaTheme2) => ({
|
||||
whiteSpace: 'nowrap',
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -7,9 +7,21 @@ import { ResourceWrapper } from 'app/api/clients/provisioning/v0alpha1';
|
||||
|
||||
import { useProvisionedRequestHandler, RequestHandlers } from './useProvisionedRequestHandler';
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
getAppEvents: jest.fn(),
|
||||
}));
|
||||
jest.mock('@grafana/runtime', () => {
|
||||
const original = jest.requireActual('@grafana/runtime');
|
||||
return {
|
||||
...original,
|
||||
getAppEvents: jest.fn(),
|
||||
config: {
|
||||
...original.config,
|
||||
bootData: {
|
||||
user: {},
|
||||
settings: {},
|
||||
navTree: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@grafana/i18n', () => ({
|
||||
t: jest.fn((key: string, defaultValue: string) => defaultValue),
|
||||
|
||||
@@ -12,9 +12,10 @@ import { findItem } from '../../browse-dashboards/state/utils';
|
||||
import { DashboardTreeSelection } from '../../browse-dashboards/types';
|
||||
|
||||
// This hook checks if selected items are unmanaged (not managed by any repository)
|
||||
export function useSelectionUnmanagedStatus(
|
||||
selectedItems: Omit<DashboardTreeSelection, 'panel' | '$all'>
|
||||
): { hasUnmanaged: boolean; isLoading: boolean } {
|
||||
export function useSelectionUnmanagedStatus(selectedItems: Omit<DashboardTreeSelection, 'panel' | '$all'>): {
|
||||
hasUnmanaged: boolean;
|
||||
isLoading: boolean;
|
||||
} {
|
||||
const browseState = useSelector((state) => state.browseDashboards);
|
||||
const [, stateManager] = useSearchStateManager();
|
||||
const isSearching = stateManager.hasSearchFilters();
|
||||
@@ -155,4 +156,3 @@ export function useSelectionUnmanagedStatus(
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,4 +69,3 @@ export async function collectAllDashboardsUnderFolder(folderUID: string): Promis
|
||||
|
||||
return dashboardUIDs;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user