Skip to content

Commit 82ede92

Browse files
authored
Merge pull request #65 from FlowTestAI/pre-post-vars
Pre post vars
2 parents 58e3087 + e1bf485 commit 82ede92

File tree

6 files changed

+164
-47
lines changed

6 files changed

+164
-47
lines changed

src/components/molecules/flow/graph/Graph.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// assumption is that apis are giving json as output
22

3+
import { cloneDeep } from 'lodash';
34
import useCanvasStore from 'stores/CanvasStore';
45
import useCollectionStore from 'stores/CollectionStore';
56
import { useTabStore } from 'stores/TabStore';
@@ -9,6 +10,10 @@ import { computeRequestNode } from './compute/requestnode';
910

1011
class Graph {
1112
constructor(nodes, edges, collectionId, onGraphComplete) {
13+
const activeEnv = useCollectionStore
14+
.getState()
15+
.collections.find((c) => c.id === collectionId)
16+
?.environments.find((e) => e.name === useTabStore.getState().selectedEnv);
1217
this.nodes = nodes;
1318
this.edges = edges;
1419
this.onGraphComplete = onGraphComplete;
@@ -17,10 +22,7 @@ class Graph {
1722
this.startTime = Date.now();
1823
this.graphRunNodeOutput = {};
1924
this.auth = undefined;
20-
this.env = useCollectionStore
21-
.getState()
22-
.collections.find((c) => c.id === collectionId)
23-
?.environments.find((e) => e.name === useTabStore.getState().selectedEnv);
25+
this.envVariables = activeEnv ? cloneDeep(activeEnv.variables) : undefined;
2426
}
2527

2628
#checkTimeout() {
@@ -95,12 +97,19 @@ class Graph {
9597
}
9698

9799
if (node.type === 'authNode') {
98-
this.auth = node.data.type ? computeAuthNode(node.data, this.env) : undefined;
100+
this.auth = node.data.type ? computeAuthNode(node.data, this.envVariables) : undefined;
99101
result = ['Success', node, prevNodeOutput];
100102
}
101103

102104
if (node.type === 'requestNode') {
103-
result = await computeRequestNode(node, prevNodeOutputData, this.env, this.auth, this.logs);
105+
result = await computeRequestNode(node, prevNodeOutputData, this.envVariables, this.auth, this.logs);
106+
// add post response variables if any
107+
if (result[3]) {
108+
this.envVariables = {
109+
...this.envVariables,
110+
...result[3],
111+
};
112+
}
104113
}
105114

106115
if (this.#checkTimeout()) {

src/components/molecules/flow/graph/compute/authnode.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { computeVariables } from './utils';
22

3-
export const computeAuthNode = (auth, env) => {
3+
export const computeAuthNode = (auth, envVariables) => {
44
if (auth.type === 'basic-auth') {
5-
auth.username = computeVariables(auth.username, env?.variables);
6-
auth.password = computeVariables(auth.password, env?.variables);
5+
auth.username = computeVariables(auth.username, envVariables);
6+
auth.password = computeVariables(auth.password, envVariables);
77

88
return auth;
99
} else if (auth.type === 'no-auth') {

src/components/molecules/flow/graph/compute/requestnode.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ const formulateRequest = (node, finalUrl, variablesDict, auth, logs) => {
4848
return options;
4949
};
5050

51-
export const computeRequestNode = async (node, prevNodeOutputData, env, auth, logs) => {
51+
export const computeRequestNode = async (node, prevNodeOutputData, envVariables, auth, logs) => {
5252
// step1 evaluate variables of this node
53-
const evalVariables = computeNodeVariables(node.data.variables, prevNodeOutputData);
53+
const evalVariables = computeNodeVariables(node.data.preReqVars, prevNodeOutputData);
5454

5555
const variablesDict = {
56-
...env?.variables,
56+
...envVariables,
5757
...evalVariables,
5858
};
5959

@@ -76,6 +76,10 @@ export const computeRequestNode = async (node, prevNodeOutputData, env, auth, lo
7676
} else {
7777
logs.push(`Request successful: ${JSON.stringify(res)}`);
7878
console.debug('Response: ', JSON.stringify(res));
79+
if (node.data.postRespVars) {
80+
const evalPostRespVars = computeNodeVariables(node.data.postRespVars, res.data);
81+
return ['Success', node, res, evalPostRespVars];
82+
}
7983
return ['Success', node, res];
8084
}
8185
};

src/components/molecules/flow/nodes/RequestNode.js

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,61 +10,79 @@ import useCanvasStore from 'stores/CanvasStore';
1010

1111
const RequestNode = ({ id, data }) => {
1212
const setRequestNodeUrl = useCanvasStore((state) => state.setRequestNodeUrl);
13-
const requestNodeAddVariable = useCanvasStore((state) => state.requestNodeAddVariable);
14-
const requestNodeDeleteVariable = useCanvasStore((state) => state.requestNodeDeleteVariable);
15-
const requestNodeChangeVariable = useCanvasStore((state) => state.requestNodeChangeVariable);
13+
const requestNodeAddPreRequestVar = useCanvasStore((state) => state.requestNodeAddPreRequestVar);
14+
const requestNodeDeletePreRequestVar = useCanvasStore((state) => state.requestNodeDeletePreRequestVar);
15+
const requestNodeChangePreRequestVar = useCanvasStore((state) => state.requestNodeChangePreRequestVar);
16+
17+
const requestNodeAddPostResponseVar = useCanvasStore((state) => state.requestNodeAddPostResponseVar);
18+
const requestNodeDeletePostResponseVar = useCanvasStore((state) => state.requestNodeDeletePostResponseVar);
19+
const requestNodeChangePostResponseVar = useCanvasStore((state) => state.requestNodeChangePostResponseVar);
1620

1721
const [variableDialogOpen, setVariableDialogOpen] = useState(false);
22+
const [modalType, setModalType] = useState('');
1823

19-
const handleAddVariable = (name, type) => {
20-
requestNodeAddVariable(id, name, type);
24+
const handleAddVariable = (vType, name, type) => {
25+
if (vType === 'pre-request') {
26+
requestNodeAddPreRequestVar(id, name, type);
27+
} else if (vType === 'post-response') {
28+
requestNodeAddPostResponseVar(id, name, type);
29+
}
2130
};
2231

23-
const handleDeleteVariable = (event, vId) => {
24-
requestNodeDeleteVariable(id, vId);
32+
const handleDeleteVariable = (event, vType, vId) => {
33+
if (vType === 'pre-request') {
34+
requestNodeDeletePreRequestVar(id, vId);
35+
} else if (vType === 'post-response') {
36+
requestNodeDeletePostResponseVar(id, vId);
37+
}
2538
};
2639

27-
const handleVariableChange = (event, vId) => {
28-
requestNodeChangeVariable(id, vId, event.target.value);
40+
const handleVariableChange = (event, vType, vId) => {
41+
if (vType === 'pre-request') {
42+
requestNodeChangePreRequestVar(id, vId, event.target.value);
43+
} else if (vType === 'post-response') {
44+
requestNodeChangePostResponseVar(id, vId, event.target.value);
45+
}
2946
};
3047

3148
const handleUrlInputChange = (event) => {
3249
setRequestNodeUrl(id, event.target.value);
3350
};
3451

35-
const renderVariables = () => {
52+
const renderVariables = (vType) => {
53+
const variables = vType === 'pre-request' ? data.preReqVars : data.postRespVars;
3654
return (
3755
<>
38-
{data.variables &&
39-
Object.keys(data.variables).map((id) => (
56+
{variables &&
57+
Object.keys(variables).map((id) => (
4058
<div className='flex items-center justify-between pb-2' key={id}>
4159
<div className='flex items-center justify-between text-sm border rounded-md border-neutral-500 text-neutral-500 outline-0 focus:ring-0'>
4260
<label className='px-4 py-2 border-r rounded-bl-md rounded-tl-md border-r-neutral-500'>{id}</label>
43-
{data.variables[id].type === 'Boolean' ? (
61+
{variables[id].type === 'Boolean' ? (
4462
<select
45-
onChange={(e) => handleVariableChange(e, id)}
63+
onChange={(e) => handleVariableChange(e, vType, id)}
4664
name='boolean-val'
4765
className='nodrag h-9 w-full rounded-br-md rounded-tr-md p-2.5 px-1 '
48-
value={data.variables[id].value}
66+
value={variables[id].value}
4967
>
5068
<option value='true'>True</option>
5169
<option value='false'>False</option>
5270
</select>
5371
) : (
5472
<input
55-
type={getInputType(data.variables[id].type)}
73+
type={getInputType(variables[id].type)}
5674
className='nodrag nowheel block h-9 w-full rounded-bl-md rounded-tl-md p-2.5'
5775
name='variable-value'
58-
data-type={getInputType(data.variables[id].type)}
59-
onChange={(e) => handleVariableChange(e, id)}
60-
value={data.variables[id].value}
76+
data-type={getInputType(variables[id].type)}
77+
onChange={(e) => handleVariableChange(e, vType, id)}
78+
value={variables[id].value}
6179
/>
6280
)}
6381
<div className='px-4 py-2 border-l rounded-br-md rounded-tr-md border-l-neutral-500'>
64-
{data.variables[id].type}
82+
{variables[id].type}
6583
</div>
6684
</div>
67-
<div onClick={(e) => handleDeleteVariable(e, id)} className='p-2 text-neutral-500'>
85+
<div onClick={(e) => handleDeleteVariable(e, vType, id)} className='p-2 text-neutral-500'>
6886
<TrashIcon className='w-4 h-4' />
6987
</div>
7088
</div>
@@ -96,16 +114,39 @@ const RequestNode = ({ id, data }) => {
96114
<div className='border-t border-neutral-300 bg-slate-100'>
97115
<div className='flex items-center justify-between px-2 py-4 font-medium'>
98116
<h3>Variables</h3>
99-
<button className='p-2' onClick={() => setVariableDialogOpen(true)}>
117+
</div>
118+
<div>
119+
Pre Request
120+
<button
121+
className='p-2'
122+
onClick={() => {
123+
setModalType('pre-request');
124+
setVariableDialogOpen(true);
125+
}}
126+
>
127+
<PlusIcon className='w-4 h-4' />
128+
</button>
129+
<div className='p-2 pt-4 border-t border-neutral-300 bg-slate-50'>{renderVariables('pre-request')}</div>
130+
</div>
131+
<div>
132+
Post Response
133+
<button
134+
className='p-2'
135+
onClick={() => {
136+
setModalType('post-response');
137+
setVariableDialogOpen(true);
138+
}}
139+
>
100140
<PlusIcon className='w-4 h-4' />
101141
</button>
142+
<div className='p-2 pt-4 border-t border-neutral-300 bg-slate-50'>{renderVariables('post-response')}</div>
102143
</div>
103-
<div className='p-2 pt-4 border-t border-neutral-300 bg-slate-50'>{renderVariables()}</div>
104144
</div>
105145
</div>
106146
<AddVariableModal
107147
closeFn={() => setVariableDialogOpen(false)}
108148
open={variableDialogOpen}
149+
modalType={modalType}
109150
onVariableAdd={handleAddVariable}
110151
/>
111152
</FlowNode>

src/components/molecules/modals/flow/AddVariableModal.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const variableTypes = [
2222
},
2323
];
2424

25-
const AddVariableModal = ({ closeFn = () => null, open = false, onVariableAdd }) => {
25+
const AddVariableModal = ({ closeFn = () => null, open = false, modalType, onVariableAdd }) => {
2626
const [variableName, setVariableName] = useState('');
2727
const [variableType, setVariableType] = useState('String');
2828

@@ -97,7 +97,7 @@ const AddVariableModal = ({ closeFn = () => null, open = false, onVariableAdd })
9797
className='inline-flex justify-center w-full px-4 py-2 text-sm font-medium text-green-900 bg-green-100 border border-transparent rounded-md grow basis-0 hover:bg-green-400'
9898
onClick={() => {
9999
if (variableName.trim() != '') {
100-
onVariableAdd(variableName, variableType);
100+
onVariableAdd(modalType, variableName, variableType);
101101
}
102102
closeFn();
103103
}}

src/stores/CanvasStore.js

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ const useCanvasStore = create((set, get) => ({
9595
}),
9696
});
9797
},
98-
requestNodeAddVariable: (nodeId, name, type) => {
98+
requestNodeAddPreRequestVar: (nodeId, name, type) => {
9999
set({
100100
nodes: get().nodes.map((node) => {
101101
if (node.id === nodeId) {
@@ -107,8 +107,8 @@ const useCanvasStore = create((set, get) => ({
107107
};
108108
node.data = {
109109
...node.data,
110-
variables: {
111-
...node.data.variables,
110+
preReqVars: {
111+
...node.data.preReqVars,
112112
[newId]: newVar,
113113
},
114114
};
@@ -118,37 +118,100 @@ const useCanvasStore = create((set, get) => ({
118118
}),
119119
});
120120
},
121-
requestNodeDeleteVariable: (nodeId, id) => {
121+
requestNodeDeletePreRequestVar: (nodeId, id) => {
122122
set({
123123
nodes: get().nodes.map((node) => {
124124
if (node.id === nodeId) {
125125
// it's important to create a new object here, to inform React Flow about the cahnges
126-
const { [id]: _, ...newVariables } = node.data.variables;
126+
const { [id]: _, ...newVariables } = node.data.preReqVars;
127127

128128
node.data = {
129129
...node.data,
130-
variables: newVariables,
130+
preReqVars: newVariables,
131131
};
132132
}
133133

134134
return node;
135135
}),
136136
});
137137
},
138-
requestNodeChangeVariable: (nodeId, id, value) => {
138+
requestNodeChangePreRequestVar: (nodeId, id, value) => {
139139
set({
140140
nodes: get().nodes.map((node) => {
141141
if (node.id === nodeId) {
142142
// it's important to create a new object here, to inform React Flow about the cahnges
143143
const updateVar = {
144-
type: node.data.variables[id].type,
144+
type: node.data.preReqVars[id].type,
145145
value,
146146
};
147147

148148
node.data = {
149149
...node.data,
150-
variables: {
151-
...node.data.variables,
150+
preReqVars: {
151+
...node.data.preReqVars,
152+
[id]: updateVar,
153+
},
154+
};
155+
}
156+
157+
return node;
158+
}),
159+
});
160+
},
161+
requestNodeAddPostResponseVar: (nodeId, name, type) => {
162+
set({
163+
nodes: get().nodes.map((node) => {
164+
if (node.id === nodeId) {
165+
// it's important to create a new object here, to inform React Flow about the cahnges
166+
const newId = name;
167+
const newVar = {
168+
type: type,
169+
value: getDefaultValue(type),
170+
};
171+
node.data = {
172+
...node.data,
173+
postRespVars: {
174+
...node.data.postRespVars,
175+
[newId]: newVar,
176+
},
177+
};
178+
}
179+
180+
return node;
181+
}),
182+
});
183+
},
184+
requestNodeDeletePostResponseVar: (nodeId, id) => {
185+
set({
186+
nodes: get().nodes.map((node) => {
187+
if (node.id === nodeId) {
188+
// it's important to create a new object here, to inform React Flow about the cahnges
189+
const { [id]: _, ...newVariables } = node.data.postRespVars;
190+
191+
node.data = {
192+
...node.data,
193+
postRespVars: newVariables,
194+
};
195+
}
196+
197+
return node;
198+
}),
199+
});
200+
},
201+
requestNodeChangePostResponseVar: (nodeId, id, value) => {
202+
set({
203+
nodes: get().nodes.map((node) => {
204+
if (node.id === nodeId) {
205+
// it's important to create a new object here, to inform React Flow about the cahnges
206+
const updateVar = {
207+
type: node.data.postRespVars[id].type,
208+
value,
209+
};
210+
211+
node.data = {
212+
...node.data,
213+
postRespVars: {
214+
...node.data.postRespVars,
152215
[id]: updateVar,
153216
},
154217
};

0 commit comments

Comments
 (0)