Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/main/models/FlowNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,23 @@ export class FlowNode extends FlowElement {
private getConnectors(subtype, element) {

if (subtype === 'start') {
return [new FlowElementConnector('connector', element.connector, {})];
const connectors = [];
connectors.push(
new FlowElementConnector('connector', element.connector, {})
);
if (Array.isArray(element.scheduledPaths)) {
for (const asyncElement of element?.scheduledPaths) {
if (asyncElement.connector) {
connectors.push(
new FlowElementConnector('connector', asyncElement.connector, {
childName: asyncElement?.name?.[0] ?? 'AsyncAfterCommit',
childOf: 'rules'
})
)
}
}
}
return connectors;
} else if (subtype === 'decisions') {
const connectors = [];
connectors.push(
Expand Down
45 changes: 45 additions & 0 deletions tests/UnconnectedElement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect } from 'chai';
import 'mocha';
import { scan } from '../src';
import { Flow } from '../src/main/models/Flow';
import { ScanResult } from '../src/main/models/ScanResult';
import unconnectedElement from './testfiles/UnconnectedElement.json';
import asyncAfterCommitOnly from './testfiles/AsyncAfterCommitOnly.json';
import waitForOnly from './testfiles/WaitForOnly.json';


describe('In the unconnected element flow', () => {
let flow: Flow;

it('there should be consideration for async elements', () => {
flow = new Flow({
path: './testfiles/Async_AfterCommitOnly.flow',
xmldata: asyncAfterCommitOnly,
});
const results: ScanResult[] = scan([flow]);
const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs);
expect(occurringResults.length).to.equal(0);
});

it('there should consideration for async wait paths', () => {
flow = new Flow({
path: './testfiles/Async_AfterCommitOnly.flow',
xmldata: waitForOnly,
});
const results: ScanResult[] = scan([flow]);
const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs);
expect(occurringResults.length).to.equal(0);
});

it('there should be checks for unconnected element', () => {
flow = new Flow({
path: './testfiles/Async_AfterCommitOnly.flow',
xmldata: unconnectedElement,
});
const results: ScanResult[] = scan([flow]);
const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs);
expect(occurringResults.length).to.equal(1);
expect(occurringResults[0].ruleName).to.equal("UnconnectedElement");
});
});

58 changes: 58 additions & 0 deletions tests/testfiles/AsyncAfterCommitOnly.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"Flow": {
"$": { "xmlns": "http://soap.sforce.com/2006/04/metadata" },
"apiVersion": ["60.0"],
"assignments": [
{
"description": ["Default Action for Asynchronous Transaction"],
"name": ["VariableAssignment"],
"label": ["VariableAssignment"],
"locationX": ["308"],
"locationY": ["276"],
"assignmentItems": [
{
"assignToReference": ["$Record.Name"],
"operator": ["Assign"],
"value": [{ "stringValue": ["Test"] }]
}
]
}
],
"description": ["AsyncOnlyAutomation"],
"environments": ["Default"],
"interviewLabel": ["Async_OnlyTransaction {!$Flow.CurrentDateTime}"],
"label": ["Async_OnlyTransaction"],
"processMetadataValues": [
{
"name": ["BuilderType"],
"value": [{ "stringValue": ["LightningFlowBuilder"] }]
},
{
"name": ["CanvasMode"],
"value": [{ "stringValue": ["AUTO_LAYOUT_CANVAS"] }]
},
{
"name": ["OriginBuilderType"],
"value": [{ "stringValue": ["LightningFlowBuilder"] }]
}
],
"processType": ["AutoLaunchedFlow"],
"start": [
{
"locationX": ["50"],
"locationY": ["0"],
"object": ["Account"],
"recordTriggerType": ["Create"],
"scheduledPaths": [
{
"connector": [{ "targetReference": ["VariableAssignment"] }],
"pathType": ["AsyncAfterCommit"]
}
],
"triggerType": ["RecordAfterSave"]
}
],
"status": ["Active"]
}
}

66 changes: 66 additions & 0 deletions tests/testfiles/UnconnectedElement.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"Flow": {
"$": { "xmlns": "http://soap.sforce.com/2006/04/metadata" },
"apiVersion": ["60.0"],
"assignments": [
{
"name": ["NotAssigned"],
"label": ["Not Assigned"],
"locationX": ["50"],
"locationY": ["276"],
"assignmentItems": [
{
"assignToReference": ["$Record.Name"],
"operator": ["Assign"],
"value": [{ "stringValue": ["Unassigned"] }]
}
]
},
{
"description": ["Default Action for Asynchronous Transaction"],
"name": ["VariableAssignment"],
"label": ["VariableAssignment"],
"locationX": ["314"],
"locationY": ["276"],
"assignmentItems": [
{
"assignToReference": ["$Record.Name"],
"operator": ["Assign"],
"value": [{ "stringValue": ["Test"] }]
}
]
}
],
"description": ["AsyncOnlyAutomation"],
"environments": ["Default"],
"interviewLabel": ["AsyncOnlyTransaction {!$Flow.CurrentDateTime}"],
"label": ["Async_OnlyTransaction"],
"processMetadataValues": [
{
"name": ["BuilderType"],
"value": [{ "stringValue": ["LightningFlowBuilder"] }]
},
{
"name": ["CanvasMode"],
"value": [{ "stringValue": ["AUTO_LAYOUT_CANVAS"] }]
},
{
"name": ["OriginBuilderType"],
"value": [{ "stringValue": ["LightningFlowBuilder"] }]
}
],
"processType": ["AutoLaunchedFlow"],
"start": [
{
"locationX": ["56"],
"locationY": ["0"],
"object": ["Account"],
"connector": [{ "targetReference": ["VariableAssignment"] }],
"recordTriggerType": ["Create"],
"triggerType": ["RecordAfterSave"]
}
],
"status": ["Active"]
}
}

63 changes: 63 additions & 0 deletions tests/testfiles/WaitForOnly.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"Flow": {
"$": { "xmlns": "http://soap.sforce.com/2006/04/metadata" },
"apiVersion": ["60.0"],
"assignments": [
{
"description": ["Default Action for Asynchronous Transaction"],
"name": ["VariableAssignment"],
"label": ["VariableAssignment"],
"locationX": ["706"],
"locationY": ["382"],
"assignmentItems": [
{
"assignToReference": ["$Record.Name"],
"operator": ["Assign"],
"value": [{ "stringValue": ["Test"] }]
}
]
}
],
"description": ["AsyncOnlyAutomation"],
"environments": ["Default"],
"interviewLabel": ["AsyncOnlyTransaction {!$Flow.CurrentDateTime}"],
"label": ["Async_OnlyTransaction"],
"processMetadataValues": [
{
"name": ["BuilderType"],
"value": [{ "stringValue": ["LightningFlowBuilder"] }]
},
{
"name": ["CanvasMode"],
"value": [{ "stringValue": ["FREE_FORM_CANVAS"] }]
},
{
"name": ["OriginBuilderType"],
"value": [{ "stringValue": ["LightningFlowBuilder"] }]
}
],
"processType": ["AutoLaunchedFlow"],
"start": [
{
"locationX": ["185"],
"locationY": ["0"],
"object": ["Account"],
"recordTriggerType": ["Create"],
"scheduledPaths": [
{ "pathType": ["AsyncAfterCommit"] },
{
"name": ["Wait_For"],
"connector": [{ "targetReference": ["VariableAssignment"] }],
"label": ["Wait For"],
"offsetNumber": ["2"],
"offsetUnit": ["Hours"],
"timeSource": ["RecordTriggerEvent"]
}
],
"triggerType": ["RecordAfterSave"]
}
],
"status": ["Active"]
}
}