mirror of
https://github.com/ansible/awx.git
synced 2026-05-07 01:17:37 -02:30
Adds tests for workflow save error handling. Removes unnecessary code that was attempting to remove credentials from a new node.
This commit is contained in:
@@ -64,10 +64,10 @@ const getAggregatedCredentials = (
|
|||||||
templateDefaultCred.credential_type === overrideCred.credential_type
|
templateDefaultCred.credential_type === overrideCred.credential_type
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
(!templateDefaultCred.vault_id && !overrideCred.inputs.vault_id) ||
|
(!templateDefaultCred.vault_id && !overrideCred.inputs?.vault_id) ||
|
||||||
(templateDefaultCred.vault_id &&
|
(templateDefaultCred.vault_id &&
|
||||||
overrideCred.inputs.vault_id &&
|
overrideCred.inputs?.vault_id &&
|
||||||
templateDefaultCred.vault_id === overrideCred.inputs.vault_id)
|
templateDefaultCred.vault_id === overrideCred.inputs?.vault_id)
|
||||||
) {
|
) {
|
||||||
credentialHasOverride = true;
|
credentialHasOverride = true;
|
||||||
}
|
}
|
||||||
@@ -405,16 +405,7 @@ function Visualizer({ template, i18n }) {
|
|||||||
failure_nodes: [],
|
failure_nodes: [],
|
||||||
always_nodes: [],
|
always_nodes: [],
|
||||||
};
|
};
|
||||||
if (node.promptValues?.removedCredentials?.length > 0) {
|
|
||||||
node.promptValues.removedCredentials.forEach(cred => {
|
|
||||||
disassociateCredentialRequests.push(
|
|
||||||
WorkflowJobTemplateNodesAPI.disassociateCredentials(
|
|
||||||
data.id,
|
|
||||||
cred.id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (node.promptValues?.addedCredentials?.length > 0) {
|
if (node.promptValues?.addedCredentials?.length > 0) {
|
||||||
node.promptValues.addedCredentials.forEach(cred => {
|
node.promptValues.addedCredentials.forEach(cred => {
|
||||||
associateCredentialRequests.push(
|
associateCredentialRequests.push(
|
||||||
@@ -583,8 +574,9 @@ function Visualizer({ template, i18n }) {
|
|||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen
|
isOpen
|
||||||
variant="error"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error saving the workflow!`)}
|
||||||
onClose={dismissNodeRequestError}
|
onClose={dismissNodeRequestError}
|
||||||
|
aria-label={i18n._(t`Error saving the workflow!`)}
|
||||||
>
|
>
|
||||||
{i18n._(t`There was an error saving the workflow.`)}
|
{i18n._(t`There was an error saving the workflow.`)}
|
||||||
<ErrorDetail error={nodeRequestError} />
|
<ErrorDetail error={nodeRequestError} />
|
||||||
|
|||||||
@@ -2,13 +2,37 @@ import React from 'react';
|
|||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||||
import {
|
import {
|
||||||
|
WorkflowApprovalTemplatesAPI,
|
||||||
WorkflowJobTemplateNodesAPI,
|
WorkflowJobTemplateNodesAPI,
|
||||||
WorkflowJobTemplatesAPI,
|
WorkflowJobTemplatesAPI,
|
||||||
} from '../../../api';
|
} from '../../../api';
|
||||||
import Visualizer from './Visualizer';
|
import Visualizer from './Visualizer';
|
||||||
|
|
||||||
|
import workflowReducer from '../../../components/Workflow/workflowReducer';
|
||||||
|
|
||||||
|
jest.mock('../../../components/Workflow/workflowReducer');
|
||||||
|
|
||||||
|
const realWorkflowReducer = jest.requireActual(
|
||||||
|
'../../../components/Workflow/workflowReducer'
|
||||||
|
).default;
|
||||||
|
|
||||||
jest.mock('../../../api');
|
jest.mock('../../../api');
|
||||||
|
|
||||||
|
const startNode = {
|
||||||
|
id: 1,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
name: 'START',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultLinks = [
|
||||||
|
{
|
||||||
|
linkType: 'always',
|
||||||
|
source: { id: 1 },
|
||||||
|
target: { id: 2 },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const template = {
|
const template = {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Foo WFJT',
|
name: 'Foo WFJT',
|
||||||
@@ -117,7 +141,6 @@ describe('Visualizer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
jest.clearAllMocks();
|
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
delete window.SVGElement.prototype.getBBox;
|
delete window.SVGElement.prototype.getBBox;
|
||||||
delete window.SVGElement.prototype.getBoundingClientRect;
|
delete window.SVGElement.prototype.getBoundingClientRect;
|
||||||
@@ -125,6 +148,12 @@ describe('Visualizer', () => {
|
|||||||
delete window.SVGElement.prototype.width;
|
delete window.SVGElement.prototype.width;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
jest.resetModules();
|
||||||
|
workflowReducer.mockImplementation(realWorkflowReducer);
|
||||||
|
});
|
||||||
|
|
||||||
test('Renders successfully', async () => {
|
test('Renders successfully', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
@@ -185,7 +214,7 @@ describe('Visualizer', () => {
|
|||||||
wrapper.find('button#link-confirm').simulate('click');
|
wrapper.find('button#link-confirm').simulate('click');
|
||||||
expect(wrapper.find('LinkEditModal').length).toBe(0);
|
expect(wrapper.find('LinkEditModal').length).toBe(0);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('button[aria-label="Save"]').simulate('click');
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
WorkflowJobTemplateNodesAPI.disassociateAlwaysNode
|
WorkflowJobTemplateNodesAPI.disassociateAlwaysNode
|
||||||
@@ -219,6 +248,633 @@ describe('Visualizer', () => {
|
|||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to node add error', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'PING',
|
||||||
|
type: 'job_template',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = defaultLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.createNode.mockRejectedValue(new Error());
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(WorkflowJobTemplatesAPI.createNode).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to node edit error', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
isEdited: true,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'PING',
|
||||||
|
type: 'job_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = defaultLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplateNodesAPI.replace.mockRejectedValue(new Error());
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(WorkflowJobTemplateNodesAPI.replace).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to approval template add error', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'Approval',
|
||||||
|
timeout: 1000,
|
||||||
|
type: 'workflow_approval_template',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = defaultLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.createNode.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
id: 9001,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplateNodesAPI.createApprovalTemplate.mockRejectedValue(
|
||||||
|
new Error()
|
||||||
|
);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(WorkflowJobTemplatesAPI.createNode).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
WorkflowJobTemplateNodesAPI.createApprovalTemplate
|
||||||
|
).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to approval template edit error', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
isEdited: true,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'Approval',
|
||||||
|
timeout: 1000,
|
||||||
|
type: 'workflow_approval_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9000,
|
||||||
|
summary_fields: {
|
||||||
|
unified_job_template: {
|
||||||
|
unified_job_type: 'workflow_approval',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = defaultLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowApprovalTemplatesAPI.update.mockRejectedValue(new Error());
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(WorkflowApprovalTemplatesAPI.update).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to node disassociate failure', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'Approval',
|
||||||
|
timeout: 1000,
|
||||||
|
type: 'workflow_approval_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9000,
|
||||||
|
summary_fields: {
|
||||||
|
unified_job_template: {
|
||||||
|
unified_job_type: 'workflow_approval',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [3],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
success_nodes: [3],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 4,
|
||||||
|
name: 'Approval 2',
|
||||||
|
timeout: 1000,
|
||||||
|
type: 'workflow_approval_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9001,
|
||||||
|
summary_fields: {
|
||||||
|
unified_job_template: {
|
||||||
|
unified_job_type: 'workflow_approval',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = [
|
||||||
|
{
|
||||||
|
linkType: 'always',
|
||||||
|
source: { id: 1 },
|
||||||
|
target: { id: 2 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
linkType: 'success',
|
||||||
|
source: { id: 2 },
|
||||||
|
target: { id: 3 },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplateNodesAPI.disassociateFailuresNode.mockRejectedValue(
|
||||||
|
new Error()
|
||||||
|
);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
WorkflowJobTemplateNodesAPI.disassociateFailuresNode
|
||||||
|
).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to node associate failure', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'Approval',
|
||||||
|
timeout: 1000,
|
||||||
|
type: 'workflow_approval_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9000,
|
||||||
|
summary_fields: {
|
||||||
|
unified_job_template: {
|
||||||
|
unified_job_type: 'workflow_approval',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [3],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
success_nodes: [3],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 4,
|
||||||
|
name: 'Approval 2',
|
||||||
|
timeout: 1000,
|
||||||
|
type: 'workflow_approval_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9001,
|
||||||
|
summary_fields: {
|
||||||
|
unified_job_template: {
|
||||||
|
unified_job_type: 'workflow_approval',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = [
|
||||||
|
{
|
||||||
|
linkType: 'always',
|
||||||
|
source: { id: 1 },
|
||||||
|
target: { id: 2 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
linkType: 'success',
|
||||||
|
source: { id: 2 },
|
||||||
|
target: { id: 3 },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplateNodesAPI.disassociateFailuresNode.mockResolvedValue();
|
||||||
|
WorkflowJobTemplateNodesAPI.associateSuccessNode.mockRejectedValue(
|
||||||
|
new Error()
|
||||||
|
);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
WorkflowJobTemplateNodesAPI.associateSuccessNode
|
||||||
|
).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to credential disassociate failure', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
isEdited: true,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'Ping',
|
||||||
|
type: 'job_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9000,
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
originalNodeCredentials: [
|
||||||
|
{
|
||||||
|
id: 456,
|
||||||
|
credential_type: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
promptValues: {
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
id: 123,
|
||||||
|
credential_type: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
launchConfig: {
|
||||||
|
defaults: {
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
id: 456,
|
||||||
|
credential_type: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = defaultLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplateNodesAPI.replace.mockResolvedValue();
|
||||||
|
WorkflowJobTemplateNodesAPI.disassociateCredentials.mockRejectedValue(
|
||||||
|
new Error()
|
||||||
|
);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
WorkflowJobTemplateNodesAPI.disassociateCredentials
|
||||||
|
).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Error shown when saving fails due to credential associate failure', async () => {
|
||||||
|
workflowReducer.mockImplementation(state => {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
isLoading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newState.nodes.length === 0) {
|
||||||
|
newState.nodes = [
|
||||||
|
startNode,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
isEdited: true,
|
||||||
|
fullUnifiedJobTemplate: {
|
||||||
|
id: 3,
|
||||||
|
name: 'Ping',
|
||||||
|
type: 'job_template',
|
||||||
|
},
|
||||||
|
originalNodeObject: {
|
||||||
|
id: 9000,
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
originalNodeCredentials: [
|
||||||
|
{
|
||||||
|
id: 456,
|
||||||
|
credential_type: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
promptValues: {
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
id: 123,
|
||||||
|
credential_type: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
launchConfig: {
|
||||||
|
defaults: {
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
id: 456,
|
||||||
|
credential_type: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success_nodes: [],
|
||||||
|
failure_nodes: [],
|
||||||
|
always_nodes: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
newState.links = defaultLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
WorkflowJobTemplatesAPI.readNodes.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
count: 0,
|
||||||
|
results: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WorkflowJobTemplateNodesAPI.replace.mockResolvedValue();
|
||||||
|
WorkflowJobTemplateNodesAPI.disassociateCredentials.mockResolvedValue();
|
||||||
|
WorkflowJobTemplateNodesAPI.associateCredentials.mockRejectedValue(
|
||||||
|
new Error()
|
||||||
|
);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<svg>
|
||||||
|
<Visualizer template={template} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(0);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Button#visualizer-save').simulate('click');
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
WorkflowJobTemplateNodesAPI.associateCredentials
|
||||||
|
).toHaveBeenCalledTimes(1);
|
||||||
|
expect(
|
||||||
|
wrapper.find('AlertModal[title="Error saving the workflow!"]').length
|
||||||
|
).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
test('Error shown to user when error thrown fetching workflow nodes', async () => {
|
test('Error shown to user when error thrown fetching workflow nodes', async () => {
|
||||||
WorkflowJobTemplatesAPI.readNodes.mockRejectedValue(new Error());
|
WorkflowJobTemplatesAPI.readNodes.mockRejectedValue(new Error());
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user