From 8772d807f343596e57d4ca9f205b0ac7b7e396f0 Mon Sep 17 00:00:00 2001 From: junners Date: Tue, 20 Feb 2024 23:29:50 -0800 Subject: [PATCH] feat: add in support for async paths --- src/main/models/FlowNode.ts | 18 ++++++- tests/UnconnectedElement.test.ts | 45 ++++++++++++++++ tests/testfiles/AsyncAfterCommitOnly.json | 58 ++++++++++++++++++++ tests/testfiles/UnconnectedElement.json | 66 +++++++++++++++++++++++ tests/testfiles/WaitForOnly.json | 63 ++++++++++++++++++++++ 5 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 tests/UnconnectedElement.test.ts create mode 100644 tests/testfiles/AsyncAfterCommitOnly.json create mode 100644 tests/testfiles/UnconnectedElement.json create mode 100644 tests/testfiles/WaitForOnly.json diff --git a/src/main/models/FlowNode.ts b/src/main/models/FlowNode.ts index 58673e4..1ac5a53 100644 --- a/src/main/models/FlowNode.ts +++ b/src/main/models/FlowNode.ts @@ -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( diff --git a/tests/UnconnectedElement.test.ts b/tests/UnconnectedElement.test.ts new file mode 100644 index 0000000..4eee8ce --- /dev/null +++ b/tests/UnconnectedElement.test.ts @@ -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"); + }); +}); + diff --git a/tests/testfiles/AsyncAfterCommitOnly.json b/tests/testfiles/AsyncAfterCommitOnly.json new file mode 100644 index 0000000..0959078 --- /dev/null +++ b/tests/testfiles/AsyncAfterCommitOnly.json @@ -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"] + } + } + \ No newline at end of file diff --git a/tests/testfiles/UnconnectedElement.json b/tests/testfiles/UnconnectedElement.json new file mode 100644 index 0000000..78c479e --- /dev/null +++ b/tests/testfiles/UnconnectedElement.json @@ -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"] + } + } + \ No newline at end of file diff --git a/tests/testfiles/WaitForOnly.json b/tests/testfiles/WaitForOnly.json new file mode 100644 index 0000000..612a693 --- /dev/null +++ b/tests/testfiles/WaitForOnly.json @@ -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"] + } + } + \ No newline at end of file