@yousolution/node-red-contrib-you-sap-service-layer 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ # [0.1.0] - 2022-07-28
6
+
7
+ - Added sqlQuery node to execute saved sql from SAP Service Layer
8
+ - Added a second output to the nextLink node to check when pagination is finished
9
+ - Bug fix
10
+
5
11
  # [0.0.5] - 2022-05-27
6
12
 
7
13
  - Change cross join
package/data/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "private": true,
6
6
  "dependencies": {
7
7
  "@types/node-red": "^1.1.1",
8
- "@yousolution/node-red-contrib-you-sap-service-layer": "file:yousolution-node-red-contrib-you-sap-service-layer-0.0.4.tgz",
8
+ "@yousolution/node-red-contrib-you-sap-service-layer": "file:yousolution-node-red-contrib-you-sap-service-layer-0.1.0.tgz",
9
9
  "@yousolution/node-red-contrib-you-yousolution.cloud": "0.0.1",
10
10
  "faker": "^6.6.6",
11
11
  "node-red-contrib-sse-client": "~0.2.2",
@@ -0,0 +1,180 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('SQLQuery',{
3
+ category: 'Sap',
4
+ color: '#FFC300',
5
+ defaults: {
6
+ name: {value: ''},
7
+ sqlCode: {value: ''},
8
+ // sqlName: {value: ''},
9
+ // sqlText: {value: ''},
10
+ headers: {value: ''},
11
+ nextLink: {value: ''},
12
+ bodyPost: {value: ''}
13
+ },
14
+ inputs:1,
15
+ outputs:1,
16
+ icon: 'font-awesome/fa-search',
17
+ label: function() {
18
+ return this.name||"SQL Query";
19
+ },
20
+ oneditprepare: function() {
21
+
22
+ $("#node-input-sqlCode").typedInput({
23
+ type:"msg",
24
+ types:["msg"],
25
+ typeField: "#node-input-sqlCode-type",
26
+ value: 'sqlCode'
27
+ });
28
+
29
+ // $("#node-input-sqlName").typedInput({
30
+ // type:"msg",
31
+ // types:["msg"],
32
+ // typeField: "#node-input-sqlName-type",
33
+ // value: 'sqlName'
34
+ // });
35
+
36
+ // $("#node-input-sqlText").typedInput({
37
+ // type:"msg",
38
+ // types:["msg"],
39
+ // typeField: "#node-input-sqlText-type",
40
+ // value: 'sqlText'
41
+ // });
42
+
43
+ $("#node-input-headers").typedInput({
44
+ type:"msg",
45
+ types:["msg"],
46
+ typeField: "#node-input-headers-type",
47
+ value: 'headers'
48
+ });
49
+
50
+ $("#node-input-nextLink").typedInput({
51
+ type:"msg",
52
+ types:["msg"],
53
+ typeField: "#node-input-nextLink-type",
54
+ value: 'nextLink'
55
+ });
56
+
57
+ $("#node-input-bodyPost").typedInput({
58
+ type:"msg",
59
+ types:["msg"],
60
+ typeField: "#node-input-bodyPost-type",
61
+ value: 'bodyPost'
62
+ });
63
+
64
+ // jQuery("#node-input-entity").change(function() {
65
+ // jQuery('#container-udo').hide();
66
+ // jQuery('#container-udt').hide();
67
+ // jQuery('#container-partnerName').hide();
68
+ // jQuery('#container-scriptName').hide();
69
+ // if (jQuery(this).val() === 'UDO'){
70
+ // jQuery('#container-udo').show();
71
+ // }
72
+ // if (jQuery(this).val() === 'UDT'){
73
+ // jQuery('#container-udt').show();
74
+ // }
75
+ // if (jQuery(this).val() === 'script'){
76
+ // jQuery('#container-partnerName').show();
77
+ // jQuery('#container-scriptName').show();
78
+ // }
79
+
80
+ // });
81
+ }
82
+ });
83
+ </script>
84
+
85
+ <script type="text/html" data-template-name="SQLQuery">
86
+ <div class="form-row">
87
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
88
+ <input type="text" id="node-input-name" placeholder="Name">
89
+ </div>
90
+
91
+ <div class="form-row">
92
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlCode</label>
93
+ <input type="text" id="node-input-sqlCode">
94
+ <input type="hidden" id="node-input-sqlCode-type">
95
+ </div>
96
+
97
+ <!-- <div class="form-row">
98
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlName</label>
99
+ <input type="text" id="node-input-sqlName">
100
+ <input type="hidden" id="node-input-sqlName-type">
101
+ </div>
102
+
103
+ <div class="form-row">
104
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlText</label>
105
+ <input type="text" id="node-input-sqlText">
106
+ <input type="hidden" id="node-input-sqlText-type">
107
+ </div> -->
108
+
109
+ <div class="form-row">
110
+ <label for="node-input-type"><i class="fa fa-cog"></i> Headers</label>
111
+ <input type="text" id="node-input-headers">
112
+ <input type="hidden" id="node-input-headers-type">
113
+ </div>
114
+
115
+ <div class="form-row">
116
+ <label for="node-input-type"><i class="fa fa-cog"></i> NextLink</label>
117
+ <input type="text" id="node-input-nextLink">
118
+ <input type="hidden" id="node-input-nextLink-type">
119
+ </div>
120
+
121
+ <div class="form-row">
122
+ <label for="node-input-type"><i class="fa fa-cog"></i> BodyPost</label>
123
+ <input type="text" id="node-input-bodyPost">
124
+ <input type="hidden" id="node-input-bodyPost-type">
125
+ </div>
126
+ </script>
127
+
128
+
129
+ <!-- Documentation -->
130
+ <script type="text/html" data-help-name="SQLQuery">
131
+ <p>Create a new Entity action</p>
132
+
133
+ <h3>Inputs</h3>
134
+ <dl class="message-properties">
135
+ <dt>Name
136
+ <span class="property-type">string</span>
137
+ </dt>
138
+ <dd> the node's name </dd>
139
+ <dt>Entity
140
+ <span class="property-type">string</span>
141
+ </dt>
142
+ <dd> the entity name of SAP resource </dd>
143
+ <dt>EntityId
144
+ <span class="property-type">number | string</span>
145
+ </dt>
146
+ <dd> the id of the entity of SAP resource </dd>
147
+ <dt>bodyPost
148
+ <span class="property-type">object</span>
149
+ </dt>
150
+ <dd> the data of the entity </dd>
151
+ </dl>
152
+
153
+ <h3>Outputs</h3>
154
+ <ol class="node-ports">
155
+ <li>Standard output
156
+ <dl class="message-properties">
157
+ <dt>payload <span class="property-type">string</span></dt>
158
+ <dd>the standard output of the command.</dd>
159
+ </dl>
160
+ </li>
161
+ </ol>
162
+
163
+ <h3>Details</h3>
164
+ <p>this node is used to create the entity of SAP.
165
+ See the examples to understand how to use it.
166
+ </p>
167
+ <!-- <p><code>msg.payload</code> is used as the payload of the published message.
168
+ If it contains an Object it will be converted to a JSON string before being sent.
169
+ If it contains a binary Buffer the message will be published as-is.</p>
170
+ <p>The topic used can be configured in the node or, if left blank, can be set
171
+ by <code>msg.topic</code>.</p>
172
+ <p>Likewise the QoS and retain values can be configured in the node or, if left
173
+ blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.</p> -->
174
+
175
+ <h3>References</h3>
176
+ <ul>
177
+ <li><a href="https://sap-samples.github.io/smb-summit-hackathon/b1sl.html" target="_black">Service layer API docs</a> - for more details </li>
178
+ <li><a href="https://github.com/yousolution-cloud/node-red-contrib-you-sap-service-layer">@yousolution-cloud/node-red-contrib-you-sap-service-layer</a> - the nodes github repository</li>
179
+ </ul>
180
+ </script>
@@ -0,0 +1,43 @@
1
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
2
+ const axios = require('axios');
3
+ const Support = require('./support');
4
+
5
+ module.exports = function (RED) {
6
+ function SQLQuery(config) {
7
+ RED.nodes.createNode(this, config);
8
+ const node = this;
9
+ // reset status
10
+ node.status({});
11
+
12
+ node.on('input', async (msg, send, done) => {
13
+ // reset status
14
+ node.status({});
15
+ try {
16
+ const data = msg[config.bodyPost];
17
+ const params = {
18
+ SqlCode: msg[config.sqlCode],
19
+ };
20
+
21
+ if (!params.SqlCode) {
22
+ const missingParams = [];
23
+ params.SqlCode ? null : missingParams.push('SqlCode');
24
+ done(new Error(`Missing mandatory params: ${missingParams.join(',')}.`));
25
+ return;
26
+ }
27
+
28
+ const options = { method: 'POST', hasRawQuery: false, isSQLQuery: true, data: data };
29
+ const login = Support.login;
30
+ const result = await Support.sendRequest({ node, msg, config, axios, login, options });
31
+ msg.payload = result.data;
32
+ msg.nextLink = result.data['odata.nextLink'];
33
+ msg.statusCode = result.status;
34
+ node.status({ fill: 'green', shape: 'dot', text: 'success' });
35
+ node.send(msg);
36
+ } catch (error) {
37
+ node.status({ fill: 'red', shape: 'dot', text: 'Error' });
38
+ done(error);
39
+ }
40
+ });
41
+ }
42
+ RED.nodes.registerType('SQLQuery', SQLQuery, {});
43
+ };
@@ -0,0 +1,166 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('createSQLQuery',{
3
+ category: 'Sap',
4
+ color: '#FFC300',
5
+ defaults: {
6
+ name: {value: ''},
7
+ sqlCode: {value: ''},
8
+ sqlName: {value: ''},
9
+ sqlText: {value: ''},
10
+ headers: {value: ''},
11
+ bodyPost: {value: ''}
12
+ },
13
+ inputs:1,
14
+ outputs:1,
15
+ icon: 'font-awesome/fa-plus',
16
+ label: function() {
17
+ return this.name||"Create SQL Query";
18
+ },
19
+ oneditprepare: function() {
20
+
21
+ $("#node-input-sqlCode").typedInput({
22
+ type:"msg",
23
+ types:["msg"],
24
+ typeField: "#node-input-sqlCode-type",
25
+ value: 'sqlCode'
26
+ });
27
+
28
+ $("#node-input-sqlName").typedInput({
29
+ type:"msg",
30
+ types:["msg"],
31
+ typeField: "#node-input-sqlName-type",
32
+ value: 'sqlName'
33
+ });
34
+
35
+ $("#node-input-sqlText").typedInput({
36
+ type:"msg",
37
+ types:["msg"],
38
+ typeField: "#node-input-sqlText-type",
39
+ value: 'sqlText'
40
+ });
41
+
42
+ $("#node-input-headers").typedInput({
43
+ type:"msg",
44
+ types:["msg"],
45
+ typeField: "#node-input-headers-type",
46
+ value: 'headers'
47
+ });
48
+
49
+ $("#node-input-bodyPost").typedInput({
50
+ type:"msg",
51
+ types:["msg"],
52
+ typeField: "#node-input-bodyPost-type",
53
+ value: 'bodyPost'
54
+ });
55
+
56
+ // jQuery("#node-input-entity").change(function() {
57
+ // jQuery('#container-udo').hide();
58
+ // jQuery('#container-udt').hide();
59
+ // jQuery('#container-partnerName').hide();
60
+ // jQuery('#container-scriptName').hide();
61
+ // if (jQuery(this).val() === 'UDO'){
62
+ // jQuery('#container-udo').show();
63
+ // }
64
+ // if (jQuery(this).val() === 'UDT'){
65
+ // jQuery('#container-udt').show();
66
+ // }
67
+ // if (jQuery(this).val() === 'script'){
68
+ // jQuery('#container-partnerName').show();
69
+ // jQuery('#container-scriptName').show();
70
+ // }
71
+
72
+ // });
73
+ }
74
+ });
75
+ </script>
76
+
77
+ <script type="text/html" data-template-name="createSQLQuery">
78
+ <div class="form-row">
79
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
80
+ <input type="text" id="node-input-name" placeholder="Name">
81
+ </div>
82
+
83
+ <div class="form-row">
84
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlCode</label>
85
+ <input type="text" id="node-input-sqlCode">
86
+ <input type="hidden" id="node-input-sqlCode-type">
87
+ </div>
88
+
89
+ <div class="form-row">
90
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlName</label>
91
+ <input type="text" id="node-input-sqlName">
92
+ <input type="hidden" id="node-input-sqlName-type">
93
+ </div>
94
+
95
+ <div class="form-row">
96
+ <label for="node-input-type"><i class="fa fa-cog"></i> SqlText</label>
97
+ <input type="text" id="node-input-sqlText">
98
+ <input type="hidden" id="node-input-sqlText-type">
99
+ </div>
100
+
101
+ <div class="form-row">
102
+ <label for="node-input-type"><i class="fa fa-cog"></i> Headers</label>
103
+ <input type="text" id="node-input-headers">
104
+ <input type="hidden" id="node-input-headers-type">
105
+ </div>
106
+
107
+ <div class="form-row">
108
+ <label for="node-input-type"><i class="fa fa-cog"></i> BodyPost</label>
109
+ <input type="text" id="node-input-bodyPost">
110
+ <input type="hidden" id="node-input-bodyPost-type">
111
+ </div>
112
+ </script>
113
+
114
+
115
+ <!-- Documentation -->
116
+ <script type="text/html" data-help-name="createSQLQuery">
117
+ <p>Create a new SQL query from SAP service layer</p>
118
+
119
+ <h3>Inputs</h3>
120
+ <dl class="message-properties">
121
+ <dt>Name
122
+ <span class="property-type">string</span>
123
+ </dt>
124
+ <dd> the node's name </dd>
125
+ <dt>Entity
126
+ <span class="property-type">string</span>
127
+ </dt>
128
+ <dd> the entity name of SAP resource </dd>
129
+ <dt>EntityId
130
+ <span class="property-type">number | string</span>
131
+ </dt>
132
+ <dd> the id of the entity of SAP resource </dd>
133
+ <dt>bodyPost
134
+ <span class="property-type">object</span>
135
+ </dt>
136
+ <dd> the data of the entity </dd>
137
+ </dl>
138
+
139
+ <h3>Outputs</h3>
140
+ <ol class="node-ports">
141
+ <li>Standard output
142
+ <dl class="message-properties">
143
+ <dt>payload <span class="property-type">string</span></dt>
144
+ <dd>the standard output of the command.</dd>
145
+ </dl>
146
+ </li>
147
+ </ol>
148
+
149
+ <h3>Details</h3>
150
+ <p>this node is used to create the entity of SAP.
151
+ See the examples to understand how to use it.
152
+ </p>
153
+ <!-- <p><code>msg.payload</code> is used as the payload of the published message.
154
+ If it contains an Object it will be converted to a JSON string before being sent.
155
+ If it contains a binary Buffer the message will be published as-is.</p>
156
+ <p>The topic used can be configured in the node or, if left blank, can be set
157
+ by <code>msg.topic</code>.</p>
158
+ <p>Likewise the QoS and retain values can be configured in the node or, if left
159
+ blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.</p> -->
160
+
161
+ <h3>References</h3>
162
+ <ul>
163
+ <li><a href="https://sap-samples.github.io/smb-summit-hackathon/b1sl.html" target="_black">Service layer API docs</a> - for more details </li>
164
+ <li><a href="https://github.com/yousolution-cloud/node-red-contrib-you-sap-service-layer">@yousolution-cloud/node-red-contrib-you-sap-service-layer</a> - the nodes github repository</li>
165
+ </ul>
166
+ </script>
@@ -0,0 +1,67 @@
1
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
2
+ const axios = require('axios');
3
+ const Support = require('./support');
4
+
5
+ module.exports = function (RED) {
6
+ function CreateSQLQuery(config) {
7
+ RED.nodes.createNode(this, config);
8
+ const node = this;
9
+ // reset status
10
+ node.status({});
11
+
12
+ node.on('input', async (msg, send, done) => {
13
+ // reset status
14
+ node.status({});
15
+ try {
16
+ // const data = msg[config.bodyPost];
17
+ const data = {
18
+ SqlCode: msg[config.sqlCode],
19
+ SqlName: msg[config.sqlName],
20
+ SqlText: msg[config.sqlText],
21
+ };
22
+
23
+ if (!data.SqlCode || !data.SqlName || !data.SqlText) {
24
+ const missingParams = [];
25
+ data.SqlCode ? null : missingParams.push('SqlCode');
26
+ data.SqlName ? null : missingParams.push('SqlName');
27
+ data.SqlText ? null : missingParams.push('SqlText');
28
+ done(new Error(`Missing mandatory params: ${missingParams.join(',')}.`));
29
+ return;
30
+ }
31
+
32
+ // if (!data.SqlCode) {
33
+ // node.status({ fill: 'red', shape: 'dot', text: 'SqlCode must have value' });
34
+ // done(new Error('SqlCode must have value'));
35
+ // return;
36
+ // }
37
+ // if (!data.SqlName) {
38
+ // node.status({ fill: 'red', shape: 'dot', text: 'SqlName must have value' });
39
+ // done(new Error('SqlName must have value'));
40
+ // return;
41
+ // }
42
+ // if (!data.SqlText) {
43
+ // node.status({ fill: 'red', shape: 'dot', text: 'SqlText must have value' });
44
+ // done(new Error('SqlText must have value'));
45
+ // return;
46
+ // }
47
+
48
+ // if (!data) {
49
+ // node.status({ fill: 'red', shape: 'dot', text: 'bodyPost must have value' });
50
+ // done(new Error('bodyPost must have value'));
51
+ // return;
52
+ // }
53
+ const options = { method: 'POST', hasRawQuery: false, isCreateSQLQuery: true, data: data };
54
+ const login = Support.login;
55
+ const result = await Support.sendRequest({ node, msg, config, axios, login, options });
56
+ msg.payload = result;
57
+ msg.statusCode = result.status;
58
+ node.status({ fill: 'green', shape: 'dot', text: 'success' });
59
+ node.send(msg);
60
+ } catch (error) {
61
+ node.status({ fill: 'red', shape: 'dot', text: 'Error' });
62
+ done(error);
63
+ }
64
+ });
65
+ }
66
+ RED.nodes.registerType('createSQLQuery', CreateSQLQuery, {});
67
+ };
@@ -7,7 +7,7 @@
7
7
  nextLink: {value: ''}
8
8
  },
9
9
  inputs:1,
10
- outputs:1,
10
+ outputs:2,
11
11
  icon: 'font-awesome/fa-arrows-h',
12
12
  label: function() {
13
13
  return this.name||"Next link";
@@ -59,8 +59,14 @@
59
59
  <ol class="node-ports">
60
60
  <li>Standard output
61
61
  <dl class="message-properties">
62
- <dt>payload <span class="property-type">string</span></dt>
63
- <dd>the standard output of the command.</dd>
62
+ <dt>payload <span class="property-type">msg</span></dt>
63
+ <dd>It returns the message with next link to the next page.</dd>
64
+ </dl>
65
+ </li>
66
+ <li>Standard output
67
+ <dl class="message-properties">
68
+ <dt>payload <span class="property-type">msg</span></dt>
69
+ <dd>It returns the message when the last page is reached.</dd>
64
70
  </dl>
65
71
  </li>
66
72
  </ol>
package/nodes/nextLink.js CHANGED
@@ -7,12 +7,12 @@ module.exports = function (RED) {
7
7
  const nextLink = msg[config.nextLink];
8
8
 
9
9
  if (!nextLink) {
10
+ node.send([null, msg]);
10
11
  return;
11
12
  }
12
-
13
- node.send(msg);
13
+
14
+ node.send([msg, null]);
14
15
  });
15
16
  }
16
17
  RED.nodes.registerType('nextLink', NextLinkNode, {});
17
18
  };
18
-
package/nodes/support.js CHANGED
@@ -164,6 +164,7 @@ function generateRequest(node, msg, config, options) {
164
164
  options.isCrossJoin = options.isCrossJoin || false;
165
165
  options.isManipulate = options.isManipulate || false;
166
166
  options.isService = options.isService || false;
167
+ options.isCreateSQLQuery = options.isCreateSQLQuery || false;
167
168
  options.service = options.service || null;
168
169
  options.manipulateMethod = options.manipulateMethod || null;
169
170
 
@@ -171,6 +172,7 @@ function generateRequest(node, msg, config, options) {
171
172
 
172
173
  let rawQuery = null;
173
174
  let url;
175
+
174
176
  if (options.hasRawQuery) {
175
177
  try {
176
178
  rawQuery = eval(config.query);
@@ -180,7 +182,7 @@ function generateRequest(node, msg, config, options) {
180
182
  }
181
183
 
182
184
  let entity = config.entity;
183
- if (!entity && !options.isService) {
185
+ if (!entity && !options.isService && !options.isCreateSQLQuery && !options.isSQLQuery) {
184
186
  throw new Error('Missing entity');
185
187
  }
186
188
 
@@ -214,6 +216,13 @@ function generateRequest(node, msg, config, options) {
214
216
  url = `https://${host}:${port}/b1s/${version}/$crossjoin(${entity})`;
215
217
  }
216
218
 
219
+ if (options.isSQLQuery) {
220
+ if (!config.sqlCode) {
221
+ throw new Error('Missing sqlCode');
222
+ }
223
+ url = `https://${host}:${port}/b1s/${version}/SQLQueries('${msg[config.sqlCode]}')/List`;
224
+ }
225
+
217
226
  if (odataNextLink) {
218
227
  url = `https://${host}:${port}/b1s/${version}/${odataNextLink}`;
219
228
  }
@@ -268,6 +277,19 @@ function generateRequest(node, msg, config, options) {
268
277
  url = `https://${host}:${port}/b1s/${version}/${config.service}`;
269
278
  }
270
279
 
280
+ if (options.isCreateSQLQuery) {
281
+ if (!config.sqlCode) {
282
+ throw new Error('Missing sqlCode');
283
+ }
284
+ if (!config.sqlName) {
285
+ throw new Error('Missing sqlName');
286
+ }
287
+ if (!config.sqlText) {
288
+ throw new Error('Missing sqlText');
289
+ }
290
+ url = `https://${host}:${port}/b1s/${version}/SQLQueries`;
291
+ }
292
+
271
293
  if (rawQuery && !odataNextLink) {
272
294
  const urlOdata = buildQuery(rawQuery);
273
295
  msg.odata = urlOdata;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yousolution/node-red-contrib-you-sap-service-layer",
3
- "version": "0.0.6",
3
+ "version": "0.1.0",
4
4
  "description": "Unofficial module SAP Service Layer for NODE-RED",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -30,7 +30,9 @@
30
30
  "crossJoinSap": "/nodes/crossJoinSap.js",
31
31
  "nextLink": "/nodes/nextLink.js",
32
32
  "serviceSap": "/nodes/serviceSap.js",
33
- "manipulateEntitySap": "/nodes/manipulateEntitySap.js"
33
+ "manipulateEntitySap": "/nodes/manipulateEntitySap.js",
34
+ "createSQLQuery": "/nodes/createSQLQuery.js",
35
+ "SQLQuery": "/nodes/SQLQuery.js"
34
36
  }
35
37
  },
36
38
  "dependencies": {
@@ -144,6 +144,52 @@ describe('authenticateSap Node', () => {
144
144
  });
145
145
  });
146
146
 
147
+ it('should generic error ', (done) => {
148
+ const flow = [
149
+ {
150
+ id: 'n1',
151
+ type: 'authenticateSap',
152
+ name: 'authenticateSap',
153
+ wires: [['n2']],
154
+ z: 'flow',
155
+ rules: [{ t: 'set', p: 'payload', to: '#:(memory1)::flowValue', tot: 'flow' }],
156
+ },
157
+ { id: 'n2', type: 'helper' },
158
+ ];
159
+ helper.load(authenticateSap, flow, () => {
160
+ const n2 = helper.getNode('n2');
161
+ const n1 = helper.getNode('n1');
162
+ n1.credentials.user = 'user';
163
+ n1.credentials.password = 'password';
164
+ n1.credentials.company = 'company';
165
+
166
+ sinon.stub(Support, 'login').rejects(new Error('Custom error'));
167
+
168
+ // n1.context().flow.set(`_YOU_SapServiceLayer_${n1.id}.headers`, true, 'memory1', function (error) {
169
+ // // console.log(error);
170
+ // });
171
+
172
+ n1.receive({});
173
+
174
+ n2.on('input', (msg) => {
175
+ try {
176
+ msg.should.have.property('payload', new Error('Custom error'));
177
+ done();
178
+ } catch (err) {
179
+ done(err);
180
+ }
181
+ });
182
+
183
+ n1.on('call:error', (error) => {
184
+ try {
185
+ error.should.have.property('firstArg', new Error('Custom error'));
186
+ } catch (err) {
187
+ done(err);
188
+ }
189
+ });
190
+ });
191
+ });
192
+
147
193
  it('should have without headers connected', (done) => {
148
194
  const flow = [
149
195
  {
@@ -0,0 +1,174 @@
1
+ const should = require('should');
2
+ const helper = require('node-red-node-test-helper');
3
+ const createSQLQuery = require('../nodes/createSQLQuery');
4
+ const Context = require('../node_modules/./@node-red/runtime/lib/nodes/context/index');
5
+ const sinon = require('sinon');
6
+ const Support = require('../nodes/support');
7
+
8
+ helper.init(require.resolve('node-red'));
9
+
10
+ describe('createSQLQuery Node', () => {
11
+ beforeEach((done) => {
12
+ helper.startServer(done);
13
+ });
14
+
15
+ function initContext(done) {
16
+ Context.init({
17
+ contextStorage: {
18
+ memory0: {
19
+ module: 'memory',
20
+ },
21
+ memory1: {
22
+ module: 'memory',
23
+ },
24
+ },
25
+ });
26
+ Context.load().then(function () {
27
+ done();
28
+ });
29
+ }
30
+
31
+ afterEach((done) => {
32
+ helper
33
+ .unload()
34
+ .then(function () {
35
+ return Context.clean({ allNodes: {} });
36
+ })
37
+ .then(function () {
38
+ return Context.close();
39
+ })
40
+ .then(function () {
41
+ helper.stopServer(done);
42
+ });
43
+
44
+ // Restore the default sandbox here
45
+ sinon.restore();
46
+
47
+ // helper.unload();
48
+ // helper.stopServer(done);
49
+ });
50
+
51
+ it('should be loaded', (done) => {
52
+ const flow = [
53
+ {
54
+ id: 'n1',
55
+ type: 'createSQLQuery',
56
+ name: 'createSQLQuery',
57
+ wires: [['n2']],
58
+ z: 'flow',
59
+ rules: [{ t: 'set', p: 'payload', to: '#:(memory1)::flowValue', tot: 'flow' }],
60
+ },
61
+ ];
62
+
63
+ helper.load(createSQLQuery, flow, () => {
64
+ initContext(function () {
65
+ const n1 = helper.getNode('n1');
66
+ try {
67
+ n1.should.have.property('name', 'createSQLQuery');
68
+ done();
69
+ } catch (err) {
70
+ done(err);
71
+ }
72
+ });
73
+ });
74
+ });
75
+
76
+ it('should have correct request with data', (done) => {
77
+ const flow = [
78
+ {
79
+ id: 'n1',
80
+ type: 'createSQLQuery',
81
+ name: 'createSQLQuery',
82
+ wires: [['n2']],
83
+ z: 'flow',
84
+ sqlCode: 'sqlCode',
85
+ sqlName: 'sqlName',
86
+ sqlText: 'sqlText',
87
+ rules: [{ t: 'set', p: 'payload', to: '#:(memory1)::flowValue', tot: 'flow' }],
88
+ },
89
+ { id: 'n2', type: 'helper' },
90
+ ];
91
+ helper.load(createSQLQuery, flow, () => {
92
+ const n2 = helper.getNode('n2');
93
+ const n1 = helper.getNode('n1');
94
+
95
+ sinon.stub(Support, 'sendRequest').resolves('ok');
96
+
97
+ n1.receive({ sqlCode: 'code', sqlName: 'name', sqlText: 'text' });
98
+
99
+ n2.on('input', (msg) => {
100
+ try {
101
+ msg.should.have.property('_msgid');
102
+ msg.should.have.property('payload', 'ok');
103
+ done();
104
+ } catch (err) {
105
+ done(err);
106
+ }
107
+ });
108
+ });
109
+ });
110
+
111
+ // it('should have request without data', (done) => {
112
+ // const flow = [
113
+ // {
114
+ // id: 'n1',
115
+ // type: 'serviceSap',
116
+ // name: 'serviceSap',
117
+ // wires: [['n2']],
118
+ // z: 'flow',
119
+ // bodyPost: 'data',
120
+ // rules: [{ t: 'set', p: 'payload', to: '#:(memory1)::flowValue', tot: 'flow' }],
121
+ // },
122
+ // { id: 'n2', type: 'helper' },
123
+ // ];
124
+ // helper.load(serviceSap, flow, () => {
125
+ // const n2 = helper.getNode('n2');
126
+ // const n1 = helper.getNode('n1');
127
+
128
+ // sinon.stub(Support, 'sendRequest').resolves('ok');
129
+ // n1.receive({});
130
+
131
+ // n2.on('input', (msg) => {
132
+ // try {
133
+ // msg.should.have.property('_msgid');
134
+ // msg.should.have.property('payload', 'ok');
135
+ // done();
136
+ // } catch (err) {
137
+ // done(err);
138
+ // }
139
+ // });
140
+ // });
141
+ // });
142
+
143
+ it('should handle the error', (done) => {
144
+ const flow = [
145
+ {
146
+ id: 'n1',
147
+ type: 'createSQLQuery',
148
+ name: 'createSQLQuery',
149
+ wires: [['n2']],
150
+ z: 'flow',
151
+ sqlCode: 'sqlCode',
152
+ sqlName: 'sqlName',
153
+ sqlText: 'sqlText',
154
+ rules: [{ t: 'set', p: 'payload', to: '#:(memory1)::flowValue', tot: 'flow' }],
155
+ },
156
+ { id: 'n2', type: 'helper' },
157
+ ];
158
+ helper.load(createSQLQuery, flow, () => {
159
+ const n2 = helper.getNode('n2');
160
+ const n1 = helper.getNode('n1');
161
+
162
+ const expected = new Error('Missing mandatory params: SqlCode.');
163
+
164
+ sinon.stub(Support, 'sendRequest').rejects(expected);
165
+
166
+ n1.receive({ sqlName: 'name', sqlText: 'text' });
167
+
168
+ n1.on('call:error', (error) => {
169
+ should.deepEqual(error.args[0], expected);
170
+ done();
171
+ });
172
+ });
173
+ });
174
+ });
@@ -835,6 +835,211 @@ describe('support library', () => {
835
835
  }).to.throw('Missing method');
836
836
  });
837
837
 
838
+ it('should generate a correct request with SQLQuery create query', () => {
839
+ const node = {
840
+ context: () => {
841
+ return {
842
+ flow: {
843
+ get: (param) => {
844
+ if (param == '_YOU_SapServiceLayer_1.host') {
845
+ return 'host';
846
+ }
847
+ if (param == '_YOU_SapServiceLayer_1.port') {
848
+ return 'port';
849
+ }
850
+ if (param == '_YOU_SapServiceLayer_1.version') {
851
+ return 'version';
852
+ }
853
+ if (param == '_YOU_SapServiceLayer_1.headers') {
854
+ return ['header:1', 'header:2'];
855
+ }
856
+ },
857
+ },
858
+ };
859
+ },
860
+ };
861
+
862
+ const msg = {
863
+ _YOU_SapServiceLayer: {
864
+ idAuth: 1,
865
+ },
866
+ entityId: 3,
867
+ };
868
+ let config = {
869
+ sqlCode: 'sqlCode',
870
+ sqlName: 'sqlName',
871
+ sqlText: 'sqlText',
872
+ };
873
+ const options = { method: 'POST', hasRawQuery: false, hasEntityId: false, isCreateSQLQuery: true };
874
+ const expectedValue = {
875
+ axiosOptions: {
876
+ headers: {
877
+ Cookie: 'header:1;header:2',
878
+ },
879
+ method: 'POST',
880
+ rejectUnauthorized: false,
881
+ url: 'https://host:port/b1s/version/SQLQueries',
882
+ withCredentials: true,
883
+ },
884
+ idAuthNode: 1,
885
+ };
886
+
887
+ should.deepEqual(Support.generateRequest(node, msg, config, options), expectedValue);
888
+ });
889
+
890
+ it('should generate a correct request with SQLQuery execute query without params', () => {
891
+ const node = {
892
+ context: () => {
893
+ return {
894
+ flow: {
895
+ get: (param) => {
896
+ if (param == '_YOU_SapServiceLayer_1.host') {
897
+ return 'host';
898
+ }
899
+ if (param == '_YOU_SapServiceLayer_1.port') {
900
+ return 'port';
901
+ }
902
+ if (param == '_YOU_SapServiceLayer_1.version') {
903
+ return 'version';
904
+ }
905
+ if (param == '_YOU_SapServiceLayer_1.headers') {
906
+ return ['header:1', 'header:2'];
907
+ }
908
+ },
909
+ },
910
+ };
911
+ },
912
+ };
913
+
914
+ const msg = {
915
+ _YOU_SapServiceLayer: {
916
+ idAuth: 1,
917
+ },
918
+ entityId: 3,
919
+ sqlCode: 'queryCode',
920
+ };
921
+ let config = {
922
+ sqlCode: 'sqlCode',
923
+ };
924
+ const options = { method: 'POST', hasRawQuery: false, hasEntityId: false, isSQLQuery: true };
925
+ const expectedValue = {
926
+ axiosOptions: {
927
+ headers: {
928
+ Cookie: 'header:1;header:2',
929
+ },
930
+ method: 'POST',
931
+ rejectUnauthorized: false,
932
+ url: `https://host:port/b1s/version/SQLQueries('queryCode')/List`,
933
+ withCredentials: true,
934
+ },
935
+ idAuthNode: 1,
936
+ };
937
+
938
+ should.deepEqual(Support.generateRequest(node, msg, config, options), expectedValue);
939
+ });
940
+
941
+ it('should generate a correct request with SQLQuery execute query with params', () => {
942
+ const node = {
943
+ context: () => {
944
+ return {
945
+ flow: {
946
+ get: (param) => {
947
+ if (param == '_YOU_SapServiceLayer_1.host') {
948
+ return 'host';
949
+ }
950
+ if (param == '_YOU_SapServiceLayer_1.port') {
951
+ return 'port';
952
+ }
953
+ if (param == '_YOU_SapServiceLayer_1.version') {
954
+ return 'version';
955
+ }
956
+ if (param == '_YOU_SapServiceLayer_1.headers') {
957
+ return ['header:1', 'header:2'];
958
+ }
959
+ },
960
+ },
961
+ };
962
+ },
963
+ };
964
+
965
+ const msg = {
966
+ _YOU_SapServiceLayer: {
967
+ idAuth: 1,
968
+ },
969
+ entityId: 3,
970
+ sqlCode: 'queryCode',
971
+ };
972
+ let config = {
973
+ sqlCode: 'sqlCode',
974
+ };
975
+ const options = { method: 'POST', hasRawQuery: false, hasEntityId: false, isSQLQuery: true };
976
+ const expectedValue = {
977
+ axiosOptions: {
978
+ headers: {
979
+ Cookie: 'header:1;header:2',
980
+ },
981
+ method: 'POST',
982
+ rejectUnauthorized: false,
983
+ url: `https://host:port/b1s/version/SQLQueries('queryCode')/List`,
984
+ withCredentials: true,
985
+ },
986
+ idAuthNode: 1,
987
+ };
988
+
989
+ should.deepEqual(Support.generateRequest(node, msg, config, options), expectedValue);
990
+ });
991
+
992
+ it('should generate a correct request with SQLQuery execute query with nextLink', () => {
993
+ const node = {
994
+ context: () => {
995
+ return {
996
+ flow: {
997
+ get: (param) => {
998
+ if (param == '_YOU_SapServiceLayer_1.host') {
999
+ return 'host';
1000
+ }
1001
+ if (param == '_YOU_SapServiceLayer_1.port') {
1002
+ return 'port';
1003
+ }
1004
+ if (param == '_YOU_SapServiceLayer_1.version') {
1005
+ return 'version';
1006
+ }
1007
+ if (param == '_YOU_SapServiceLayer_1.headers') {
1008
+ return ['header:1', 'header:2'];
1009
+ }
1010
+ },
1011
+ },
1012
+ };
1013
+ },
1014
+ };
1015
+
1016
+ const msg = {
1017
+ _YOU_SapServiceLayer: {
1018
+ idAuth: 1,
1019
+ },
1020
+ entityId: 3,
1021
+ sqlCode: 'queryCode',
1022
+ };
1023
+ let config = {
1024
+ sqlCode: 'sqlCode',
1025
+ };
1026
+ const options = { method: 'POST', hasRawQuery: false, hasEntityId: false, isSQLQuery: true };
1027
+ const expectedValue = {
1028
+ axiosOptions: {
1029
+ headers: {
1030
+ Cookie: 'header:1;header:2',
1031
+ },
1032
+ method: 'POST',
1033
+ rejectUnauthorized: false,
1034
+ url: `https://host:port/b1s/version/SQLQueries('queryCode')/List`,
1035
+ withCredentials: true,
1036
+ },
1037
+ idAuthNode: 1,
1038
+ };
1039
+
1040
+ should.deepEqual(Support.generateRequest(node, msg, config, options), expectedValue);
1041
+ });
1042
+
838
1043
  it('should have error missing object', () => {
839
1044
  const node = {
840
1045
  context: () => {