Skip to content

Commit ea27161

Browse files
feat: implement task testing business logic
* chore: simplify gitignore * chore: fix eslint * chore: add tsconfig * chore: handle `npm start` with no .env gracefully
1 parent e48e818 commit ea27161

37 files changed

+207121
-1100
lines changed

.gitignore

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,5 @@
1-
# Logs
2-
logs
3-
*.log
4-
npm-debug.log*
5-
yarn-debug.log*
6-
yarn-error.log*
7-
pnpm-debug.log*
8-
lerna-debug.log*
9-
10-
node_modules
11-
dist
12-
dist-ssr
13-
*.local
14-
public
15-
16-
# Editor directories and files
17-
.vscode/*
18-
!.vscode/extensions.json
19-
.idea
201
.DS_Store
21-
*.suo
22-
*.ntvs*
23-
*.njsproj
24-
*.sln
25-
*.sw?
2+
.env
3+
dist
4+
node_modules
5+
public

demo/App.jsx

Lines changed: 157 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,114 @@ import TaskTesting from '../lib';
77

88
import diagram from './diagram.bpmn';
99

10+
import connectorTemplates from './connectorTemplates.json';
11+
12+
import '@carbon/styles/css/styles.min.css';
1013
import './style.css';
1114

1215
function App() {
1316
const modelerRef = useRef(null);
1417

1518
const [ modeler, setModeler ] = useState(null);
16-
const [ tab, setTab ] = useState('test');
1719

18-
const [ config, setConfig ] = useState({
19-
input: {},
20-
output: {}
21-
});
20+
const [ canExecuteTask, setCanExecuteTask ] = useState(false);
21+
22+
const [ config, setConfig ] = useState(undefined);
2223

2324
useEffect(() => {
2425
setTimeout(() => {
25-
26-
// simulate fetching config asynchronously
2726
setConfig({
2827
input: {
29-
'ServiceTask_1': '{\n "foo": "bar"\n}'
28+
'ServiceTask_1': JSON.stringify({
29+
a: 1,
30+
b: 2,
31+
c: {
32+
d: 3,
33+
e: 4,
34+
f: [ 5, 6, 7 ]
35+
},
36+
g: 8,
37+
h: 9,
38+
i: 10,
39+
j: {
40+
k: 11,
41+
l: 12
42+
},
43+
m: 13,
44+
n: 14,
45+
o: 15,
46+
p: 16,
47+
q: 17,
48+
r: 18,
49+
s: 19,
50+
t: 20
51+
}, null, 2)
3052
},
3153
output: {
3254
'ServiceTask_1': {
3355
success: true,
3456
variables: {
35-
foo: 'baz'
57+
'm': 13,
58+
'g': 8,
59+
'a': 1,
60+
'c': {
61+
'd': 3,
62+
'e': 4,
63+
'f': [
64+
5,
65+
6,
66+
7
67+
]
68+
},
69+
'p': 16,
70+
'j': {
71+
'k': 11,
72+
'l': 12
73+
},
74+
'i': 10,
75+
'h': 9,
76+
's': 19,
77+
'o': 15,
78+
't': 20,
79+
'n': 14,
80+
'q': 17,
81+
'r': 18,
82+
'b': 2,
83+
'fooPlusOne': null,
84+
'output1': 1,
85+
'output4': 'foo',
86+
'output2': true,
87+
'output3': {
88+
'foo': 1
89+
}
90+
}
91+
},
92+
'ServiceTask_2': {
93+
success: true,
94+
variables: {
95+
'a': 'foo',
96+
'c': 'bar',
97+
'e': 'baz'
98+
}
99+
},
100+
'ServiceTask_4': {
101+
success: false,
102+
variables: null,
103+
incident: {
104+
key: '2251799814592731',
105+
processDefinitionKey: '2251799814239639',
106+
processInstanceKey: '2251799814592711',
107+
type: 'JOB_NO_RETRIES',
108+
message: 'Bad gateway',
109+
creationTime: '2025-08-21T14:40:55.402+0000',
110+
state: 'ACTIVE',
111+
jobKey: '2251799814592726',
112+
tenantId: '<default>'
36113
}
37114
}
38115
}
39116
});
40-
}, 2000);
117+
}, 3000);
41118
}, []);
42119

43120
useEffect(() => {
@@ -46,14 +123,16 @@ function App() {
46123
container: '#canvas',
47124
propertiesPanel: {
48125
parent: '#properties'
49-
}
126+
},
127+
elementTemplates: connectorTemplates
50128
}));
51129
}
52130
}, []);
53131

54132
useEffect(() => {
55133
async function importXml() {
56134
await modeler.importXML(diagram);
135+
57136
modeler.get('canvas').zoom('fit-viewport');
58137
}
59138

@@ -64,19 +143,55 @@ function App() {
64143

65144
const injector = modeler?.get('injector');
66145

67-
const props = {
68-
injector,
69-
deploy: () => {
70-
console.log('Deploying...');
71-
},
72-
startInstance: () => {
73-
console.log('Starting instance...');
74-
},
75-
getInstance: () => {
76-
console.log('Getting instance...');
77-
},
78-
config,
79-
saveConfig: (config) => setConfig(config)
146+
const deploy = async () => {
147+
const { xml } = await modeler.saveXML();
148+
149+
const response = await fetch('/api/deploy', {
150+
method: 'POST',
151+
headers: {
152+
'Content-Type': 'application/json'
153+
},
154+
body: JSON.stringify({
155+
xml
156+
})
157+
});
158+
159+
return await response.json();
160+
};
161+
162+
const startInstance = async (processId, elementId, variables) => {
163+
const response = await fetch('/api/startInstance', {
164+
method: 'POST',
165+
headers: {
166+
'Content-Type': 'application/json'
167+
},
168+
body: JSON.stringify({
169+
processId,
170+
elementId,
171+
variables
172+
})
173+
});
174+
175+
return response.json();
176+
};
177+
178+
const getProcessInstance = (processInstanceKey) => {
179+
return fetch(`/api/getProcessInstance/${processInstanceKey}`)
180+
.then(response => response.json());
181+
};
182+
183+
const getProcessInstanceVariables = async (processInstanceKey) => {
184+
return fetch(`/api/getProcessInstanceVariables/${processInstanceKey}`)
185+
.then(response => response.json());
186+
};
187+
188+
const getProcessInstanceIncident = async (processInstanceKey) => {
189+
return fetch(`/api/getProcessInstanceIncident/${processInstanceKey}`)
190+
.then(response => response.json());
191+
};
192+
193+
const onConfigChanged = (config) => {
194+
setConfig(config);
80195
};
81196

82197
return (
@@ -85,19 +200,23 @@ function App() {
85200
<div id="canvas" className="canvas"></div>
86201
<div id="properties" className="properties-panel"></div>
87202
</div>
88-
<div className="bottom-panel">
89-
<div className="bottom-panel_tabs">
90-
<div className={ `bottom-panel_tabs-item ${tab === 'problems' ? 'active' : ''}` } onClick={ () => setTab('problems') }>
91-
Problems
92-
</div>
93-
<div className={ `bottom-panel_tabs-item ${tab === 'test' ? 'active' : ''}` } onClick={ () => setTab('test') }>
94-
Task testing
95-
</div>
96-
</div>
97-
<div className="bottom-panel_tabs-content">
98-
{tab === 'problems' && <ProblemsTab />}
99-
{tab === 'test' && <TestTab { ...props } />}
100-
</div>
203+
<div className="task-testing">
204+
<TestTab
205+
injector={ injector }
206+
canExecuteTask={ canExecuteTask }
207+
cannotExecuteTaskLabel="Cannot test task"
208+
cannotExecuteTaskDescription="Configure your connection to test the task"
209+
cannotExecuteTaskCallback={ () => setCanExecuteTask(true) }
210+
api={ {
211+
deploy,
212+
startInstance,
213+
getProcessInstance,
214+
getProcessInstanceVariables,
215+
getProcessInstanceIncident
216+
} }
217+
config={ config }
218+
onConfigChanged={ onConfigChanged }
219+
/>
101220
</div>
102221
</>
103222
);
@@ -107,14 +226,10 @@ function TestTab(props) {
107226
const { injector } = props;
108227

109228
if (!injector) {
110-
return <div>Loading...</div>;
229+
return null;
111230
}
112231

113232
return <TaskTesting { ...props } />;
114233
}
115234

116-
function ProblemsTab() {
117-
return <div style={ { padding: '10px' } }>I got 99 problems but running a single task ain&apos;t one.</div>;
118-
}
119-
120235
export default App;

0 commit comments

Comments
 (0)