Skip to content

Commit

Permalink
[Cases] Show deprecated icon in connectors with isDeprecated true (el…
Browse files Browse the repository at this point in the history
…astic#132237)

Co-authored-by: Christos Nasikas <[email protected]>
  • Loading branch information
academo and cnasikas authored May 20, 2022
1 parent f88b140 commit 473141f
Show file tree
Hide file tree
Showing 25 changed files with 285 additions and 178 deletions.
25 changes: 25 additions & 0 deletions x-pack/plugins/actions/server/lib/is_conector_deprecated.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ describe('isConnectorDeprecated', () => {
isPreconfigured: false as const,
};

it('returns false if the config is not defined', () => {
// @ts-expect-error
expect(isConnectorDeprecated({})).toBe(false);
});

it('returns false if the connector is not ITSM or SecOps', () => {
expect(isConnectorDeprecated(connector)).toBe(false);
});
Expand Down Expand Up @@ -48,4 +53,24 @@ describe('isConnectorDeprecated', () => {
})
).toBe(true);
});

it('returns true if the connector is .servicenow and the usesTableApi is omitted', () => {
expect(
isConnectorDeprecated({
...connector,
actionTypeId: '.servicenow',
config: { apiUrl: 'http://example.com' },
})
).toBe(true);
});

it('returns true if the connector is .servicenow-sir and the usesTableApi is omitted', () => {
expect(
isConnectorDeprecated({
...connector,
actionTypeId: '.servicenow-sir',
config: { apiUrl: 'http://example.com' },
})
).toBe(true);
});
});
40 changes: 36 additions & 4 deletions x-pack/plugins/actions/server/lib/is_conector_deprecated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
* 2.0.
*/

import { isPlainObject } from 'lodash';
import { PreConfiguredAction, RawAction } from '../types';

export type ConnectorWithOptionalDeprecation = Omit<PreConfiguredAction, 'isDeprecated'> &
Pick<Partial<PreConfiguredAction>, 'isDeprecated'>;

const isObject = (obj: unknown): obj is Record<string, unknown> => isPlainObject(obj);

export const isConnectorDeprecated = (
connector: RawAction | ConnectorWithOptionalDeprecation
): boolean => {
Expand All @@ -18,11 +21,40 @@ export const isConnectorDeprecated = (
* Connectors after the Elastic ServiceNow application use the
* Import Set API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_ImportSetAPI)
* A ServiceNow connector is considered deprecated if it uses the Table API.
*
* All other connectors do not have the usesTableApi config property
* so the function will always return false for them.
*/
return !!connector.config?.usesTableApi;

/**
* We cannot deduct if the connector is
* deprecated without config. In this case
* we always return false.
*/
if (!isObject(connector.config)) {
return false;
}

/**
* If the usesTableApi is not defined it means that the connector is created
* before the introduction of the usesTableApi property. In that case, the connector is assumed
* to be deprecated because all connectors prior 7.16 where using the Table API.
* Migrations x-pack/plugins/actions/server/saved_objects/actions_migrations.ts set
* the usesTableApi property to true to all connectors prior 7.16. Pre configured connectors
* cannot be migrated. This check ensures that pre configured connectors without the
* usesTableApi property explicitly in the kibana.yml file are considered deprecated.
* According to the schema defined here x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts
* if the property is not defined it will be set to true at the execution of the connector.
*/
if (!Object.hasOwn(connector.config, 'usesTableApi')) {
return true;
}

/**
* Connector created prior to 7.16 will be migrated to have the usesTableApi property set to true.
* Connectors created after 7.16 should have the usesTableApi property set to true or false.
* If the usesTableApi is omitted on an API call it will be defaulted to true. Check the schema
* here x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts.
* The !! is to make TS happy.
*/
return !!connector.config.usesTableApi;
}

return false;
Expand Down
10 changes: 9 additions & 1 deletion x-pack/plugins/cases/common/api/connectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@

import * as rt from 'io-ts';

import { ActionResult, ActionType } from '@kbn/actions-plugin/common';
import type { ActionType } from '@kbn/actions-plugin/common';
/**
* ActionResult type from the common folder is outdated.
* The type from server is not exported properly so we
* disable the linting for the moment
*/

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import type { ActionResult } from '@kbn/actions-plugin/server/types';
import { JiraFieldsRT } from './jira';
import { ResilientFieldsRT } from './resilient';
import { ServiceNowITSMFieldsRT } from './servicenow_itsm';
Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/cases/public/common/mock/connectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const connectorsMock: ActionConnector[] = [
apiUrl: 'https://instance1.service-now.com',
},
isPreconfigured: false,
isDeprecated: false,
},
{
id: 'resilient-2',
Expand All @@ -26,6 +27,7 @@ export const connectorsMock: ActionConnector[] = [
orgId: '201',
},
isPreconfigured: false,
isDeprecated: false,
},
{
id: 'jira-1',
Expand All @@ -35,6 +37,7 @@ export const connectorsMock: ActionConnector[] = [
apiUrl: 'https://instance.atlassian.ne',
},
isPreconfigured: false,
isDeprecated: false,
},
{
id: 'servicenow-sir',
Expand All @@ -44,6 +47,7 @@ export const connectorsMock: ActionConnector[] = [
apiUrl: 'https://instance1.service-now.com',
},
isPreconfigured: false,
isDeprecated: false,
},
{
id: 'servicenow-uses-table-api',
Expand All @@ -54,6 +58,7 @@ export const connectorsMock: ActionConnector[] = [
usesTableApi: true,
},
isPreconfigured: false,
isDeprecated: true,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ describe('ExternalServiceColumn ', () => {
name: 'None',
config: {},
isPreconfigured: false,
isDeprecated: false,
},
]}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ describe('ConnectorsDropdown', () => {
name: 'None',
config: {},
isPreconfigured: false,
isDeprecated: false,
},
]}
/>,
Expand All @@ -269,4 +270,26 @@ describe('ConnectorsDropdown', () => {
);
expect(tooltips[0]).toBeInTheDocument();
});

test('it shows the deprecated tooltip when the connector is deprecated by configuration', () => {
const connector = connectors[0];
render(
<ConnectorsDropdown
{...props}
connectors={[
{
...connector,
isDeprecated: true,
},
]}
selectedConnector={connector.id}
/>,
{ wrapper: ({ children }) => <TestProviders>{children}</TestProviders> }
);

const tooltips = screen.getAllByText(
'This connector is deprecated. Update it, or create a new one.'
);
expect(tooltips[0]).toBeInTheDocument();
});
});
2 changes: 2 additions & 0 deletions x-pack/plugins/cases/public/components/connectors/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const connector = {
actionTypeId: '.jira',
config: {},
isPreconfigured: false,
isDeprecated: false,
};

export const swimlaneConnector = {
Expand All @@ -29,6 +30,7 @@ export const swimlaneConnector = {
},
},
isPreconfigured: false,
isDeprecated: false,
};

export const issues = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,18 @@ describe('ServiceNowITSM Fields', () => {
);
});

it('shows the deprecated callout when the connector uses the table API', async () => {
const tableApiConnector = { ...connector, config: { usesTableApi: true } };
it('shows the deprecated callout if the connector is deprecated', async () => {
const tableApiConnector = { ...connector, isDeprecated: true };
render(<Fields fields={fields} onChange={onChange} connector={tableApiConnector} />);
expect(screen.getByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
});

it('does not show the deprecated callout when the connector does not uses the table API', async () => {
it('does not show the deprecated callout when the connector is not deprecated', async () => {
render(<Fields fields={fields} onChange={onChange} connector={connector} />);
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
});

it('does not show the deprecated callout when the connector is preconfigured', async () => {
it('does not show the deprecated callout when the connector is preconfigured and not deprecated', async () => {
render(
<Fields
fields={fields}
Expand All @@ -157,12 +157,15 @@ describe('ServiceNowITSM Fields', () => {
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
});

it('does not show the deprecated callout when the config of the connector is undefined', async () => {
it('shows the deprecated callout when the connector is preconfigured and deprecated', async () => {
render(
// @ts-expect-error
<Fields fields={fields} onChange={onChange} connector={{ ...connector, config: undefined }} />
<Fields
fields={fields}
onChange={onChange}
connector={{ ...connector, isPreconfigured: true, isDeprecated: true }}
/>
);
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
expect(screen.queryByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
});

it('should hide subcategory if selecting a category without subcategories', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { ConnectorCard } from '../card';
import { useGetChoices } from './use_get_choices';
import { Fields, Choice } from './types';
import { choicesToEuiOptions } from './helpers';
import { connectorValidator } from './validator';
import { DeprecatedCallout } from '../deprecated_callout';

const useGetChoicesFields = ['urgency', 'severity', 'impact', 'category', 'subcategory'];
Expand Down Expand Up @@ -44,7 +43,7 @@ const ServiceNowITSMFieldsComponent: React.FunctionComponent<
} = fields ?? {};
const { http, notifications } = useKibana().services;
const [choices, setChoices] = useState<Fields>(defaultFields);
const showConnectorWarning = useMemo(() => connectorValidator(connector) != null, [connector]);
const showConnectorWarning = connector.isDeprecated;

const categoryOptions = useMemo(
() => choicesToEuiOptions(choices.category),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,18 @@ describe('ServiceNowSIR Fields', () => {
]);
});

test('it shows the deprecated callout when the connector uses the table API', async () => {
const tableApiConnector = { ...connector, config: { usesTableApi: true } };
test('shows the deprecated callout if the connector is deprecated', async () => {
const tableApiConnector = { ...connector, isDeprecated: true };
render(<Fields fields={fields} onChange={onChange} connector={tableApiConnector} />);
expect(screen.getByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
});

test('it does not show the deprecated callout when the connector does not uses the table API', async () => {
test('does not show the deprecated callout when the connector is not deprecated', async () => {
render(<Fields fields={fields} onChange={onChange} connector={connector} />);
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
});

it('does not show the deprecated callout when the connector is preconfigured', async () => {
it('does not show the deprecated callout when the connector is preconfigured and not deprecated', async () => {
render(
<Fields
fields={fields}
Expand All @@ -191,12 +191,15 @@ describe('ServiceNowSIR Fields', () => {
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
});

it('does not show the deprecated callout when the config of the connector is undefined', async () => {
it('shows the deprecated callout when the connector is preconfigured and deprecated', async () => {
render(
// @ts-expect-error
<Fields fields={fields} onChange={onChange} connector={{ ...connector, config: undefined }} />
<Fields
fields={fields}
onChange={onChange}
connector={{ ...connector, isPreconfigured: true, isDeprecated: true }}
/>
);
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
expect(screen.queryByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
});

test('it should hide subcategory if selecting a category without subcategories', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { Choice, Fields } from './types';
import { choicesToEuiOptions } from './helpers';

import * as i18n from './translations';
import { connectorValidator } from './validator';
import { DeprecatedCallout } from '../deprecated_callout';

const useGetChoicesFields = ['category', 'subcategory', 'priority'];
Expand All @@ -43,7 +42,7 @@ const ServiceNowSIRFieldsComponent: React.FunctionComponent<

const { http, notifications } = useKibana().services;
const [choices, setChoices] = useState<Fields>(defaultFields);
const showConnectorWarning = useMemo(() => connectorValidator(connector) != null, [connector]);
const showConnectorWarning = connector.isDeprecated;

const onChangeCb = useCallback(
(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const connector = {
actionTypeId: '.servicenow',
name: 'ServiceNow',
isPreconfigured: false,
isDeprecated: false,
config: {
apiUrl: 'https://dev94428.service-now.com/',
},
Expand Down

This file was deleted.

Loading

0 comments on commit 473141f

Please sign in to comment.