diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
index 2971da7a1041a..028849f48fdb4 100644
--- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
@@ -516,7 +516,6 @@ describe('AllCasesListGeneric', () => {
filterOptions: {
...DEFAULT_FILTER_OPTIONS,
searchFields: ['title', 'description'],
- owner: ['securitySolution'],
category: ['twix'],
},
queryParams: DEFAULT_QUERY_PARAMS,
@@ -645,82 +644,6 @@ describe('AllCasesListGeneric', () => {
});
describe('Solutions', () => {
- it('should set the owner to all available solutions when deselecting all solutions', async () => {
- const { getByTestId } = render(
-
-
-
- );
-
- expect(useGetCasesMock).toHaveBeenCalledWith({
- filterOptions: {
- search: '',
- searchFields: ['title', 'description'],
- severity: [],
- reporters: [],
- status: [],
- tags: [],
- assignees: [],
- owner: ['securitySolution', 'observability'],
- category: [],
- customFields: {},
- },
- queryParams: DEFAULT_QUERY_PARAMS,
- });
-
- userEvent.click(getByTestId('options-filter-popover-button-owner'));
-
- await waitForEuiPopoverOpen();
-
- userEvent.click(
- getByTestId(`options-filter-popover-item-${SECURITY_SOLUTION_OWNER}`),
- undefined,
- {
- skipPointerEventsCheck: true,
- }
- );
-
- expect(useGetCasesMock).toBeCalledWith({
- filterOptions: {
- search: '',
- searchFields: ['title', 'description'],
- severity: [],
- reporters: [],
- status: [],
- tags: [],
- assignees: [],
- owner: ['securitySolution'],
- category: [],
- customFields: {},
- },
- queryParams: DEFAULT_QUERY_PARAMS,
- });
-
- userEvent.click(
- getByTestId(`options-filter-popover-item-${SECURITY_SOLUTION_OWNER}`),
- undefined,
- {
- skipPointerEventsCheck: true,
- }
- );
-
- expect(useGetCasesMock).toHaveBeenLastCalledWith({
- filterOptions: {
- search: '',
- searchFields: ['title', 'description'],
- severity: [],
- reporters: [],
- status: [],
- tags: [],
- assignees: [],
- owner: ['securitySolution', 'observability'],
- category: [],
- customFields: {},
- },
- queryParams: DEFAULT_QUERY_PARAMS,
- });
- });
-
it('should hide the solutions filter if the owner is provided', async () => {
const { queryByTestId } = render(
@@ -730,30 +653,6 @@ describe('AllCasesListGeneric', () => {
expect(queryByTestId('options-filter-popover-button-owner')).toBeFalsy();
});
-
- it('should call useGetCases with the correct owner on initial render', async () => {
- render(
-
-
-
- );
-
- expect(useGetCasesMock).toHaveBeenCalledWith({
- filterOptions: {
- search: '',
- searchFields: ['title', 'description'],
- severity: [],
- reporters: [],
- status: [],
- tags: [],
- assignees: [],
- owner: ['securitySolution'],
- category: [],
- customFields: {},
- },
- queryParams: DEFAULT_QUERY_PARAMS,
- });
- });
});
describe('Actions', () => {
@@ -1102,7 +1001,6 @@ describe('AllCasesListGeneric', () => {
expect(useGetCasesMock).toHaveBeenLastCalledWith({
filterOptions: {
...DEFAULT_FILTER_OPTIONS,
- owner: [SECURITY_SOLUTION_OWNER],
assignees: [],
},
queryParams: DEFAULT_QUERY_PARAMS,
diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx
index a997e25a59f2d..449f7a190f6f0 100644
--- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx
@@ -63,10 +63,10 @@ export const AllCasesList = React.memo(
const isLoading = useIsLoadingCases();
const hasOwner = !!owner.length;
+
const firstAvailableStatus = head(difference(caseStatuses, hiddenStatuses));
const initialFilterOptions = {
...(!isEmpty(hiddenStatuses) && firstAvailableStatus && { status: [firstAvailableStatus] }),
- owner: hasOwner ? owner : availableSolutions,
};
const { queryParams, setQueryParams, filterOptions, setFilterOptions } = useAllCasesState(
@@ -210,7 +210,6 @@ export const AllCasesList = React.memo(
availableSolutions={hasOwner ? [] : availableSolutions}
hiddenStatuses={hiddenStatuses}
onCreateCasePressed={onCreateCasePressed}
- initialFilterOptions={initialFilterOptions}
isSelectorView={isSelectorView}
isLoading={isLoadingCurrentUserProfile}
currentUserProfile={currentUserProfile}
diff --git a/x-pack/plugins/cases/public/components/all_cases/solution_filter.test.tsx b/x-pack/plugins/cases/public/components/all_cases/solution_filter.test.tsx
index 69c757e354b86..1118a633c479f 100644
--- a/x-pack/plugins/cases/public/components/all_cases/solution_filter.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/solution_filter.test.tsx
@@ -100,7 +100,7 @@ describe('SolutionFilter ', () => {
expect(onChange).toHaveBeenCalledWith({
filterId: 'owner',
- selectedOptionKeys: [solutions[0]],
+ selectedOptionKeys: [],
});
});
});
@@ -168,7 +168,7 @@ describe('SolutionFilter ', () => {
expect(onChange).toHaveBeenCalledWith({
filterId: 'owner',
- selectedOptionKeys: [solutions[0], solutions[1]],
+ selectedOptionKeys: [],
});
});
});
diff --git a/x-pack/plugins/cases/public/components/all_cases/solution_filter.tsx b/x-pack/plugins/cases/public/components/all_cases/solution_filter.tsx
index 6f4eabddc0f8f..f2002e4c7899b 100644
--- a/x-pack/plugins/cases/public/components/all_cases/solution_filter.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/solution_filter.tsx
@@ -43,37 +43,6 @@ export const SolutionFilterComponent = ({
const options = mapToMultiSelectOption(hasOwner ? owner : availableSolutions);
const solutions = availableSolutions.map((solution) => mapToReadableSolutionName(solution));
- /**
- * If the user selects and deselects all solutions then the owner is set to an empty array.
- * This results in fetching all cases the user has access to including
- * the ones with read access. We want to show only the cases the user has full access to.
- * For that reason we fallback to availableSolutions if the owner is empty.
- *
- * If the consumer of cases has passed an owner we fallback to the provided owner
- */
- const _onChange = ({
- filterId,
- selectedOptionKeys: newOptions,
- }: {
- filterId: string;
- selectedOptionKeys: string[];
- }) => {
- if (hasOwner) {
- onChange({
- filterId,
- selectedOptionKeys: newOptions.length === 0 ? owner : newOptions,
- });
- } else {
- onChange({
- filterId,
- selectedOptionKeys: newOptions.length === 0 ? availableSolutions : newOptions,
- });
- }
- };
-
- const selectedOptionsInFilter =
- selectedOptionKeys.length === availableSolutions.length ? [] : selectedOptionKeys;
-
const renderOption = (option: EuiSelectableOption) => {
const solution = solutions.find((solutionData) => solutionData.id === option.label) as Solution;
return (
@@ -90,10 +59,10 @@ export const SolutionFilterComponent = ({
);
};
diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_system_filter_config.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_system_filter_config.tsx
index 0b522f6b066c8..ba2ca2d5f363f 100644
--- a/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_system_filter_config.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_system_filter_config.tsx
@@ -7,7 +7,6 @@
import React from 'react';
-import type { FilterOptions } from '../../../../common/ui';
import type { CaseStatuses } from '../../../../common/types/domain';
import { MAX_TAGS_FILTER_LENGTH, MAX_CATEGORY_FILTER_LENGTH } from '../../../../common/constants';
import { MultiSelectFilter, mapToMultiSelectOption } from '../multi_select_filter';
@@ -28,7 +27,6 @@ interface UseFilterConfigProps {
countOpenCases: number | null;
currentUserProfile: CurrentUserProfile;
hiddenStatuses?: CaseStatuses[];
- initialFilterOptions: Partial;
isLoading: boolean;
isSelectorView?: boolean;
onFilterOptionsChange: FilterChangeHandler;
@@ -44,7 +42,6 @@ export const getSystemFilterConfig = ({
countOpenCases,
currentUserProfile,
hiddenStatuses,
- initialFilterOptions,
isLoading,
isSelectorView,
onFilterOptionsChange,
@@ -69,7 +66,7 @@ export const getSystemFilterConfig = ({
isAvailable: true,
getEmptyOptions: () => {
return {
- severity: initialFilterOptions.severity || [],
+ severity: [],
};
},
render: ({ filterOptions }: FilterConfigRenderParams) => (
@@ -86,7 +83,7 @@ export const getSystemFilterConfig = ({
isAvailable: true,
getEmptyOptions: () => {
return {
- status: initialFilterOptions.status || [],
+ status: [],
};
},
render: ({ filterOptions }: FilterConfigRenderParams) => (
@@ -107,7 +104,7 @@ export const getSystemFilterConfig = ({
isAvailable: caseAssignmentAuthorized && !isSelectorView,
getEmptyOptions: () => {
return {
- assignees: initialFilterOptions.assignees || [],
+ assignees: [],
};
},
render: ({ filterOptions }: FilterConfigRenderParams) => {
@@ -128,7 +125,7 @@ export const getSystemFilterConfig = ({
isAvailable: true,
getEmptyOptions: () => {
return {
- tags: initialFilterOptions.tags || [],
+ tags: [],
};
},
render: ({ filterOptions }: FilterConfigRenderParams) => (
@@ -150,7 +147,7 @@ export const getSystemFilterConfig = ({
isAvailable: true,
getEmptyOptions: () => {
return {
- category: initialFilterOptions.category || [],
+ category: [],
};
},
render: ({ filterOptions }: FilterConfigRenderParams) => (
@@ -172,7 +169,7 @@ export const getSystemFilterConfig = ({
isAvailable: availableSolutions.length > 1,
getEmptyOptions: () => {
return {
- owner: initialFilterOptions.owner || [],
+ owner: [],
};
},
render: ({ filterOptions }: FilterConfigRenderParams) => (
@@ -195,7 +192,6 @@ export const useSystemFilterConfig = ({
countOpenCases,
currentUserProfile,
hiddenStatuses,
- initialFilterOptions,
isLoading,
isSelectorView,
onFilterOptionsChange,
@@ -210,7 +206,6 @@ export const useSystemFilterConfig = ({
countOpenCases,
currentUserProfile,
hiddenStatuses,
- initialFilterOptions,
isLoading,
isSelectorView,
onFilterOptionsChange,
diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx
index f4b93724ed4b9..0abed867a29b3 100644
--- a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx
@@ -262,6 +262,9 @@ describe('CasesTableFilters ', () => {
describe('Solution filter', () => {
it('shows Solution filter when provided more than 1 availableSolutions', () => {
+ appMockRender = createAppMockRenderer({
+ owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
+ });
appMockRender.render(
{
});
it('does not show Solution filter when provided less than 1 availableSolutions', () => {
- appMockRender.render(
-
- );
+ appMockRender = createAppMockRenderer({
+ owner: [],
+ });
+ appMockRender.render();
expect(screen.queryByTestId('options-filter-popover-button-owner')).not.toBeInTheDocument();
});
it('does not select a solution on initial render', () => {
+ appMockRender = createAppMockRenderer({
+ owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
+ });
appMockRender.render(
{
);
});
- it('should reset the filter setting all available solutions when deactivated', async () => {
+ it('should reset the filter when deactivated', async () => {
+ appMockRender = createAppMockRenderer({
+ owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
+ });
+
+ const overrideProps = {
+ ...props,
+ filterOptions: {
+ ...props.filterOptions,
+ owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
+ },
+ };
+
appMockRender.render(
);
@@ -306,8 +324,39 @@ describe('CasesTableFilters ', () => {
expect(onFilterChanged).toHaveBeenCalledWith({
...DEFAULT_FILTER_OPTIONS,
+ owner: [],
+ });
+ });
+
+ it('should check all options when all options are selected', async () => {
+ appMockRender = createAppMockRenderer({
owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
});
+
+ const overrideProps = {
+ ...props,
+ filterOptions: {
+ ...props.filterOptions,
+ owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
+ },
+ };
+
+ appMockRender.render(
+
+ );
+
+ userEvent.click(screen.getByRole('button', { name: 'Solution' }));
+ await waitForEuiPopoverOpen();
+
+ const allOptions = screen.getAllByRole('option');
+ expect(allOptions).toHaveLength(2);
+ expect(allOptions[0]).toHaveAttribute('aria-checked', 'true');
+ expect(allOptions[0]).toHaveTextContent('Security');
+ expect(allOptions[1]).toHaveAttribute('aria-checked', 'true');
+ expect(allOptions[1]).toHaveTextContent('Observability');
});
});
diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx
index e9e4350b6619f..dbdc947418eca 100644
--- a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx
@@ -28,7 +28,6 @@ export interface CasesTableFiltersProps {
availableSolutions: string[];
isSelectorView?: boolean;
onCreateCasePressed?: () => void;
- initialFilterOptions: Partial;
isLoading: boolean;
currentUserProfile: CurrentUserProfile;
filterOptions: FilterOptions;
@@ -49,7 +48,6 @@ const CasesTableFiltersComponent = ({
availableSolutions,
isSelectorView = false,
onCreateCasePressed,
- initialFilterOptions,
isLoading,
currentUserProfile,
filterOptions,
@@ -78,7 +76,6 @@ const CasesTableFiltersComponent = ({
countOpenCases,
currentUserProfile,
hiddenStatuses,
- initialFilterOptions,
isLoading,
isSelectorView,
onFilterOptionsChange,
diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx
index cd63e741327b5..72eb3326f199a 100644
--- a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx
+++ b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx
@@ -11,10 +11,11 @@ import { useGetCases } from './use_get_cases';
import * as api from './api';
import type { AppMockRenderer } from '../common/mock';
import { createAppMockRenderer } from '../common/mock';
-import { useToasts } from '../common/lib/kibana';
+import { useToasts } from '../common/lib/kibana/hooks';
+import { OWNERS } from '../../common/constants';
jest.mock('./api');
-jest.mock('../common/lib/kibana');
+jest.mock('../common/lib/kibana/hooks');
describe('useGetCases', () => {
const abortCtrl = new AbortController();
@@ -24,8 +25,8 @@ describe('useGetCases', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
- appMockRender = createAppMockRenderer();
jest.clearAllMocks();
+ appMockRender = createAppMockRenderer();
});
it('calls getCases with correct arguments', async () => {
@@ -33,9 +34,10 @@ describe('useGetCases', () => {
const { waitForNextUpdate } = renderHook(() => useGetCases(), {
wrapper: appMockRender.AppWrapper,
});
+
await waitForNextUpdate();
expect(spyOnGetCases).toBeCalledWith({
- filterOptions: { ...DEFAULT_FILTER_OPTIONS },
+ filterOptions: { ...DEFAULT_FILTER_OPTIONS, owner: ['securitySolution'] },
queryParams: DEFAULT_QUERY_PARAMS,
signal: abortCtrl.signal,
});
@@ -46,6 +48,7 @@ describe('useGetCases', () => {
spyOnGetCases.mockImplementation(() => {
throw new Error('Something went wrong');
});
+
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess, addError });
@@ -56,4 +59,97 @@ describe('useGetCases', () => {
await waitForNextUpdate();
expect(addError).toHaveBeenCalled();
});
+
+ it('should set all owners when no owner is provided', async () => {
+ appMockRender = createAppMockRenderer({ owner: [] });
+
+ appMockRender.coreStart.application.capabilities = {
+ ...appMockRender.coreStart.application.capabilities,
+ observabilityCases: {
+ create_cases: true,
+ read_cases: true,
+ update_cases: true,
+ push_cases: true,
+ cases_connectors: true,
+ delete_cases: true,
+ cases_settings: true,
+ },
+ securitySolutionCases: {
+ create_cases: true,
+ read_cases: true,
+ update_cases: true,
+ push_cases: true,
+ cases_connectors: true,
+ delete_cases: true,
+ cases_settings: true,
+ },
+ };
+
+ const spyOnGetCases = jest.spyOn(api, 'getCases');
+ const { waitForNextUpdate } = renderHook(() => useGetCases(), {
+ wrapper: appMockRender.AppWrapper,
+ });
+
+ await waitForNextUpdate();
+
+ expect(spyOnGetCases).toBeCalledWith({
+ filterOptions: { ...DEFAULT_FILTER_OPTIONS, owner: [...OWNERS] },
+ queryParams: DEFAULT_QUERY_PARAMS,
+ signal: abortCtrl.signal,
+ });
+ });
+
+ it('should set only the available owners when no owner is provided', async () => {
+ appMockRender = createAppMockRenderer({ owner: [] });
+ const spyOnGetCases = jest.spyOn(api, 'getCases');
+
+ const { waitForNextUpdate } = renderHook(() => useGetCases(), {
+ wrapper: appMockRender.AppWrapper,
+ });
+
+ await waitForNextUpdate();
+
+ expect(spyOnGetCases).toBeCalledWith({
+ filterOptions: { ...DEFAULT_FILTER_OPTIONS, owner: ['cases'] },
+ queryParams: DEFAULT_QUERY_PARAMS,
+ signal: abortCtrl.signal,
+ });
+ });
+
+ it('should use the app owner when the filter options do not specify the owner', async () => {
+ appMockRender = createAppMockRenderer({ owner: ['observability'] });
+ const spyOnGetCases = jest.spyOn(api, 'getCases');
+
+ const { waitForNextUpdate } = renderHook(() => useGetCases(), {
+ wrapper: appMockRender.AppWrapper,
+ });
+
+ await waitForNextUpdate();
+
+ expect(spyOnGetCases).toBeCalledWith({
+ filterOptions: { ...DEFAULT_FILTER_OPTIONS, owner: ['observability'] },
+ queryParams: DEFAULT_QUERY_PARAMS,
+ signal: abortCtrl.signal,
+ });
+ });
+
+ it('respects the owner in the filter options if provided', async () => {
+ appMockRender = createAppMockRenderer({ owner: ['observability'] });
+ const spyOnGetCases = jest.spyOn(api, 'getCases');
+
+ const { waitForNextUpdate } = renderHook(
+ () => useGetCases({ filterOptions: { owner: ['my-owner'] } }),
+ {
+ wrapper: appMockRender.AppWrapper,
+ }
+ );
+
+ await waitForNextUpdate();
+
+ expect(spyOnGetCases).toBeCalledWith({
+ filterOptions: { ...DEFAULT_FILTER_OPTIONS, owner: ['my-owner'] },
+ queryParams: DEFAULT_QUERY_PARAMS,
+ signal: abortCtrl.signal,
+ });
+ });
});
diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.tsx
index c182cfbfe3cc1..327f1a99cbe9b 100644
--- a/x-pack/plugins/cases/public/containers/use_get_cases.tsx
+++ b/x-pack/plugins/cases/public/containers/use_get_cases.tsx
@@ -13,6 +13,9 @@ import { useToasts } from '../common/lib/kibana';
import * as i18n from './translations';
import { getCases } from './api';
import type { ServerError } from '../types';
+import { useCasesContext } from '../components/cases_context/use_cases_context';
+import { useAvailableCasesOwners } from '../components/app/use_available_owners';
+import { getAllPermissionsExceptFrom } from '../utils/permissions';
export const initialData: CasesFindResponseUI = {
cases: [],
@@ -31,6 +34,17 @@ export const useGetCases = (
} = {}
): UseQueryResult => {
const toasts = useToasts();
+ const { owner } = useCasesContext();
+ const availableSolutions = useAvailableCasesOwners(getAllPermissionsExceptFrom('delete'));
+
+ const hasOwner = !!owner.length;
+ const initialOwner = hasOwner ? owner : availableSolutions;
+
+ const ownerFilter =
+ params.filterOptions?.owner != null && params.filterOptions.owner.length > 0
+ ? { owner: params.filterOptions.owner }
+ : { owner: initialOwner };
+
return useQuery(
casesQueriesKeys.cases(params),
({ signal }) => {
@@ -38,6 +52,7 @@ export const useGetCases = (
filterOptions: {
...DEFAULT_FILTER_OPTIONS,
...(params.filterOptions ?? {}),
+ ...ownerFilter,
},
queryParams: {
...DEFAULT_QUERY_PARAMS,
diff --git a/x-pack/test/functional/services/cases/list.ts b/x-pack/test/functional/services/cases/list.ts
index 77e250cf838d0..61d588dc261ed 100644
--- a/x-pack/test/functional/services/cases/list.ts
+++ b/x-pack/test/functional/services/cases/list.ts
@@ -183,11 +183,16 @@ export function CasesTableServiceProvider(
await casesCommon.selectFirstRowInAssigneesPopover();
},
- async filterByOwner(owner: string) {
- await common.clickAndValidate(
- 'options-filter-popover-button-owner',
- `options-filter-popover-item-${owner}`
- );
+ async filterByOwner(
+ owner: string,
+ options: { popupAlreadyOpen: boolean } = { popupAlreadyOpen: false }
+ ) {
+ if (!options.popupAlreadyOpen) {
+ await common.clickAndValidate(
+ 'options-filter-popover-button-owner',
+ `options-filter-popover-item-${owner}`
+ );
+ }
await testSubjects.click(`options-filter-popover-item-${owner}`);
},
diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts
index cb9dffb548888..fc313fc502fd8 100644
--- a/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts
+++ b/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts
@@ -318,6 +318,22 @@ export default ({ getPageObject, getService }: FtrProviderContext) => {
}
});
+ it('filters with multiple selection', async () => {
+ await openModal();
+
+ let popupAlreadyOpen = false;
+ for (const [owner] of createdCases.entries()) {
+ await cases.casesTable.filterByOwner(owner, { popupAlreadyOpen });
+ popupAlreadyOpen = true;
+ }
+ await cases.casesTable.waitForTableToFinishLoading();
+
+ for (const caseId of createdCases.values()) {
+ await testSubjects.existOrFail(`cases-table-row-${caseId}`);
+ }
+ await closeModal();
+ });
+
it('attaches correctly', async () => {
for (const [owner, currentCaseId] of createdCases.entries()) {
await openModal();