Skip to content

Commit 27df567

Browse files
fix toast message (#81687) (#82040)
Co-authored-by: Kibana Machine <[email protected]> Co-authored-by: Kibana Machine <[email protected]>
1 parent 996bc38 commit 27df567

File tree

5 files changed

+338
-18
lines changed

5 files changed

+338
-18
lines changed

x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,12 @@ describe('Detections Rules API', () => {
411411
describe('createPrepackagedRules', () => {
412412
beforeEach(() => {
413413
fetchMock.mockClear();
414-
fetchMock.mockResolvedValue('unknown');
414+
fetchMock.mockResolvedValue({
415+
rules_installed: 0,
416+
rules_updated: 0,
417+
timelines_installed: 0,
418+
timelines_updated: 0,
419+
});
415420
});
416421

417422
test('check parameter url when creating pre-packaged rules', async () => {
@@ -423,7 +428,12 @@ describe('Detections Rules API', () => {
423428
});
424429
test('happy path', async () => {
425430
const resp = await createPrepackagedRules({ signal: abortCtrl.signal });
426-
expect(resp).toEqual(true);
431+
expect(resp).toEqual({
432+
rules_installed: 0,
433+
rules_updated: 0,
434+
timelines_installed: 0,
435+
timelines_updated: 0,
436+
});
427437
});
428438
});
429439

x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,25 @@ export const duplicateRules = async ({ rules }: DuplicateRulesProps): Promise<Bu
245245
*
246246
* @throws An error if response is not OK
247247
*/
248-
export const createPrepackagedRules = async ({ signal }: BasicFetchProps): Promise<boolean> => {
249-
await KibanaServices.get().http.fetch<unknown>(DETECTION_ENGINE_PREPACKAGED_URL, {
248+
export const createPrepackagedRules = async ({
249+
signal,
250+
}: BasicFetchProps): Promise<{
251+
rules_installed: number;
252+
rules_updated: number;
253+
timelines_installed: number;
254+
timelines_updated: number;
255+
}> => {
256+
const result = await KibanaServices.get().http.fetch<{
257+
rules_installed: number;
258+
rules_updated: number;
259+
timelines_installed: number;
260+
timelines_updated: number;
261+
}>(DETECTION_ENGINE_PREPACKAGED_URL, {
250262
method: 'PUT',
251263
signal,
252264
});
253265

254-
return true;
266+
return result;
255267
};
256268

257269
/**

x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/translations.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,21 @@ export const RULE_AND_TIMELINE_PREPACKAGED_FAILURE = i18n.translate(
3030
export const RULE_AND_TIMELINE_PREPACKAGED_SUCCESS = i18n.translate(
3131
'xpack.securitySolution.containers.detectionEngine.createPrePackagedRuleAndTimelineSuccesDescription',
3232
{
33-
defaultMessage: 'Installed pre-packaged rules and timelines from elastic',
33+
defaultMessage: 'Installed pre-packaged rules and timeline templates from elastic',
34+
}
35+
);
36+
37+
export const RULE_PREPACKAGED_SUCCESS = i18n.translate(
38+
'xpack.securitySolution.containers.detectionEngine.createPrePackagedRuleSuccesDescription',
39+
{
40+
defaultMessage: 'Installed pre-packaged rules from elastic',
41+
}
42+
);
43+
44+
export const TIMELINE_PREPACKAGED_SUCCESS = i18n.translate(
45+
'xpack.securitySolution.containers.detectionEngine.createPrePackagedTimelineSuccesDescription',
46+
{
47+
defaultMessage: 'Installed pre-packaged timeline templates from elastic',
3448
}
3549
);
3650

x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx

Lines changed: 270 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
* or more contributor license agreements. Licensed under the Elastic License;
44
* you may not use this file except in compliance with the Elastic License.
55
*/
6-
6+
import { ReactElement } from 'react';
77
import { renderHook, act } from '@testing-library/react-hooks';
88
import { ReturnPrePackagedRulesAndTimelines, usePrePackagedRules } from './use_pre_packaged_rules';
99
import * as api from './api';
10+
import { shallow } from 'enzyme';
11+
import * as i18n from './translations';
1012

11-
jest.mock('./api');
13+
jest.mock('./api', () => ({
14+
getPrePackagedRulesStatus: jest.fn(),
15+
createPrepackagedRules: jest.fn(),
16+
}));
1217

1318
describe('usePrePackagedRules', () => {
1419
beforeEach(() => {
@@ -52,6 +57,21 @@ describe('usePrePackagedRules', () => {
5257
});
5358

5459
test('fetch getPrePackagedRulesStatus', async () => {
60+
(api.getPrePackagedRulesStatus as jest.Mock).mockResolvedValue({
61+
rules_custom_installed: 33,
62+
rules_installed: 12,
63+
rules_not_installed: 0,
64+
rules_not_updated: 0,
65+
timelines_installed: 0,
66+
timelines_not_installed: 0,
67+
timelines_not_updated: 0,
68+
});
69+
(api.createPrepackagedRules as jest.Mock).mockResolvedValue({
70+
rules_installed: 0,
71+
rules_updated: 0,
72+
timelines_installed: 0,
73+
timelines_updated: 0,
74+
});
5575
await act(async () => {
5676
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
5777
() =>
@@ -87,7 +107,6 @@ describe('usePrePackagedRules', () => {
87107
});
88108

89109
test('happy path to createPrePackagedRules', async () => {
90-
const spyOnCreatePrepackagedRules = jest.spyOn(api, 'createPrepackagedRules');
91110
await act(async () => {
92111
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
93112
() =>
@@ -106,7 +125,7 @@ describe('usePrePackagedRules', () => {
106125
resp = await result.current.createPrePackagedRules();
107126
}
108127
expect(resp).toEqual(true);
109-
expect(spyOnCreatePrepackagedRules).toHaveBeenCalled();
128+
expect(api.createPrepackagedRules).toHaveBeenCalled();
110129
expect(result.current).toEqual({
111130
getLoadPrebuiltRulesAndTemplatesButton:
112131
result.current.getLoadPrebuiltRulesAndTemplatesButton,
@@ -127,6 +146,253 @@ describe('usePrePackagedRules', () => {
127146
});
128147
});
129148

149+
test('getLoadPrebuiltRulesAndTemplatesButton - LOAD_PREPACKAGED_RULES', async () => {
150+
(api.getPrePackagedRulesStatus as jest.Mock).mockResolvedValue({
151+
rules_custom_installed: 0,
152+
rules_installed: 0,
153+
rules_not_installed: 1,
154+
rules_not_updated: 0,
155+
timelines_installed: 0,
156+
timelines_not_installed: 0,
157+
timelines_not_updated: 0,
158+
});
159+
(api.createPrepackagedRules as jest.Mock).mockResolvedValue({
160+
rules_installed: 0,
161+
rules_updated: 0,
162+
timelines_installed: 0,
163+
timelines_updated: 0,
164+
});
165+
await act(async () => {
166+
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
167+
() =>
168+
usePrePackagedRules({
169+
canUserCRUD: true,
170+
hasIndexWrite: true,
171+
isAuthenticated: true,
172+
hasEncryptionKey: true,
173+
isSignalIndexExists: true,
174+
})
175+
);
176+
await waitForNextUpdate();
177+
await waitForNextUpdate();
178+
179+
const button = result.current.getLoadPrebuiltRulesAndTemplatesButton({
180+
isDisabled: false,
181+
onClick: jest.fn(),
182+
'data-test-subj': 'button',
183+
});
184+
const wrapper = shallow(button as ReactElement);
185+
expect(wrapper.find('[data-test-subj="button"]').text()).toEqual(i18n.LOAD_PREPACKAGED_RULES);
186+
});
187+
});
188+
189+
test('getLoadPrebuiltRulesAndTemplatesButton - LOAD_PREPACKAGED_TIMELINE_TEMPLATES', async () => {
190+
(api.getPrePackagedRulesStatus as jest.Mock).mockResolvedValue({
191+
rules_custom_installed: 0,
192+
rules_installed: 0,
193+
rules_not_installed: 0,
194+
rules_not_updated: 0,
195+
timelines_installed: 0,
196+
timelines_not_installed: 1,
197+
timelines_not_updated: 0,
198+
});
199+
(api.createPrepackagedRules as jest.Mock).mockResolvedValue({
200+
rules_installed: 0,
201+
rules_updated: 0,
202+
timelines_installed: 0,
203+
timelines_updated: 0,
204+
});
205+
await act(async () => {
206+
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
207+
() =>
208+
usePrePackagedRules({
209+
canUserCRUD: true,
210+
hasIndexWrite: true,
211+
isAuthenticated: true,
212+
hasEncryptionKey: true,
213+
isSignalIndexExists: true,
214+
})
215+
);
216+
await waitForNextUpdate();
217+
await waitForNextUpdate();
218+
219+
const button = result.current.getLoadPrebuiltRulesAndTemplatesButton({
220+
isDisabled: false,
221+
onClick: jest.fn(),
222+
'data-test-subj': 'button',
223+
});
224+
const wrapper = shallow(button as ReactElement);
225+
expect(wrapper.find('[data-test-subj="button"]').text()).toEqual(
226+
i18n.LOAD_PREPACKAGED_TIMELINE_TEMPLATES
227+
);
228+
});
229+
});
230+
231+
test('getLoadPrebuiltRulesAndTemplatesButton - LOAD_PREPACKAGED_RULES_AND_TEMPLATES', async () => {
232+
(api.getPrePackagedRulesStatus as jest.Mock).mockResolvedValue({
233+
rules_custom_installed: 0,
234+
rules_installed: 0,
235+
rules_not_installed: 1,
236+
rules_not_updated: 0,
237+
timelines_installed: 0,
238+
timelines_not_installed: 1,
239+
timelines_not_updated: 0,
240+
});
241+
(api.createPrepackagedRules as jest.Mock).mockResolvedValue({
242+
rules_installed: 0,
243+
rules_updated: 0,
244+
timelines_installed: 0,
245+
timelines_updated: 0,
246+
});
247+
await act(async () => {
248+
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
249+
() =>
250+
usePrePackagedRules({
251+
canUserCRUD: true,
252+
hasIndexWrite: true,
253+
isAuthenticated: true,
254+
hasEncryptionKey: true,
255+
isSignalIndexExists: true,
256+
})
257+
);
258+
await waitForNextUpdate();
259+
await waitForNextUpdate();
260+
261+
const button = result.current.getLoadPrebuiltRulesAndTemplatesButton({
262+
isDisabled: false,
263+
onClick: jest.fn(),
264+
'data-test-subj': 'button',
265+
});
266+
const wrapper = shallow(button as ReactElement);
267+
expect(wrapper.find('[data-test-subj="button"]').text()).toEqual(
268+
i18n.LOAD_PREPACKAGED_RULES_AND_TEMPLATES
269+
);
270+
});
271+
});
272+
273+
test('getReloadPrebuiltRulesAndTemplatesButton - missing rules and templates', async () => {
274+
(api.getPrePackagedRulesStatus as jest.Mock).mockResolvedValue({
275+
rules_custom_installed: 0,
276+
rules_installed: 1,
277+
rules_not_installed: 1,
278+
rules_not_updated: 0,
279+
timelines_installed: 0,
280+
timelines_not_installed: 1,
281+
timelines_not_updated: 0,
282+
});
283+
(api.createPrepackagedRules as jest.Mock).mockResolvedValue({
284+
rules_installed: 0,
285+
rules_updated: 0,
286+
timelines_installed: 0,
287+
timelines_updated: 0,
288+
});
289+
await act(async () => {
290+
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
291+
() =>
292+
usePrePackagedRules({
293+
canUserCRUD: true,
294+
hasIndexWrite: true,
295+
isAuthenticated: true,
296+
hasEncryptionKey: true,
297+
isSignalIndexExists: true,
298+
})
299+
);
300+
await waitForNextUpdate();
301+
await waitForNextUpdate();
302+
303+
const button = result.current.getReloadPrebuiltRulesAndTemplatesButton({
304+
isDisabled: false,
305+
onClick: jest.fn(),
306+
});
307+
const wrapper = shallow(button as ReactElement);
308+
expect(wrapper.find('[data-test-subj="reloadPrebuiltRulesBtn"]').text()).toEqual(
309+
'Install 1 Elastic prebuilt rule and 1 Elastic prebuilt timeline '
310+
);
311+
});
312+
});
313+
314+
test('getReloadPrebuiltRulesAndTemplatesButton - missing rules', async () => {
315+
(api.getPrePackagedRulesStatus as jest.Mock).mockResolvedValue({
316+
rules_custom_installed: 0,
317+
rules_installed: 1,
318+
rules_not_installed: 1,
319+
rules_not_updated: 0,
320+
timelines_installed: 0,
321+
timelines_not_installed: 0,
322+
timelines_not_updated: 0,
323+
});
324+
(api.createPrepackagedRules as jest.Mock).mockResolvedValue({
325+
rules_installed: 0,
326+
rules_updated: 0,
327+
timelines_installed: 0,
328+
timelines_updated: 0,
329+
});
330+
await act(async () => {
331+
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
332+
() =>
333+
usePrePackagedRules({
334+
canUserCRUD: true,
335+
hasIndexWrite: true,
336+
isAuthenticated: true,
337+
hasEncryptionKey: true,
338+
isSignalIndexExists: true,
339+
})
340+
);
341+
await waitForNextUpdate();
342+
await waitForNextUpdate();
343+
344+
const button = result.current.getReloadPrebuiltRulesAndTemplatesButton({
345+
isDisabled: false,
346+
onClick: jest.fn(),
347+
});
348+
const wrapper = shallow(button as ReactElement);
349+
expect(wrapper.find('[data-test-subj="reloadPrebuiltRulesBtn"]').text()).toEqual(
350+
'Install 1 Elastic prebuilt rule '
351+
);
352+
});
353+
});
354+
355+
test('getReloadPrebuiltRulesAndTemplatesButton - missing templates', async () => {
356+
(api.getPrePackagedRulesStatus as jest.Mock).mockResolvedValue({
357+
rules_custom_installed: 0,
358+
rules_installed: 1,
359+
rules_not_installed: 0,
360+
rules_not_updated: 0,
361+
timelines_installed: 1,
362+
timelines_not_installed: 1,
363+
timelines_not_updated: 0,
364+
});
365+
(api.createPrepackagedRules as jest.Mock).mockResolvedValue({
366+
rules_installed: 0,
367+
rules_updated: 0,
368+
timelines_installed: 0,
369+
timelines_updated: 0,
370+
});
371+
await act(async () => {
372+
const { result, waitForNextUpdate } = renderHook<unknown, ReturnPrePackagedRulesAndTimelines>(
373+
() =>
374+
usePrePackagedRules({
375+
canUserCRUD: true,
376+
hasIndexWrite: true,
377+
isAuthenticated: true,
378+
hasEncryptionKey: true,
379+
isSignalIndexExists: true,
380+
})
381+
);
382+
await waitForNextUpdate();
383+
await waitForNextUpdate();
384+
385+
const button = result.current.getReloadPrebuiltRulesAndTemplatesButton({
386+
isDisabled: false,
387+
onClick: jest.fn(),
388+
});
389+
const wrapper = shallow(button as ReactElement);
390+
expect(wrapper.find('[data-test-subj="reloadPrebuiltRulesBtn"]').text()).toEqual(
391+
'Install 1 Elastic prebuilt timeline '
392+
);
393+
});
394+
});
395+
130396
test('unhappy path to createPrePackagedRules', async () => {
131397
const spyOnCreatePrepackagedRules = jest.spyOn(api, 'createPrepackagedRules');
132398
spyOnCreatePrepackagedRules.mockImplementation(() => {

0 commit comments

Comments
 (0)