From 61544bbfc8680ab11756891e7abcc83d33da7040 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Fri, 30 Oct 2020 13:24:35 -0400 Subject: [PATCH 01/14] Added log_retention_logic and setOpenModal --- .../log_retention/log_retention_logic.test.ts | 61 +++++++++++++++++++ .../log_retention/log_retention_logic.ts | 32 ++++++++++ .../settings/log_retention/types.ts | 10 +++ 3 files changed, 103 insertions(+) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts new file mode 100644 index 0000000000000..78c51c8f715fc --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { resetContext } from 'kea'; + +import { ELogRetentionOptions } from './types'; +import { LogRetentionLogic } from './log_retention_logic'; + +describe('LogRetentionLogic', () => { + const DEFAULT_VALUES = { + openModal: null, + }; + + const mount = (defaults?: object) => { + if (!defaults) { + resetContext({}); + } else { + resetContext({ + defaults: { + enterprise_search: { + app_search: { + log_retention_logic: { + ...defaults, + }, + }, + }, + }, + }); + } + LogRetentionLogic.mount(); + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('has expected default values', () => { + mount(); + expect(LogRetentionLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('actions', () => { + describe('setOpenModal', () => { + describe('openModal', () => { + it('should be set to the provided value', () => { + mount(); + + LogRetentionLogic.actions.setOpenModal(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + openModal: ELogRetentionOptions.Analytics, + }); + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts new file mode 100644 index 0000000000000..92bc2eec79403 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { ELogRetentionOptions } from './types'; + +interface ILogRetentionActions { + setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; +} + +interface ILogRetentionValues { + openModal: ELogRetentionOptions | null; +} + +export const LogRetentionLogic = kea>({ + path: ['enterprise_search', 'app_search', 'log_retention_logic'], + actions: () => ({ + setOpenModal: (option) => ({ option }), + }), + reducers: () => ({ + openModal: [ + null, + { + setOpenModal: (_, { option }) => option, + }, + ], + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts new file mode 100644 index 0000000000000..3164900afe781 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export enum ELogRetentionOptions { + Analytics = 'analytics', + API = 'api', +} From df72b998c06845321f973e1226a24177f59e183a Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Fri, 30 Oct 2020 13:46:19 -0400 Subject: [PATCH 02/14] Added closeModals to log_retention_logic Note that I changd it to set logsRetentionUpdating to false instead of null so that our types were correct --- .../log_retention/log_retention_logic.test.ts | 33 +++++++++++++++++++ .../log_retention/log_retention_logic.ts | 10 ++++++ 2 files changed, 43 insertions(+) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 78c51c8f715fc..726e075c33dc9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -12,6 +12,7 @@ import { LogRetentionLogic } from './log_retention_logic'; describe('LogRetentionLogic', () => { const DEFAULT_VALUES = { openModal: null, + logsRetentionUpdating: false, }; const mount = (defaults?: object) => { @@ -57,5 +58,37 @@ describe('LogRetentionLogic', () => { }); }); }); + + describe('closeModals', () => { + describe('openModal', () => { + it('resets openModal to null', () => { + mount({ + openModal: 'analytics', + }); + + LogRetentionLogic.actions.closeModals(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + openModal: null, + }); + }); + }); + + describe('logsRetentionUpdating', () => { + it('resets logsRetentionUpdating to false', () => { + mount({ + logsRetentionUpdating: true, + }); + + LogRetentionLogic.actions.closeModals(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + logsRetentionUpdating: false, + }); + }); + }); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index 92bc2eec79403..b5ff3634033f7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -10,9 +10,11 @@ import { ELogRetentionOptions } from './types'; interface ILogRetentionActions { setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; + closeModals(): { value: boolean }; } interface ILogRetentionValues { + logsRetentionUpdating: boolean; openModal: ELogRetentionOptions | null; } @@ -20,11 +22,19 @@ export const LogRetentionLogic = kea ({ setOpenModal: (option) => ({ option }), + closeModals: true, }), reducers: () => ({ + logsRetentionUpdating: [ + false, + { + closeModals: () => false, + }, + ], openModal: [ null, { + closeModals: () => null, setOpenModal: (_, { option }) => option, }, ], From 059a04ffca4648ad166e0f290ddca975d4c90c8d Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Fri, 30 Oct 2020 13:54:53 -0400 Subject: [PATCH 03/14] Added clearLogRetentionUpdating --- .../log_retention/log_retention_logic.test.ts | 17 +++++++++++++++++ .../log_retention/log_retention_logic.ts | 7 +++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 726e075c33dc9..06dc6e567e4d4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -90,5 +90,22 @@ describe('LogRetentionLogic', () => { }); }); }); + + describe('clearLogRetentionUpdating', () => { + describe('logsRetentionUpdating', () => { + it('resets logsRetentionUpdating to false', () => { + mount({ + logsRetentionUpdating: true, + }); + + LogRetentionLogic.actions.clearLogRetentionUpdating(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + logsRetentionUpdating: false, + }); + }); + }); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index b5ff3634033f7..f8a0c12166886 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -9,8 +9,9 @@ import { kea, MakeLogicType } from 'kea'; import { ELogRetentionOptions } from './types'; interface ILogRetentionActions { - setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; + clearLogRetentionUpdating(): { value: boolean }; closeModals(): { value: boolean }; + setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; } interface ILogRetentionValues { @@ -21,13 +22,15 @@ interface ILogRetentionValues { export const LogRetentionLogic = kea>({ path: ['enterprise_search', 'app_search', 'log_retention_logic'], actions: () => ({ - setOpenModal: (option) => ({ option }), + clearLogRetentionUpdating: true, closeModals: true, + setOpenModal: (option) => ({ option }), }), reducers: () => ({ logsRetentionUpdating: [ false, { + clearLogRetentionUpdating: () => false, closeModals: () => false, }, ], From 9024d597c3935b5d11b7aa06b7167eab94ae876d Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Fri, 30 Oct 2020 14:23:51 -0400 Subject: [PATCH 04/14] Added updateLogRetention --- .../log_retention/log_retention_logic.test.ts | 44 +++++++++++++++++++ .../log_retention/log_retention_logic.ts | 22 +++++++++- .../settings/log_retention/types.ts | 16 +++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 06dc6e567e4d4..108db09a16e81 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -11,6 +11,7 @@ import { LogRetentionLogic } from './log_retention_logic'; describe('LogRetentionLogic', () => { const DEFAULT_VALUES = { + logRetention: null, openModal: null, logsRetentionUpdating: false, }; @@ -107,5 +108,48 @@ describe('LogRetentionLogic', () => { }); }); }); + + describe('updateLogRetention', () => { + describe('logRetention', () => { + it('updates the logRetention values that are passed, and defaults the others that are not set', () => { + mount({ + logRetention: {}, + }); + + LogRetentionLogic.actions.updateLogRetention({ + api: { enabled: true }, + }); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + logRetention: { + api: { enabled: true }, + analytics: {}, // This is defaulted to {} + }, + }); + }); + + it('updates the logRetention values that are passed, and retains that values that are already set', () => { + mount({ + logRetention: { + api: { enabled: true }, + analytics: { enabled: true }, + }, + }); + + LogRetentionLogic.actions.updateLogRetention({ + api: { enabled: false }, + }); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + logRetention: { + api: { enabled: false }, + analytics: { enabled: true }, + }, + }); + }); + }); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index f8a0c12166886..6a9e488674f3f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -6,15 +6,17 @@ import { kea, MakeLogicType } from 'kea'; -import { ELogRetentionOptions } from './types'; +import { ELogRetentionOptions, ILogRetention } from './types'; interface ILogRetentionActions { clearLogRetentionUpdating(): { value: boolean }; closeModals(): { value: boolean }; setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; + updateLogRetention(logRetention: ILogRetention): { logRetention: ILogRetention }; } interface ILogRetentionValues { + logRetention: ILogRetention | null; logsRetentionUpdating: boolean; openModal: ELogRetentionOptions | null; } @@ -25,8 +27,26 @@ export const LogRetentionLogic = kea ({ option }), + updateLogRetention: (logRetention) => ({ logRetention }), }), reducers: () => ({ + logRetention: [ + null, + { + updateLogRetention: (previousValue, { logRetention }) => { + return { + [ELogRetentionOptions.Analytics]: { + ...previousValue?.[ELogRetentionOptions.Analytics], + ...logRetention[ELogRetentionOptions.Analytics], + }, + [ELogRetentionOptions.API]: { + ...previousValue?.[ELogRetentionOptions.API], + ...logRetention[ELogRetentionOptions.API], + }, + }; + }, + }, + ], logsRetentionUpdating: [ false, { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts index 3164900afe781..186780d830029 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts @@ -8,3 +8,19 @@ export enum ELogRetentionOptions { Analytics = 'analytics', API = 'api', } + +export interface ILogRetention { + [ELogRetentionOptions.Analytics]?: ILogRetentionSettings; + [ELogRetentionOptions.API]?: ILogRetentionSettings; +} + +export interface ILogRetentionPolicy { + isDefault: boolean; + minAgeDays: number | null; +} + +export interface ILogRetentionSettings { + disabledAt?: string | null; + enabled?: boolean; + retentionPolicy?: ILogRetentionPolicy | null; +} From 0ac6bf8ea202837093964a498693ef0956cba47e Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Mon, 2 Nov 2020 13:22:47 -0500 Subject: [PATCH 05/14] Added saveLogRetention --- .../log_retention/log_retention_logic.test.ts | 91 +++++++++++++++++++ .../log_retention/log_retention_logic.ts | 30 +++++- .../settings/log_retention/types.ts | 16 ++++ .../utils/convert_log_retention.test.ts | 64 +++++++++++++ .../utils/convert_log_retention.ts | 45 +++++++++ 5 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 108db09a16e81..43ebb32a8156b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -6,6 +6,17 @@ import { resetContext } from 'kea'; +import { mockHttpValues } from '../../../../__mocks__'; +jest.mock('../../../../shared/http', () => ({ + HttpLogic: { values: mockHttpValues }, +})); +const { http } = mockHttpValues; + +jest.mock('../../../../shared/flash_messages', () => ({ + flashAPIErrors: jest.fn(), +})); +import { flashAPIErrors } from '../../../../shared/flash_messages'; + import { ELogRetentionOptions } from './types'; import { LogRetentionLogic } from './log_retention_logic'; @@ -151,5 +162,85 @@ describe('LogRetentionLogic', () => { }); }); }); + + describe('saveLogRetention', () => { + beforeEach(() => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + }); + + describe('openModal', () => { + it('should be reset to null', () => { + mount({ + openModal: ELogRetentionOptions.Analytics, + }); + + LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + openModal: null, + }); + }); + }); + + it('will call an API endpoint and update log retention', async () => { + jest.spyOn(LogRetentionLogic.actions, 'updateLogRetention'); + const promise = Promise.resolve({ + analytics: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + api: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + }); + http.put.mockReturnValue(promise); + + LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); + + expect(http.put).toHaveBeenCalledWith(`/api/app_search/log_settings`, { + body: JSON.stringify({ + analytics: { + enabled: true, + }, + }), + }); + + await promise; + expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith({ + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + }); + + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + + it('handles errors', async () => { + const promise = Promise.reject('An error occured'); + http.put.mockReturnValue(promise); + + LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); + + try { + await promise; + } catch { + // Do nothing + } + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index 6a9e488674f3f..52021734a2f57 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -6,11 +6,18 @@ import { kea, MakeLogicType } from 'kea'; -import { ELogRetentionOptions, ILogRetention } from './types'; +import { ELogRetentionOptions, ILogRetention, ILogRetentionServer } from './types'; +import { HttpLogic } from '../../../../shared/http'; +import { flashAPIErrors } from '../../../../shared/flash_messages'; +import { convertLogRetentionFromServerToClient } from './utils/convert_log_retention'; interface ILogRetentionActions { clearLogRetentionUpdating(): { value: boolean }; closeModals(): { value: boolean }; + saveLogRetention( + option: ELogRetentionOptions, + enabled: boolean + ): { option: ELogRetentionOptions; enabled: boolean }; setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; updateLogRetention(logRetention: ILogRetention): { logRetention: ILogRetention }; } @@ -26,6 +33,7 @@ export const LogRetentionLogic = kea ({ clearLogRetentionUpdating: true, closeModals: true, + saveLogRetention: (option, enabled) => ({ enabled, option }), setOpenModal: (option) => ({ option }), updateLogRetention: (logRetention) => ({ logRetention }), }), @@ -58,8 +66,28 @@ export const LogRetentionLogic = kea null, + saveLogRetention: () => null, setOpenModal: (_, { option }) => option, }, ], }), + listeners: ({ actions }) => ({ + saveLogRetention: async ({ enabled, option }) => { + const updateData = { [option.toString()]: { enabled } }; + + try { + const { http } = HttpLogic.values; + const response = await http.put('/api/app_search/log_settings', { + body: JSON.stringify(updateData), + }); + actions.updateLogRetention( + convertLogRetentionFromServerToClient(response as ILogRetentionServer) + ); + } catch (e) { + flashAPIErrors(e); + } finally { + actions.clearLogRetentionUpdating(); + } + }, + }), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts index 186780d830029..41745097dbe15 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts @@ -24,3 +24,19 @@ export interface ILogRetentionSettings { enabled?: boolean; retentionPolicy?: ILogRetentionPolicy | null; } + +export interface ILogRetentionServer { + [ELogRetentionOptions.Analytics]: ILogRetentionServerSettings; + [ELogRetentionOptions.API]: ILogRetentionServerSettings; +} + +export interface ILogRetentionServerPolicy { + is_default: boolean; + min_age_days: number | null; +} + +export interface ILogRetentionServerSettings { + disabled_at: string | null; + enabled: boolean; + retention_policy: ILogRetentionServerPolicy | null; +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.test.ts new file mode 100644 index 0000000000000..b49b2afe50831 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.test.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { convertLogRetentionFromServerToClient } from './convert_log_retention'; + +describe('convertLogRetentionFromServerToClient', () => { + it('converts log retention from server to client', () => { + expect( + convertLogRetentionFromServerToClient({ + analytics: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + api: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + }) + ).toEqual({ + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + }); + }); + + it('handles null retention policies and null min_age_days', () => { + expect( + convertLogRetentionFromServerToClient({ + analytics: { + disabled_at: null, + enabled: true, + retention_policy: null, + }, + api: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: null }, + }, + }) + ).toEqual({ + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: null }, + }, + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts new file mode 100644 index 0000000000000..857784401ca96 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + ELogRetentionOptions, + ILogRetention, + ILogRetentionPolicy, + ILogRetentionServer, + ILogRetentionServerPolicy, + ILogRetentionServerSettings, + ILogRetentionSettings, +} from '../types'; + +export const convertLogRetentionFromServerToClient = ( + logRetention: ILogRetentionServer +): ILogRetention => ({ + [ELogRetentionOptions.Analytics]: convertLogRetentionSettingsFromServerToClient( + logRetention[ELogRetentionOptions.Analytics] + ), + [ELogRetentionOptions.API]: convertLogRetentionSettingsFromServerToClient( + logRetention[ELogRetentionOptions.API] + ), +}); + +const convertLogRetentionSettingsFromServerToClient = ({ + disabled_at: disabledAt, + enabled, + retention_policy: retentionPolicy, +}: ILogRetentionServerSettings): ILogRetentionSettings => ({ + disabledAt, + enabled, + retentionPolicy: + retentionPolicy === null ? null : convertLogRetentionPolicyFromServerToClient(retentionPolicy), +}); + +const convertLogRetentionPolicyFromServerToClient = ({ + min_age_days: minAgeDays, + is_default: isDefault, +}: ILogRetentionServerPolicy): ILogRetentionPolicy => ({ + isDefault, + minAgeDays: minAgeDays === null ? null : minAgeDays, +}); From fc94421aa67ba714d94e791e54f0fcd137417481 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Mon, 2 Nov 2020 14:22:56 -0500 Subject: [PATCH 06/14] Added toggleLogRetention --- .../log_retention/log_retention_logic.test.ts | 65 +++++++++++++++++++ .../log_retention/log_retention_logic.ts | 21 +++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 43ebb32a8156b..1187cb1d47cf0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -242,5 +242,70 @@ describe('LogRetentionLogic', () => { expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); }); }); + + describe('toggleLogRetention', () => { + describe('logsRetentionUpdating', () => { + it('sets logsRetentionUpdating to true', () => { + mount({ + logsRetentionUpdating: false, + }); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + logsRetentionUpdating: true, + }); + }); + }); + + it('will call setOpenModal if already enabled', () => { + mount({ + logRetention: { + [ELogRetentionOptions.Analytics]: { + enabled: true, + }, + }, + }); + jest.spyOn(LogRetentionLogic.actions, 'setOpenModal'); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.actions.setOpenModal).toHaveBeenCalledWith( + ELogRetentionOptions.Analytics + ); + }); + }); + + it('will call saveLogRetention if NOT already enabled', () => { + mount({ + logRetention: { + [ELogRetentionOptions.Analytics]: { + enabled: false, + }, + }, + }); + jest.spyOn(LogRetentionLogic.actions, 'saveLogRetention'); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.actions.saveLogRetention).toHaveBeenCalledWith( + ELogRetentionOptions.Analytics, + true + ); + }); + + it('will do nothing if logRetention option is not yet set', () => { + mount({ + logRetention: {}, + }); + jest.spyOn(LogRetentionLogic.actions, 'saveLogRetention'); + jest.spyOn(LogRetentionLogic.actions, 'setOpenModal'); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.API); + + expect(LogRetentionLogic.actions.saveLogRetention).not.toHaveBeenCalled(); + expect(LogRetentionLogic.actions.setOpenModal).not.toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index 52021734a2f57..3393d1e69eabf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -19,6 +19,7 @@ interface ILogRetentionActions { enabled: boolean ): { option: ELogRetentionOptions; enabled: boolean }; setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; + toggleLogRetention(option: ELogRetentionOptions): { option: ELogRetentionOptions }; updateLogRetention(logRetention: ILogRetention): { logRetention: ILogRetention }; } @@ -35,6 +36,7 @@ export const LogRetentionLogic = kea ({ enabled, option }), setOpenModal: (option) => ({ option }), + toggleLogRetention: (option) => ({ option }), updateLogRetention: (logRetention) => ({ logRetention }), }), reducers: () => ({ @@ -60,6 +62,7 @@ export const LogRetentionLogic = kea false, closeModals: () => false, + toggleLogRetention: () => true, }, ], openModal: [ @@ -71,7 +74,7 @@ export const LogRetentionLogic = kea ({ + listeners: ({ actions, values }) => ({ saveLogRetention: async ({ enabled, option }) => { const updateData = { [option.toString()]: { enabled } }; @@ -89,5 +92,21 @@ export const LogRetentionLogic = kea { + const logRetention = values.logRetention && values.logRetention[option]; + + // If the user has found a way to call this before we've retrieved + // log retention settings from the server, short circuit this and return early + if (!logRetention) { + return; + } + + const optionIsAlreadyEnabled = logRetention.enabled; + if (optionIsAlreadyEnabled) { + actions.setOpenModal(option); + } else { + actions.saveLogRetention(option, true); + } + }, }), }); From 701951dd222abee03680b32ab95bdc86d3b86fbe Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Mon, 2 Nov 2020 14:35:11 -0500 Subject: [PATCH 07/14] Added fetchLogRetention --- .../log_retention/log_retention_logic.test.ts | 107 ++++++++++++++---- .../log_retention/log_retention_logic.ts | 16 +++ 2 files changed, 99 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 1187cb1d47cf0..ba88dd53a67e8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -21,6 +21,32 @@ import { ELogRetentionOptions } from './types'; import { LogRetentionLogic } from './log_retention_logic'; describe('LogRetentionLogic', () => { + const TYPICAL_SERVER_LOG_RETENTION = { + analytics: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + api: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + }; + + const TYPICAL_CLIENT_LOG_RETENTION = { + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + }; + const DEFAULT_VALUES = { logRetention: null, openModal: null, @@ -186,18 +212,7 @@ describe('LogRetentionLogic', () => { it('will call an API endpoint and update log retention', async () => { jest.spyOn(LogRetentionLogic.actions, 'updateLogRetention'); - const promise = Promise.resolve({ - analytics: { - disabled_at: null, - enabled: true, - retention_policy: { is_default: true, min_age_days: 180 }, - }, - api: { - disabled_at: null, - enabled: true, - retention_policy: { is_default: true, min_age_days: 180 }, - }, - }); + const promise = Promise.resolve(TYPICAL_SERVER_LOG_RETENTION); http.put.mockReturnValue(promise); LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); @@ -211,18 +226,9 @@ describe('LogRetentionLogic', () => { }); await promise; - expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith({ - analytics: { - disabledAt: null, - enabled: true, - retentionPolicy: { isDefault: true, minAgeDays: 180 }, - }, - api: { - disabledAt: null, - enabled: true, - retentionPolicy: { isDefault: true, minAgeDays: 180 }, - }, - }); + expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( + TYPICAL_CLIENT_LOG_RETENTION + ); expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); }); @@ -308,4 +314,57 @@ describe('LogRetentionLogic', () => { expect(LogRetentionLogic.actions.setOpenModal).not.toHaveBeenCalled(); }); }); + + describe('fetchLogRetention', () => { + describe('logsRetentionUpdating', () => { + it('sets logsRetentionUpdating to true', () => { + mount({ + logsRetentionUpdating: false, + }); + + LogRetentionLogic.actions.fetchLogRetention(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + logsRetentionUpdating: true, + }); + }); + }); + + it('will call an API endpoint and update log retention', async () => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + jest.spyOn(LogRetentionLogic.actions, 'updateLogRetention').mockImplementationOnce(() => {}); + + const promise = Promise.resolve(TYPICAL_SERVER_LOG_RETENTION); + http.get.mockReturnValue(promise); + + LogRetentionLogic.actions.fetchLogRetention(); + + expect(http.get).toHaveBeenCalledWith(`/api/app_search/log_settings`); + await promise; + expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( + TYPICAL_CLIENT_LOG_RETENTION + ); + + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + + it('handles errors', async () => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + const promise = Promise.reject('An error occured'); + http.get.mockReturnValue(promise); + + LogRetentionLogic.actions.fetchLogRetention(); + + try { + await promise; + } catch { + // Do nothing + } + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index 3393d1e69eabf..9fac2ebfd787f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -14,6 +14,7 @@ import { convertLogRetentionFromServerToClient } from './utils/convert_log_reten interface ILogRetentionActions { clearLogRetentionUpdating(): { value: boolean }; closeModals(): { value: boolean }; + fetchLogRetention(): { value: boolean }; saveLogRetention( option: ELogRetentionOptions, enabled: boolean @@ -34,6 +35,7 @@ export const LogRetentionLogic = kea ({ clearLogRetentionUpdating: true, closeModals: true, + fetchLogRetention: true, saveLogRetention: (option, enabled) => ({ enabled, option }), setOpenModal: (option) => ({ option }), toggleLogRetention: (option) => ({ option }), @@ -62,6 +64,7 @@ export const LogRetentionLogic = kea false, closeModals: () => false, + fetchLogRetention: () => true, toggleLogRetention: () => true, }, ], @@ -75,6 +78,19 @@ export const LogRetentionLogic = kea ({ + fetchLogRetention: async () => { + try { + const { http } = HttpLogic.values; + const response = await http.get('/api/app_search/log_settings'); + actions.updateLogRetention( + convertLogRetentionFromServerToClient(response as ILogRetentionServer) + ); + } catch (e) { + flashAPIErrors(e); + } finally { + actions.clearLogRetentionUpdating(); + } + }, saveLogRetention: async ({ enabled, option }) => { const updateData = { [option.toString()]: { enabled } }; From be76a85a3fe1c7656465c9759a0ccc42d4dee05c Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 4 Nov 2020 09:05:21 -0500 Subject: [PATCH 08/14] Apply suggestions from code review Co-authored-by: Constance --- .../settings/log_retention/log_retention_logic.test.ts | 4 ++-- .../components/settings/log_retention/log_retention_logic.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index ba88dd53a67e8..d41ed9b003f10 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -217,7 +217,7 @@ describe('LogRetentionLogic', () => { LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); - expect(http.put).toHaveBeenCalledWith(`/api/app_search/log_settings`, { + expect(http.put).toHaveBeenCalledWith('/api/app_search/log_settings', { body: JSON.stringify({ analytics: { enabled: true, @@ -341,7 +341,7 @@ describe('LogRetentionLogic', () => { LogRetentionLogic.actions.fetchLogRetention(); - expect(http.get).toHaveBeenCalledWith(`/api/app_search/log_settings`); + expect(http.get).toHaveBeenCalledWith('/api/app_search/log_settings'); await promise; expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( TYPICAL_CLIENT_LOG_RETENTION diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index 9fac2ebfd787f..e69e939c4e041 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -109,7 +109,7 @@ export const LogRetentionLogic = kea { - const logRetention = values.logRetention && values.logRetention[option]; + const logRetention = values.logRetention?.[option]; // If the user has found a way to call this before we've retrieved // log retention settings from the server, short circuit this and return early From 6b0989e811c6d65ac412997c5fdd9c720e0a15be Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 4 Nov 2020 09:08:35 -0500 Subject: [PATCH 09/14] Dont call toString on enum --- .../components/settings/log_retention/log_retention_logic.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index e69e939c4e041..b5b83ff313ed1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -92,7 +92,7 @@ export const LogRetentionLogic = kea { - const updateData = { [option.toString()]: { enabled } }; + const updateData = { [option]: { enabled } }; try { const { http } = HttpLogic.values; From 42cc30b8cb2b4b5b2a8ba402d4c92862889775cf Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 4 Nov 2020 09:09:50 -0500 Subject: [PATCH 10/14] Simplified null check --- .../settings/log_retention/utils/convert_log_retention.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts index 857784401ca96..1c0818fc286f2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts @@ -41,5 +41,5 @@ const convertLogRetentionPolicyFromServerToClient = ({ is_default: isDefault, }: ILogRetentionServerPolicy): ILogRetentionPolicy => ({ isDefault, - minAgeDays: minAgeDays === null ? null : minAgeDays, + minAgeDays, }); From 267d2333ff8539ccd6e106607a8a12e78a3d92d6 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 4 Nov 2020 09:17:03 -0500 Subject: [PATCH 11/14] Rename openModal --- .../log_retention/log_retention_logic.test.ts | 34 +++++++++---------- .../log_retention/log_retention_logic.ts | 12 +++---- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index d41ed9b003f10..9659634ecacb2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -49,7 +49,7 @@ describe('LogRetentionLogic', () => { const DEFAULT_VALUES = { logRetention: null, - openModal: null, + openedModal: null, logsRetentionUpdating: false, }; @@ -82,33 +82,33 @@ describe('LogRetentionLogic', () => { }); describe('actions', () => { - describe('setOpenModal', () => { - describe('openModal', () => { + describe('setOpenedModal', () => { + describe('openedModal', () => { it('should be set to the provided value', () => { mount(); - LogRetentionLogic.actions.setOpenModal(ELogRetentionOptions.Analytics); + LogRetentionLogic.actions.setOpenedModal(ELogRetentionOptions.Analytics); expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, - openModal: ELogRetentionOptions.Analytics, + openedModal: ELogRetentionOptions.Analytics, }); }); }); }); describe('closeModals', () => { - describe('openModal', () => { - it('resets openModal to null', () => { + describe('openedModal', () => { + it('resets openedModal to null', () => { mount({ - openModal: 'analytics', + openedModal: 'analytics', }); LogRetentionLogic.actions.closeModals(); expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, - openModal: null, + openedModal: null, }); }); }); @@ -195,17 +195,17 @@ describe('LogRetentionLogic', () => { jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); }); - describe('openModal', () => { + describe('openedModal', () => { it('should be reset to null', () => { mount({ - openModal: ELogRetentionOptions.Analytics, + openedModal: ELogRetentionOptions.Analytics, }); LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, - openModal: null, + openedModal: null, }); }); }); @@ -265,7 +265,7 @@ describe('LogRetentionLogic', () => { }); }); - it('will call setOpenModal if already enabled', () => { + it('will call setOpenedModal if already enabled', () => { mount({ logRetention: { [ELogRetentionOptions.Analytics]: { @@ -273,11 +273,11 @@ describe('LogRetentionLogic', () => { }, }, }); - jest.spyOn(LogRetentionLogic.actions, 'setOpenModal'); + jest.spyOn(LogRetentionLogic.actions, 'setOpenedModal'); LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); - expect(LogRetentionLogic.actions.setOpenModal).toHaveBeenCalledWith( + expect(LogRetentionLogic.actions.setOpenedModal).toHaveBeenCalledWith( ELogRetentionOptions.Analytics ); }); @@ -306,12 +306,12 @@ describe('LogRetentionLogic', () => { logRetention: {}, }); jest.spyOn(LogRetentionLogic.actions, 'saveLogRetention'); - jest.spyOn(LogRetentionLogic.actions, 'setOpenModal'); + jest.spyOn(LogRetentionLogic.actions, 'setOpenedModal'); LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.API); expect(LogRetentionLogic.actions.saveLogRetention).not.toHaveBeenCalled(); - expect(LogRetentionLogic.actions.setOpenModal).not.toHaveBeenCalled(); + expect(LogRetentionLogic.actions.setOpenedModal).not.toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index b5b83ff313ed1..2b261545e98aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -19,7 +19,7 @@ interface ILogRetentionActions { option: ELogRetentionOptions, enabled: boolean ): { option: ELogRetentionOptions; enabled: boolean }; - setOpenModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; + setOpenedModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; toggleLogRetention(option: ELogRetentionOptions): { option: ELogRetentionOptions }; updateLogRetention(logRetention: ILogRetention): { logRetention: ILogRetention }; } @@ -27,7 +27,7 @@ interface ILogRetentionActions { interface ILogRetentionValues { logRetention: ILogRetention | null; logsRetentionUpdating: boolean; - openModal: ELogRetentionOptions | null; + openedModal: ELogRetentionOptions | null; } export const LogRetentionLogic = kea>({ @@ -37,7 +37,7 @@ export const LogRetentionLogic = kea ({ enabled, option }), - setOpenModal: (option) => ({ option }), + setOpenedModal: (option) => ({ option }), toggleLogRetention: (option) => ({ option }), updateLogRetention: (logRetention) => ({ logRetention }), }), @@ -68,12 +68,12 @@ export const LogRetentionLogic = kea true, }, ], - openModal: [ + openedModal: [ null, { closeModals: () => null, saveLogRetention: () => null, - setOpenModal: (_, { option }) => option, + setOpenedModal: (_, { option }) => option, }, ], }), @@ -119,7 +119,7 @@ export const LogRetentionLogic = kea Date: Wed, 4 Nov 2020 09:18:23 -0500 Subject: [PATCH 12/14] Rename logsRetentionUpdating --- .../log_retention/log_retention_logic.test.ts | 34 +++++++++---------- .../log_retention/log_retention_logic.ts | 4 +-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 9659634ecacb2..e7c07298ca631 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -50,7 +50,7 @@ describe('LogRetentionLogic', () => { const DEFAULT_VALUES = { logRetention: null, openedModal: null, - logsRetentionUpdating: false, + isLogRetentionUpdating: false, }; const mount = (defaults?: object) => { @@ -113,34 +113,34 @@ describe('LogRetentionLogic', () => { }); }); - describe('logsRetentionUpdating', () => { - it('resets logsRetentionUpdating to false', () => { + describe('isLogRetentionUpdating', () => { + it('resets isLogRetentionUpdating to false', () => { mount({ - logsRetentionUpdating: true, + isLogRetentionUpdating: true, }); LogRetentionLogic.actions.closeModals(); expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, - logsRetentionUpdating: false, + isLogRetentionUpdating: false, }); }); }); }); describe('clearLogRetentionUpdating', () => { - describe('logsRetentionUpdating', () => { - it('resets logsRetentionUpdating to false', () => { + describe('isLogRetentionUpdating', () => { + it('resets isLogRetentionUpdating to false', () => { mount({ - logsRetentionUpdating: true, + isLogRetentionUpdating: true, }); LogRetentionLogic.actions.clearLogRetentionUpdating(); expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, - logsRetentionUpdating: false, + isLogRetentionUpdating: false, }); }); }); @@ -250,17 +250,17 @@ describe('LogRetentionLogic', () => { }); describe('toggleLogRetention', () => { - describe('logsRetentionUpdating', () => { - it('sets logsRetentionUpdating to true', () => { + describe('isLogRetentionUpdating', () => { + it('sets isLogRetentionUpdating to true', () => { mount({ - logsRetentionUpdating: false, + isLogRetentionUpdating: false, }); LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, - logsRetentionUpdating: true, + isLogRetentionUpdating: true, }); }); }); @@ -316,17 +316,17 @@ describe('LogRetentionLogic', () => { }); describe('fetchLogRetention', () => { - describe('logsRetentionUpdating', () => { - it('sets logsRetentionUpdating to true', () => { + describe('isLogRetentionUpdating', () => { + it('sets isLogRetentionUpdating to true', () => { mount({ - logsRetentionUpdating: false, + isLogRetentionUpdating: false, }); LogRetentionLogic.actions.fetchLogRetention(); expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, - logsRetentionUpdating: true, + isLogRetentionUpdating: true, }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index 2b261545e98aa..e2553fbd47e18 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -26,7 +26,7 @@ interface ILogRetentionActions { interface ILogRetentionValues { logRetention: ILogRetention | null; - logsRetentionUpdating: boolean; + isLogRetentionUpdating: boolean; openedModal: ELogRetentionOptions | null; } @@ -59,7 +59,7 @@ export const LogRetentionLogic = kea false, From 170d2c2680adf5a41cc167a68a428ed86dbfc3d1 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Thu, 5 Nov 2020 10:47:15 -0500 Subject: [PATCH 13/14] Moved test to actions block --- .../log_retention/log_retention_logic.test.ts | 108 +++++++++--------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index e7c07298ca631..198becab19b49 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -283,6 +283,61 @@ describe('LogRetentionLogic', () => { }); }); + describe('fetchLogRetention', () => { + describe('isLogRetentionUpdating', () => { + it('sets isLogRetentionUpdating to true', () => { + mount({ + isLogRetentionUpdating: false, + }); + + LogRetentionLogic.actions.fetchLogRetention(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + isLogRetentionUpdating: true, + }); + }); + }); + + it('will call an API endpoint and update log retention', async () => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + jest + .spyOn(LogRetentionLogic.actions, 'updateLogRetention') + .mockImplementationOnce(() => {}); + + const promise = Promise.resolve(TYPICAL_SERVER_LOG_RETENTION); + http.get.mockReturnValue(promise); + + LogRetentionLogic.actions.fetchLogRetention(); + + expect(http.get).toHaveBeenCalledWith('/api/app_search/log_settings'); + await promise; + expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( + TYPICAL_CLIENT_LOG_RETENTION + ); + + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + + it('handles errors', async () => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + const promise = Promise.reject('An error occured'); + http.get.mockReturnValue(promise); + + LogRetentionLogic.actions.fetchLogRetention(); + + try { + await promise; + } catch { + // Do nothing + } + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + }); + it('will call saveLogRetention if NOT already enabled', () => { mount({ logRetention: { @@ -314,57 +369,4 @@ describe('LogRetentionLogic', () => { expect(LogRetentionLogic.actions.setOpenedModal).not.toHaveBeenCalled(); }); }); - - describe('fetchLogRetention', () => { - describe('isLogRetentionUpdating', () => { - it('sets isLogRetentionUpdating to true', () => { - mount({ - isLogRetentionUpdating: false, - }); - - LogRetentionLogic.actions.fetchLogRetention(); - - expect(LogRetentionLogic.values).toEqual({ - ...DEFAULT_VALUES, - isLogRetentionUpdating: true, - }); - }); - }); - - it('will call an API endpoint and update log retention', async () => { - mount(); - jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); - jest.spyOn(LogRetentionLogic.actions, 'updateLogRetention').mockImplementationOnce(() => {}); - - const promise = Promise.resolve(TYPICAL_SERVER_LOG_RETENTION); - http.get.mockReturnValue(promise); - - LogRetentionLogic.actions.fetchLogRetention(); - - expect(http.get).toHaveBeenCalledWith('/api/app_search/log_settings'); - await promise; - expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( - TYPICAL_CLIENT_LOG_RETENTION - ); - - expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); - }); - - it('handles errors', async () => { - mount(); - jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); - const promise = Promise.reject('An error occured'); - http.get.mockReturnValue(promise); - - LogRetentionLogic.actions.fetchLogRetention(); - - try { - await promise; - } catch { - // Do nothing - } - expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); - expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); - }); - }); }); From 9788589ad094396bce0ce83870c0165b4c7d6293 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Thu, 5 Nov 2020 11:13:45 -0500 Subject: [PATCH 14/14] Update ILogRetention This is always complete. When it's returned from the server, it is fully formed, with all options available. We don't need to make the properties optional. --- .../log_retention/log_retention_logic.test.ts | 42 +++++++++---------- .../log_retention/log_retention_logic.ts | 13 +----- .../settings/log_retention/types.ts | 4 +- 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index 198becab19b49..367c7b085123f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -148,41 +148,37 @@ describe('LogRetentionLogic', () => { describe('updateLogRetention', () => { describe('logRetention', () => { - it('updates the logRetention values that are passed, and defaults the others that are not set', () => { + it('updates the logRetention values that are passed', () => { mount({ logRetention: {}, }); LogRetentionLogic.actions.updateLogRetention({ - api: { enabled: true }, - }); - - expect(LogRetentionLogic.values).toEqual({ - ...DEFAULT_VALUES, - logRetention: { - api: { enabled: true }, - analytics: {}, // This is defaulted to {} + api: { + disabledAt: null, + enabled: true, + retentionPolicy: null, }, - }); - }); - - it('updates the logRetention values that are passed, and retains that values that are already set', () => { - mount({ - logRetention: { - api: { enabled: true }, - analytics: { enabled: true }, + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: null, }, }); - LogRetentionLogic.actions.updateLogRetention({ - api: { enabled: false }, - }); - expect(LogRetentionLogic.values).toEqual({ ...DEFAULT_VALUES, logRetention: { - api: { enabled: false }, - analytics: { enabled: true }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, }, }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts index e2553fbd47e18..28830f2edb1d9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -45,18 +45,7 @@ export const LogRetentionLogic = kea { - return { - [ELogRetentionOptions.Analytics]: { - ...previousValue?.[ELogRetentionOptions.Analytics], - ...logRetention[ELogRetentionOptions.Analytics], - }, - [ELogRetentionOptions.API]: { - ...previousValue?.[ELogRetentionOptions.API], - ...logRetention[ELogRetentionOptions.API], - }, - }; - }, + updateLogRetention: (_, { logRetention }) => logRetention, }, ], isLogRetentionUpdating: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts index 41745097dbe15..7d4f30f88f38f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts @@ -10,8 +10,8 @@ export enum ELogRetentionOptions { } export interface ILogRetention { - [ELogRetentionOptions.Analytics]?: ILogRetentionSettings; - [ELogRetentionOptions.API]?: ILogRetentionSettings; + [ELogRetentionOptions.Analytics]: ILogRetentionSettings; + [ELogRetentionOptions.API]: ILogRetentionSettings; } export interface ILogRetentionPolicy {