[Cases] Adding new external services field for get connectors API (#149535)

This PR adds a new `externalServices` field for the get connector API.
This is needed to show the "View <incident>" link in the case's action's
menu. I moved all push related fields under a new `push` field as well.
I also ran into some circular references since the API response now
needs the external services type from the cases.ts file and the cases.ts
file imports the connector index.ts so I refactored them.

Example response

```
{
    "4175c370-9cd4-11ed-975e-43fe3caaded6": {
        "name": "Jira",
        "type": ".jira",
        "fields": {
            "issueType": "10001",
            "parent": null,
            "priority": null
        },
        "id": "4175c370-9cd4-11ed-975e-43fe3caaded6",
        "push": {
            "needsToBePushed": false,
            "hasBeenPushed": true,
            "externalService": {
                "pushed_at": "2023-01-25T17:18:47.770Z",
                "pushed_by": {
                    "username": "elastic",
                    "full_name": null,
                    "email": null,
                    "profile_uid": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0"
                },
                "connector_name": "Jira",
                "external_id": "10026",
                "external_title": "TPN-27",
                "external_url": "<url>",
                "connector_id": "4175c370-9cd4-11ed-975e-43fe3caaded6"
            },
            "latestUserActionPushDate": "2023-01-25T17:18:47.819Z",
            "oldestUserActionPushDate": "2023-01-25T17:18:47.819Z"
        }
    }
}
```
This commit is contained in:
Jonathan Buttner 2023-01-26 08:46:20 -05:00 committed by GitHub
parent 063850817b
commit 82afa05699
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 315 additions and 172 deletions

View file

@ -11,7 +11,7 @@ import { NumberFromString } from '../saved_object';
import { UserRT } from '../user';
import { CommentResponseRt } from './comment';
import { CasesStatusResponseRt, CaseStatusRt } from './status';
import { CaseConnectorRt } from '../connectors';
import { CaseConnectorRt } from '../connectors/connector';
import { CaseAssigneesRt } from './assignee';
export const AttachmentTotalsRt = rt.type({

View file

@ -0,0 +1,119 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import * as rt from 'io-ts';
import type { ActionType } from '@kbn/actions-plugin/common';
import type { ActionResult } from '@kbn/actions-plugin/server/types';
import { JiraFieldsRT } from './jira';
import { ResilientFieldsRT } from './resilient';
import { ServiceNowITSMFieldsRT } from './servicenow_itsm';
import { ServiceNowSIRFieldsRT } from './servicenow_sir';
import { SwimlaneFieldsRT } from './swimlane';
export type ActionConnector = ActionResult;
export type ActionTypeConnector = ActionType;
export const ConnectorFieldsRt = rt.union([
JiraFieldsRT,
ResilientFieldsRT,
ServiceNowITSMFieldsRT,
ServiceNowSIRFieldsRT,
rt.null,
]);
export enum ConnectorTypes {
casesWebhook = '.cases-webhook',
jira = '.jira',
none = '.none',
resilient = '.resilient',
serviceNowITSM = '.servicenow',
serviceNowSIR = '.servicenow-sir',
swimlane = '.swimlane',
}
const ConnectorCasesWebhookTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.casesWebhook),
fields: rt.null,
});
const ConnectorJiraTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.jira),
fields: rt.union([JiraFieldsRT, rt.null]),
});
const ConnectorResilientTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.resilient),
fields: rt.union([ResilientFieldsRT, rt.null]),
});
const ConnectorServiceNowITSMTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.serviceNowITSM),
fields: rt.union([ServiceNowITSMFieldsRT, rt.null]),
});
const ConnectorSwimlaneTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.swimlane),
fields: rt.union([SwimlaneFieldsRT, rt.null]),
});
const ConnectorServiceNowSIRTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.serviceNowSIR),
fields: rt.union([ServiceNowSIRFieldsRT, rt.null]),
});
const ConnectorNoneTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.none),
fields: rt.null,
});
export const NONE_CONNECTOR_ID: string = 'none';
export const ConnectorTypeFieldsRt = rt.union([
ConnectorCasesWebhookTypeFieldsRt,
ConnectorJiraTypeFieldsRt,
ConnectorNoneTypeFieldsRt,
ConnectorResilientTypeFieldsRt,
ConnectorServiceNowITSMTypeFieldsRt,
ConnectorServiceNowSIRTypeFieldsRt,
ConnectorSwimlaneTypeFieldsRt,
]);
/**
* This type represents the connector's format when it is encoded within a user action.
*/
export const CaseUserActionConnectorRt = rt.union([
rt.intersection([ConnectorCasesWebhookTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorJiraTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorNoneTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorResilientTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorServiceNowITSMTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorServiceNowSIRTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorSwimlaneTypeFieldsRt, rt.type({ name: rt.string })]),
]);
export const CaseConnectorRt = rt.intersection([
rt.type({
id: rt.string,
}),
CaseUserActionConnectorRt,
]);
export type CaseUserActionConnector = rt.TypeOf<typeof CaseUserActionConnectorRt>;
export type CaseConnector = rt.TypeOf<typeof CaseConnectorRt>;
export type ConnectorTypeFields = rt.TypeOf<typeof ConnectorTypeFieldsRt>;
export type ConnectorCasesWebhookTypeFields = rt.TypeOf<typeof ConnectorCasesWebhookTypeFieldsRt>;
export type ConnectorJiraTypeFields = rt.TypeOf<typeof ConnectorJiraTypeFieldsRt>;
export type ConnectorResilientTypeFields = rt.TypeOf<typeof ConnectorResilientTypeFieldsRt>;
export type ConnectorSwimlaneTypeFields = rt.TypeOf<typeof ConnectorSwimlaneTypeFieldsRt>;
export type ConnectorServiceNowITSMTypeFields = rt.TypeOf<
typeof ConnectorServiceNowITSMTypeFieldsRt
>;
export type ConnectorServiceNowSIRTypeFields = rt.TypeOf<typeof ConnectorServiceNowSIRTypeFieldsRt>;
// we need to change these types back and forth for storing in ES (arrays overwrite, objects merge)
export type ConnectorFields = rt.TypeOf<typeof ConnectorFieldsRt>;

View file

@ -0,0 +1,34 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import * as rt from 'io-ts';
import { CaseConnectorRt } from './connector';
import { CaseExternalServiceBasicRt } from '../cases';
const CaseConnectorPushInfoRt = rt.intersection([
rt.type({
needsToBePushed: rt.boolean,
hasBeenPushed: rt.boolean,
}),
rt.partial({
latestUserActionPushDate: rt.string,
oldestUserActionPushDate: rt.string,
externalService: CaseExternalServiceBasicRt,
}),
]);
export const GetCaseConnectorsResponseRt = rt.record(
rt.string,
rt.intersection([
rt.type({
push: CaseConnectorPushInfoRt,
}),
CaseConnectorRt,
])
);
export type GetCaseConnectorsResponse = rt.TypeOf<typeof GetCaseConnectorsResponseRt>;

View file

@ -5,139 +5,11 @@
* 2.0.
*/
import * as rt from 'io-ts';
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
*/
import type { ActionResult } from '@kbn/actions-plugin/server/types';
import { JiraFieldsRT } from './jira';
import { ResilientFieldsRT } from './resilient';
import { ServiceNowITSMFieldsRT } from './servicenow_itsm';
import { ServiceNowSIRFieldsRT } from './servicenow_sir';
import { SwimlaneFieldsRT } from './swimlane';
export * from './jira';
export * from './servicenow_itsm';
export * from './servicenow_sir';
export * from './resilient';
export * from './mappings';
export * from './swimlane';
export type ActionConnector = ActionResult;
export type ActionTypeConnector = ActionType;
export const ConnectorFieldsRt = rt.union([
JiraFieldsRT,
ResilientFieldsRT,
ServiceNowITSMFieldsRT,
ServiceNowSIRFieldsRT,
rt.null,
]);
export enum ConnectorTypes {
casesWebhook = '.cases-webhook',
jira = '.jira',
none = '.none',
resilient = '.resilient',
serviceNowITSM = '.servicenow',
serviceNowSIR = '.servicenow-sir',
swimlane = '.swimlane',
}
const ConnectorCasesWebhookTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.casesWebhook),
fields: rt.null,
});
const ConnectorJiraTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.jira),
fields: rt.union([JiraFieldsRT, rt.null]),
});
const ConnectorResilientTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.resilient),
fields: rt.union([ResilientFieldsRT, rt.null]),
});
const ConnectorServiceNowITSMTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.serviceNowITSM),
fields: rt.union([ServiceNowITSMFieldsRT, rt.null]),
});
const ConnectorSwimlaneTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.swimlane),
fields: rt.union([SwimlaneFieldsRT, rt.null]),
});
const ConnectorServiceNowSIRTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.serviceNowSIR),
fields: rt.union([ServiceNowSIRFieldsRT, rt.null]),
});
const ConnectorNoneTypeFieldsRt = rt.type({
type: rt.literal(ConnectorTypes.none),
fields: rt.null,
});
export const NONE_CONNECTOR_ID: string = 'none';
export const ConnectorTypeFieldsRt = rt.union([
ConnectorCasesWebhookTypeFieldsRt,
ConnectorJiraTypeFieldsRt,
ConnectorNoneTypeFieldsRt,
ConnectorResilientTypeFieldsRt,
ConnectorServiceNowITSMTypeFieldsRt,
ConnectorServiceNowSIRTypeFieldsRt,
ConnectorSwimlaneTypeFieldsRt,
]);
/**
* This type represents the connector's format when it is encoded within a user action.
*/
export const CaseUserActionConnectorRt = rt.union([
rt.intersection([ConnectorCasesWebhookTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorJiraTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorNoneTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorResilientTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorServiceNowITSMTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorServiceNowSIRTypeFieldsRt, rt.type({ name: rt.string })]),
rt.intersection([ConnectorSwimlaneTypeFieldsRt, rt.type({ name: rt.string })]),
]);
export const CaseConnectorRt = rt.intersection([
rt.type({
id: rt.string,
}),
CaseUserActionConnectorRt,
]);
export const GetCaseConnectorsResponseRt = rt.record(
rt.string,
rt.intersection([
rt.type({ needsToBePushed: rt.boolean, hasBeenPushed: rt.boolean }),
rt.partial(rt.type({ latestPushDate: rt.string, oldestPushDate: rt.string }).props),
CaseConnectorRt,
])
);
export type CaseUserActionConnector = rt.TypeOf<typeof CaseUserActionConnectorRt>;
export type CaseConnector = rt.TypeOf<typeof CaseConnectorRt>;
export type ConnectorTypeFields = rt.TypeOf<typeof ConnectorTypeFieldsRt>;
export type ConnectorCasesWebhookTypeFields = rt.TypeOf<typeof ConnectorCasesWebhookTypeFieldsRt>;
export type ConnectorJiraTypeFields = rt.TypeOf<typeof ConnectorJiraTypeFieldsRt>;
export type ConnectorResilientTypeFields = rt.TypeOf<typeof ConnectorResilientTypeFieldsRt>;
export type ConnectorSwimlaneTypeFields = rt.TypeOf<typeof ConnectorSwimlaneTypeFieldsRt>;
export type ConnectorServiceNowITSMTypeFields = rt.TypeOf<
typeof ConnectorServiceNowITSMTypeFieldsRt
>;
export type ConnectorServiceNowSIRTypeFields = rt.TypeOf<typeof ConnectorServiceNowSIRTypeFieldsRt>;
// we need to change these types back and forth for storing in ES (arrays overwrite, objects merge)
export type ConnectorFields = rt.TypeOf<typeof ConnectorFieldsRt>;
export type GetCaseConnectorsResponse = rt.TypeOf<typeof GetCaseConnectorsResponseRt>;
export * from './get_connectors';
export * from './connector';

View file

@ -14,9 +14,14 @@ import type {
GetCaseConnectorsResponse,
CaseConnector,
CaseUserActionInjectedAttributesWithoutActionId,
CaseExternalServiceBasic,
} from '../../../common/api';
import { GetCaseConnectorsResponseRt } from '../../../common/api';
import { isConnectorUserAction, isCreateCaseUserAction } from '../../../common/utils/user_actions';
import {
isConnectorUserAction,
isCreateCaseUserAction,
isPushedUserAction,
} from '../../../common/utils/user_actions';
import { createCaseError } from '../../common/error';
import type { CasesClientArgs } from '..';
import type { Authorization, OwnerEntity } from '../../authorization';
@ -106,6 +111,7 @@ const checkConnectorsAuthorization = async ({
interface EnrichedPushInfo {
latestPushDate: Date;
oldestPushDate: Date;
externalService: CaseExternalServiceBasic;
connectorFieldsUsedInPush: CaseConnector;
}
@ -125,20 +131,21 @@ const getConnectorsInfo = async ({
const connectorIds = connectors.map((connector) => connector.connectorId);
const [pushInfo, actionConnectors] = await Promise.all([
getPushInfo({ caseId, activity: connectors, userActionService }),
getEnrichedPushInfo({ caseId, activity: connectors, userActionService }),
actionsClient.getBulk(connectorIds),
]);
return createConnectorInfoResult({ actionConnectors, connectors, pushInfo, latestUserAction });
};
interface PushTimeFrameDetails {
interface PushDetails {
connectorId: string;
externalService: CaseExternalServiceBasic;
mostRecentPush: Date;
oldestPush: Date;
}
const getPushInfo = async ({
const getEnrichedPushInfo = async ({
caseId,
activity,
userActionService,
@ -147,24 +154,7 @@ const getPushInfo = async ({
activity: CaseConnectorActivity[];
userActionService: CaseUserActionService;
}): Promise<Map<string, EnrichedPushInfo>> => {
const pushDetails: PushTimeFrameDetails[] = [];
for (const connectorInfo of activity) {
const mostRecentPushCreatedAt = getDate(connectorInfo.push?.mostRecent.attributes.created_at);
const oldestPushCreatedAt = getDate(connectorInfo.push?.oldest.attributes.created_at);
if (
connectorInfo.push != null &&
mostRecentPushCreatedAt != null &&
oldestPushCreatedAt != null
) {
pushDetails.push({
connectorId: connectorInfo.connectorId,
mostRecentPush: mostRecentPushCreatedAt,
oldestPush: oldestPushCreatedAt,
});
}
}
const pushDetails = getPushDetails(activity);
const connectorFieldsForPushes = await userActionService.getConnectorFieldsBeforeLatestPush(
caseId,
@ -180,6 +170,7 @@ const getPushInfo = async ({
enrichedPushInfo.set(pushInfo.connectorId, {
latestPushDate: pushInfo.mostRecentPush,
oldestPushDate: pushInfo.oldestPush,
externalService: pushInfo.externalService,
connectorFieldsUsedInPush: connectorFields,
});
}
@ -188,6 +179,40 @@ const getPushInfo = async ({
return enrichedPushInfo;
};
const getPushDetails = (activity: CaseConnectorActivity[]) => {
const pushDetails: PushDetails[] = [];
for (const connectorInfo of activity) {
const externalService = getExternalServiceFromSavedObject(connectorInfo.push?.mostRecent);
const mostRecentPushCreatedAt = getDate(connectorInfo.push?.mostRecent.attributes.created_at);
const oldestPushCreatedAt = getDate(connectorInfo.push?.oldest.attributes.created_at);
if (
connectorInfo.push != null &&
externalService != null &&
mostRecentPushCreatedAt != null &&
oldestPushCreatedAt != null
) {
pushDetails.push({
connectorId: connectorInfo.connectorId,
externalService,
mostRecentPush: mostRecentPushCreatedAt,
oldestPush: oldestPushCreatedAt,
});
}
}
return pushDetails;
};
const getExternalServiceFromSavedObject = (
savedObject: SavedObject<CaseUserActionInjectedAttributesWithoutActionId> | undefined
): CaseExternalServiceBasic | undefined => {
if (savedObject != null && isPushedUserAction(savedObject.attributes)) {
return savedObject.attributes.payload.externalService;
}
};
const getDate = (timestamp: string | undefined): Date | undefined => {
if (timestamp == null) {
return;
@ -247,10 +272,13 @@ const createConnectorInfoResult = ({
results[connector.id] = {
...connector,
name: connectorDetails.name,
needsToBePushed,
latestPushDate: enrichedPushInfo?.latestPushDate.toISOString(),
oldestPushDate: enrichedPushInfo?.oldestPushDate.toISOString(),
hasBeenPushed: hasBeenPushed(enrichedPushInfo),
push: {
needsToBePushed,
hasBeenPushed: hasBeenPushed(enrichedPushInfo),
externalService: enrichedPushInfo?.externalService,
latestUserActionPushDate: enrichedPushInfo?.latestPushDate.toISOString(),
oldestUserActionPushDate: enrichedPushInfo?.oldestPushDate.toISOString(),
},
};
}
}

View file

@ -145,7 +145,7 @@ export default ({ getService }: FtrProviderContext): void => {
urgency: '2',
});
expect(snConnector.needsToBePushed).to.be(false);
expect(snConnector.push.needsToBePushed).to.be(false);
expect(snConnector.name).to.be('ServiceNow Connector');
expect(snConnector.id).to.be(connector.id);
});
@ -232,6 +232,92 @@ export default ({ getService }: FtrProviderContext): void => {
});
describe('push', () => {
describe('externalService', () => {
it('sets externalService field to the most recent push info', async () => {
const { postedCase, connector } = await createCaseWithConnector({
supertest,
serviceNowSimulatorURL,
actionsRemover,
});
await pushCase({
supertest,
caseId: postedCase.id,
connectorId: connector.id,
});
const pachedCase = await createComment({
supertest,
caseId: postedCase.id,
params: postCommentUserReq,
});
const serviceNow2 = await createConnector({
supertest,
req: {
...getServiceNowConnector(),
name: 'ServiceNow 2 Connector',
config: { apiUrl: serviceNowSimulatorURL },
},
});
actionsRemover.add('default', serviceNow2.id, 'action', 'actions');
// change to serviceNow2 connector
await updateCase({
supertest,
params: {
cases: [
{
id: pachedCase.id,
version: pachedCase.version,
connector: {
id: serviceNow2.id,
name: 'ServiceNow 2 Connector',
type: ConnectorTypes.serviceNowITSM,
fields: {
urgency: '2',
impact: '2',
severity: '2',
category: 'software',
subcategory: 'os',
},
},
},
],
},
});
await pushCase({
supertest,
caseId: pachedCase.id,
connectorId: serviceNow2.id,
});
const [userActions, connectors] = await Promise.all([
getCaseUserActions({ supertest, caseID: postedCase.id }),
getConnectors({ caseId: postedCase.id, supertest }),
]);
const pushes = userActions.filter((ua) => ua.type === ActionTypes.pushed);
const latestPush = pushes[pushes.length - 1];
expect(Object.keys(connectors).length).to.be(2);
expect(connectors[serviceNow2.id].push.latestUserActionPushDate).to.eql(
latestPush.created_at
);
expect(connectors[serviceNow2.id].push.externalService?.connector_id).to.eql(
serviceNow2.id
);
expect(connectors[serviceNow2.id].push.externalService?.connector_name).to.eql(
serviceNow2.name
);
expect(connectors[serviceNow2.id].push.externalService?.connector_name).to.not.eql(
connector.name
);
});
});
describe('latestPushDate', () => {
it('does not set latestPushDate or oldestPushDate when the connector has not been used to push', async () => {
const { postedCase, connector } = await createCaseWithConnector({
@ -244,8 +330,8 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(1);
expect(connectors).to.have.property(connector.id);
expect(connectors[connector.id].latestPushDate).to.be(undefined);
expect(connectors[connector.id].oldestPushDate).to.be(undefined);
expect(connectors[connector.id].push.latestUserActionPushDate).to.be(undefined);
expect(connectors[connector.id].push.oldestUserActionPushDate).to.be(undefined);
});
it('sets latestPushDate to the most recent push date and oldestPushDate to the first push date', async () => {
@ -283,8 +369,12 @@ export default ({ getService }: FtrProviderContext): void => {
const latestPush = pushes[pushes.length - 1];
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[connector.id].latestPushDate).to.eql(latestPush.created_at);
expect(connectors[connector.id].oldestPushDate).to.eql(oldestPush.created_at);
expect(connectors[connector.id].push.latestUserActionPushDate).to.eql(
latestPush.created_at
);
expect(connectors[connector.id].push.oldestUserActionPushDate).to.eql(
oldestPush.created_at
);
});
});
@ -299,7 +389,7 @@ export default ({ getService }: FtrProviderContext): void => {
const connectors = await getConnectors({ caseId: postedCase.id, supertest });
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[connector.id].hasBeenPushed).to.be(false);
expect(connectors[connector.id].push.hasBeenPushed).to.be(false);
});
it('sets hasBeenPushed to true when the connector was used to push', async () => {
@ -318,7 +408,7 @@ export default ({ getService }: FtrProviderContext): void => {
const connectors = await getConnectors({ caseId: postedCase.id, supertest });
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[connector.id].hasBeenPushed).to.be(true);
expect(connectors[connector.id].push.hasBeenPushed).to.be(true);
});
});
@ -334,7 +424,7 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[connector.id].id).to.be(connector.id);
expect(connectors[connector.id].needsToBePushed).to.be(true);
expect(connectors[connector.id].push.needsToBePushed).to.be(true);
});
it('sets needs to push to false when a push has occurred', async () => {
@ -354,7 +444,7 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[connector.id].id).to.be(connector.id);
expect(connectors[connector.id].needsToBePushed).to.be(false);
expect(connectors[connector.id].push.needsToBePushed).to.be(false);
});
it('sets needs to push to true when a comment was created after the last push', async () => {
@ -380,7 +470,7 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[connector.id].id).to.be(connector.id);
expect(connectors[connector.id].needsToBePushed).to.be(true);
expect(connectors[connector.id].push.needsToBePushed).to.be(true);
});
it('sets needs to push to false when the severity of a case was changed after the last push', async () => {
@ -413,7 +503,7 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[connector.id].id).to.be(connector.id);
expect(connectors[connector.id].needsToBePushed).to.be(false);
expect(connectors[connector.id].push.needsToBePushed).to.be(false);
});
it('sets needs to push to false the service now connector and true for jira', async () => {
@ -461,9 +551,9 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(2);
expect(connectors[serviceNowConnector.id].id).to.be(serviceNowConnector.id);
expect(connectors[serviceNowConnector.id].needsToBePushed).to.be(false);
expect(connectors[serviceNowConnector.id].push.needsToBePushed).to.be(false);
expect(connectors[jiraConnector.id].id).to.be(jiraConnector.id);
expect(connectors[jiraConnector.id].needsToBePushed).to.be(true);
expect(connectors[jiraConnector.id].push.needsToBePushed).to.be(true);
});
describe('changing connector fields', () => {
@ -564,7 +654,7 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[serviceNowConnector.id].id).to.be(serviceNowConnector.id);
expect(connectors[serviceNowConnector.id].needsToBePushed).to.be(false);
expect(connectors[serviceNowConnector.id].push.needsToBePushed).to.be(false);
});
it('sets needs to push to true when the latest connector fields do not match those used in the push', async () => {
@ -609,7 +699,7 @@ export default ({ getService }: FtrProviderContext): void => {
expect(Object.keys(connectors).length).to.be(1);
expect(connectors[serviceNowConnector.id].id).to.be(serviceNowConnector.id);
expect(connectors[serviceNowConnector.id].needsToBePushed).to.be(true);
expect(connectors[serviceNowConnector.id].push.needsToBePushed).to.be(true);
});
});
});