@adobe/acc-js-sdk 1.1.0 → 1.1.3
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/.github/workflows/npm-publish.yml +1 -1
- package/CHANGELOG.md +21 -0
- package/README.md +126 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/samples/utils.js +3 -1
- package/src/client.js +141 -69
- package/src/soap.js +31 -8
- package/test/client.hasPackage.test.js +6 -6
- package/test/client.test.js +384 -3
- package/test/soap.test.js +87 -2
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
node-version: 10.0.0
|
|
17
17
|
- name: Publish if version has been updated
|
|
18
18
|
#uses: pascalgn/npm-publish-action@06e0830ea83eea10ed4a62654eeaedafb8bf50fc
|
|
19
|
-
uses: mkiki/npm-publish-action@
|
|
19
|
+
uses: mkiki/npm-publish-action@52879298d00c0a02781e1f02c9e917e01cff1bc7
|
|
20
20
|
with: # All of theses inputs are optional
|
|
21
21
|
tag_name: "v%s"
|
|
22
22
|
tag_message: "v%s"
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ This is a node.js SDK for Campaign API. It exposes the Campaign API exactly like
|
|
|
5
5
|
|
|
6
6
|
# Changelog
|
|
7
7
|
|
|
8
|
+
## Version 1.1.3
|
|
9
|
+
_2022/05/30_
|
|
10
|
+
|
|
11
|
+
* Fix a bug in client.hasPackage which was returning an incorrect result when passed a single parameter (it would always return false). Fixed the corresponding unit test too.
|
|
12
|
+
* Fix a bug causing API calls having a input parameter of type "int" to fail. Usually the type is described as "long", but sometimes "int" is used instead, such as, for instance, in the nms:extAccount#UpdateMCSynchWkf method.
|
|
13
|
+
* When using XML representations and DOMDocument method parameter type, the SDK expects to be passed an actual DOM document. Now it supports being passed a DOM element too. This is a common case when using the nms:delivery#createFromModel API followed by a xtk:session#Write API call.
|
|
14
|
+
* Avoid the error 'Cannot transform entity to xml because no XML root name was given' by using SOAP method parameter name as the default for XML document root when no other root is available
|
|
15
|
+
* Document how to set the password of an external account
|
|
16
|
+
* By default, SDK will send additional HTTP headers to help troubleshooting and usage tracking
|
|
17
|
+
* Add the ability to pass extra HTTP headers to API calls, either globally (to all HTTP headers), or locally, i.e. for a specific method
|
|
18
|
+
|
|
19
|
+
## Version 1.1.2
|
|
20
|
+
_2022/03/22_
|
|
21
|
+
|
|
22
|
+
* Add support for choosing the representation (XML or JSON) at the method level using NLWS.xml or NLWS.json.
|
|
23
|
+
|
|
24
|
+
## Version 1.1.1
|
|
25
|
+
_2022/03/10_
|
|
26
|
+
|
|
27
|
+
* Fixed an issue with encoding: make the default charset encoding to be UTF-8 (https://github.com/adobe/acc-js-sdk/issues/26)
|
|
28
|
+
|
|
8
29
|
## Version 1.1.0
|
|
9
30
|
_2022/03/05_
|
|
10
31
|
|
package/README.md
CHANGED
|
@@ -129,7 +129,10 @@ transport|axios|Overrides the transport layer
|
|
|
129
129
|
noStorage|false|De-activate using of local storage
|
|
130
130
|
storage|localStorage|Overrides the local storage for caches
|
|
131
131
|
refreshClient|undefined|Async callback to run when the session token is expired
|
|
132
|
-
|
|
132
|
+
charset|UTF-8|The charset encoding used for http requests. In version 1.1.1 and above, the default will be UTF-8. It's possible to override (including setting an empty character set) with this option.
|
|
133
|
+
extraHttpHeaders|[string]:string|An optional dictionary (key/value pairs) of extra HTTP headers to pass to all API calls.
|
|
134
|
+
clientApp|string|An optional string describing the name and version of the SDK client application. It will be passed to the server in the ACC-SDK-Client-App HTTP header
|
|
135
|
+
noSDKHeaders|boolean|Can be set to disable passing ACC-SDK-* HTTP headers to the server
|
|
133
136
|
```js
|
|
134
137
|
const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(
|
|
135
138
|
"https://myInstance.campaign.adobe.com",
|
|
@@ -303,6 +306,15 @@ const queryDef = {
|
|
|
303
306
|
};
|
|
304
307
|
```
|
|
305
308
|
|
|
309
|
+
## Method-level representation
|
|
310
|
+
|
|
311
|
+
The client object is created with a default representation which is used for all API calls in the context of this client. Since version 1.1.2, it is also possible to set the representation at the method level, i.e. use a particular representation for a particular API call.
|
|
312
|
+
|
|
313
|
+
* `client.NLWS`: use the default representation set at the client level
|
|
314
|
+
* `client.NLWS.xml`: use the XML reresentation
|
|
315
|
+
* `client.NLWS.json`: use the SimpleJson representation
|
|
316
|
+
|
|
317
|
+
|
|
306
318
|
## SimpleJson format
|
|
307
319
|
The Simple JSON format works like this:
|
|
308
320
|
|
|
@@ -323,7 +335,7 @@ XML elements are mapped to JSON objects
|
|
|
323
335
|
* XML: `<root><item id=1/></root>`
|
|
324
336
|
* JSON: `{ item: { id:1 } }`
|
|
325
337
|
|
|
326
|
-
If the parent element tag ends with `-
|
|
338
|
+
If the parent element tag ends with `-collection` children are always an array, even if there are no children, or if there is just one child. The rationale is that XML/JSON conversion is ambigous : XML can have multiple elements with the same tag and when there's only one such element, it's not possible to determine if it should be represented as a JSON object or JSON array unless we have additional metadata.
|
|
327
339
|
|
|
328
340
|
* XML: `<root-collection><item id=1/></root>`
|
|
329
341
|
* JSON: `{ item: [ { id:1 } ] }`
|
|
@@ -566,6 +578,49 @@ const document = DomUtil.fromJSON(json, "BadgerFish");
|
|
|
566
578
|
const json = DomUtil.toJSON(documentOrElement, "BadgerFish");
|
|
567
579
|
```
|
|
568
580
|
|
|
581
|
+
## Passing XML parameters
|
|
582
|
+
Many Campaign APIs take arguments which are DOM documents or DOM elements. For example, the nms:delivery#DeployTriggerMessages first argument is a DOMElement which is supposed to be a `<where>` clause used as a condition to select Message Center deliveries to publish.
|
|
583
|
+
|
|
584
|
+
```xml
|
|
585
|
+
<method name="DeployTriggerMessages" static="true">
|
|
586
|
+
<parameters>
|
|
587
|
+
<param inout="in" name="deliveries" type="DOMElement"/>
|
|
588
|
+
<param inout="in" name="localPublish" type="boolean"/>
|
|
589
|
+
</parameters>
|
|
590
|
+
</method>
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
For example, one would want to use the following condition to republish a particular delivery
|
|
594
|
+
|
|
595
|
+
```js
|
|
596
|
+
await client.NLWS.nmsDelivery.DeployTriggerMessages({
|
|
597
|
+
condition: [ {
|
|
598
|
+
expr: "@internalName='DM23'"
|
|
599
|
+
}]
|
|
600
|
+
}, false);
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
The JSON object corresponds to the following XML
|
|
604
|
+
```xml
|
|
605
|
+
<where>
|
|
606
|
+
<condition expr="@internalName='DM23'"/>
|
|
607
|
+
</where>
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Note that in XML, unlike JSON, the root element `<where>` is explicitely named "where". When converting JSON to XML, there is no way for the SDK to know which tag name to used for the root XML element. The SDK contains some code to set it for the most common situation, but will rely on the user to specify, when necessary, the name of the root elment. This can be done using the `xtkschema` (all case insensitive) attribute as follows:
|
|
611
|
+
```js
|
|
612
|
+
await client.NLWS.nmsDelivery.DeployTriggerMessages({
|
|
613
|
+
xtkschema: 'xtk:where',
|
|
614
|
+
condition: [ {
|
|
615
|
+
expr: "@internalName='DM23'"
|
|
616
|
+
}]
|
|
617
|
+
}, false);
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
When the `xtkschema` attribute is set, the part after the colon (i.e. "where" in this example) will be used as the root element, effectively generating the right XML.
|
|
621
|
+
|
|
622
|
+
In our example, the `DeployTriggerMessages` will work properly regardless of the XML root of its `deliveries` parameter, so it's not needed to actually set the `xtkschema` attribute, but it's a best practice to do so, because some APIs will actually depend on receiving the right tag name.
|
|
623
|
+
|
|
569
624
|
## Error Management
|
|
570
625
|
|
|
571
626
|
If an API call fails (SOAP fault or HTTP error), a `CampaignException` object is thrown. This object contains the following attributes
|
|
@@ -644,6 +699,64 @@ const password = cipher.decryptPassword(encryptedPassword);
|
|
|
644
699
|
|
|
645
700
|
> **warning** This function is deprecated in version 1.0.0 of the SDK because it may break as we deploy Vault.
|
|
646
701
|
|
|
702
|
+
In order to set the password of an external account, you can use the `encryptPassword` API as follow
|
|
703
|
+
|
|
704
|
+
```js
|
|
705
|
+
const password = await this._client.NLWS.xtkSession.encryptPassword('password');
|
|
706
|
+
const account = {
|
|
707
|
+
xtkschema: "nms:extAccount",
|
|
708
|
+
name: name,
|
|
709
|
+
account: 'admin',
|
|
710
|
+
server: server,
|
|
711
|
+
password: password,
|
|
712
|
+
};
|
|
713
|
+
await this._client.NLWS.xtkSession.Write(account);
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
## HTTP Headers
|
|
718
|
+
|
|
719
|
+
### Out-of-the-box headers
|
|
720
|
+
In version 1.1.3 and above, the SDK will pass additional HTTP headers automatically
|
|
721
|
+
|
|
722
|
+
Header | Description
|
|
723
|
+
-------|------------
|
|
724
|
+
SOAPAction| name of the schema and SOAP method (ex: xtk:query#ExecuteQuery)
|
|
725
|
+
ACC-SDK-Version| Version of the SDK making the scores
|
|
726
|
+
ACC-SDK-Auth| Authentification type and ACC user
|
|
727
|
+
ACC-SDK-Client-App| Name of the application calling the client SDK
|
|
728
|
+
ACC-SDK-Call-RetryCount| In case an API call is retried, indicates the number of retries
|
|
729
|
+
ACC-SDK-Call-Internal| Indicates that an API call is performed byt the SDK for its own purpose
|
|
730
|
+
|
|
731
|
+
The `ACC-SDK` headers can be removed using the connection parameter `noSDKHeaders`.
|
|
732
|
+
|
|
733
|
+
### Custom HTTP headers
|
|
734
|
+
In version 1.1.3 and above, it is possible to pass additional HTTP headers or override HTTP headers set by the SDK. This can be done globally (i.e. for all API calls), or locally, i.e. just for a particular call, or both.
|
|
735
|
+
|
|
736
|
+
Http headers are passed through an object whose keys represent the header name and values the corresponding header value. Nothing particular is done in term of case sensitivity, headers will be passed as passed.
|
|
737
|
+
|
|
738
|
+
To set global HTTP headers for all API calls of a client, pass an http headers array in the connection parameters
|
|
739
|
+
```js
|
|
740
|
+
const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(
|
|
741
|
+
"https://myInstance.campaign.adobe.com",
|
|
742
|
+
"admin", "admin",
|
|
743
|
+
{ extraHttpHeaders: {
|
|
744
|
+
"X-ACC-JS-SDK-LBSAFE": "1",
|
|
745
|
+
"X-ACC-WEBUI-VERSION: "1.2"
|
|
746
|
+
} });
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
Subsequent API calls will have the corresponding headers set.
|
|
750
|
+
|
|
751
|
+
To set more HTTP headers for a particular API call, use the "headers" method of the NLWS object.
|
|
752
|
+
|
|
753
|
+
```js
|
|
754
|
+
const query = client.NLWS
|
|
755
|
+
.headers({'X-Test': 'hello'})
|
|
756
|
+
.xtkQueryDef.create(queryDef);
|
|
757
|
+
await query.executeQuery();
|
|
758
|
+
```
|
|
759
|
+
|
|
647
760
|
|
|
648
761
|
|
|
649
762
|
# Samples
|
|
@@ -1134,6 +1247,17 @@ const folder = {
|
|
|
1134
1247
|
await NLWS.xtkSession.write(folder);
|
|
1135
1248
|
````
|
|
1136
1249
|
|
|
1250
|
+
Some objects, such as deliveries are created from templates. The `createFromModel` API is preferred in this case. Given a template name, and a patch object, it will return an object created from the template and the patch, applying all sort of business rules and default values. This object can be inserted using a writer.
|
|
1251
|
+
|
|
1252
|
+
In this example, an email delivery is created from the "mail" delivery template and it's label is set to "Hello".
|
|
1253
|
+
|
|
1254
|
+
Note the xtkschema attribute in the second parameter of the `createFromModel` API call which is needed for the SDK to perform the proper JSON to XML transformation.
|
|
1255
|
+
|
|
1256
|
+
```js
|
|
1257
|
+
const mail = await client.NLWS.nmsDelivery.createFromModel('mail', { xtkschema:'nms:delivery', label:'Hello'});
|
|
1258
|
+
await client.NLWS.xtkSession.write(mail);
|
|
1259
|
+
````
|
|
1260
|
+
|
|
1137
1261
|
# Workflow API
|
|
1138
1262
|
|
|
1139
1263
|
Start and stop wotkflows, passing either an id or workflow internal name
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/acc-js-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@adobe/acc-js-sdk",
|
|
9
|
-
"version": "1.1.
|
|
9
|
+
"version": "1.1.3",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"axios": "^0.25.0",
|
package/package.json
CHANGED
package/samples/utils.js
CHANGED
|
@@ -47,7 +47,9 @@ async function run(main) {
|
|
|
47
47
|
*/
|
|
48
48
|
async function logon(callback) {
|
|
49
49
|
var main = async () => {
|
|
50
|
-
const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(url, user, password
|
|
50
|
+
const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(url, user, password, {
|
|
51
|
+
clientApp: 'acc-js-sdk sample'
|
|
52
|
+
});
|
|
51
53
|
const client = await sdk.init(connectionParameters);
|
|
52
54
|
const NLWS = client.NLWS;
|
|
53
55
|
|
package/src/client.js
CHANGED
|
@@ -96,65 +96,96 @@ const xtkObjectHandler = {
|
|
|
96
96
|
* <code>
|
|
97
97
|
* result = await client.NLWS.xtkSession.getServerTime();
|
|
98
98
|
* </code>
|
|
99
|
+
*
|
|
100
|
+
* To get a handler, call the `clientHandler` function and optionally pass a representation.
|
|
101
|
+
* If no representation is passed (undefined), the representation set at the client level
|
|
102
|
+
* will be used, which is the default behavior.
|
|
103
|
+
* To get a proxy with a specific representation, use NLWS.xml or NMWS.json
|
|
99
104
|
*
|
|
100
105
|
* @private
|
|
101
106
|
* @memberof Campaign
|
|
102
107
|
*/
|
|
103
|
-
const clientHandler = {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
const clientHandler = (representation, headers) => {
|
|
109
|
+
return {
|
|
110
|
+
get: function(client, namespace) {
|
|
111
|
+
|
|
112
|
+
// Force XML or JSON representation (NLWS.xml or NLWS.json)
|
|
113
|
+
if (namespace == "xml") return new Proxy(client, clientHandler("xml", headers));
|
|
114
|
+
if (namespace == "json") return new Proxy(client, clientHandler("SimpleJson", headers));
|
|
115
|
+
|
|
116
|
+
// Override HTTP headers (NLWS.headers({...}))
|
|
117
|
+
// Unlike NLWS.xml or NLWS.json, NLWS.headers returns a function. This function takes key/value
|
|
118
|
+
// pairs of headers, and, when called, returns a proxy object which will remember the headers
|
|
119
|
+
// and be able to pass them to subsequent SOAP call context
|
|
120
|
+
if (namespace == "headers") return (methodHeaders) => {
|
|
121
|
+
// Build of copy of the http headers and append new headers in order to accomodate
|
|
122
|
+
// chained calls, such as NLWS.headers(...).headers(...)
|
|
123
|
+
const newHeaders = {};
|
|
124
|
+
if (headers) for (let h in headers) newHeaders[h] = headers[h];
|
|
125
|
+
if (methodHeaders) for (let h in methodHeaders) newHeaders[h] = methodHeaders[h];
|
|
126
|
+
return new Proxy(client, clientHandler(representation, newHeaders));
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return new Proxy({ client:client, namespace:namespace}, {
|
|
130
|
+
get: function(callContext, methodName) {
|
|
131
|
+
callContext.representation = representation;
|
|
132
|
+
callContext.headers = callContext.headers || client._connectionParameters._options.extraHttpHeaders;
|
|
133
|
+
if (headers) {
|
|
134
|
+
for (let h in headers) callContext.headers[h] = headers[h];
|
|
116
135
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return callContext.client.logoff();
|
|
130
|
-
else if (namespace == "xtkSession" && methodNameLC == "getoption") {
|
|
131
|
-
var promise = callContext.client._callMethod(methodName, callContext, argumentsList);
|
|
132
|
-
return promise.then(function(optionAndValue) {
|
|
133
|
-
const optionName = argumentsList[0];
|
|
134
|
-
client._optionCache.put(optionName, optionAndValue);
|
|
135
|
-
return optionAndValue;
|
|
136
|
-
});
|
|
136
|
+
|
|
137
|
+
if (methodName == ".") return callContext;
|
|
138
|
+
|
|
139
|
+
// get Schema id from namespace (find first upper case letter)
|
|
140
|
+
var schemaId = "";
|
|
141
|
+
for (var i=0; i<namespace.length; i++) {
|
|
142
|
+
const c = namespace[i];
|
|
143
|
+
if (c >='A' && c<='Z') {
|
|
144
|
+
schemaId = schemaId + ":" + c.toLowerCase() + namespace.substr(i+1);
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
schemaId = schemaId + c;
|
|
137
148
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
149
|
+
callContext.schemaId = schemaId;
|
|
150
|
+
|
|
151
|
+
const caller = function(thisArg, argumentsList) {
|
|
152
|
+
const callContext = thisArg["."];
|
|
153
|
+
const namespace = callContext.namespace;
|
|
154
|
+
const methodNameLC = methodName.toLowerCase();
|
|
155
|
+
methodName = methodName.substr(0, 1).toUpperCase() + methodName.substr(1);
|
|
156
|
+
if (namespace == "xtkSession" && methodNameLC == "logon")
|
|
157
|
+
return callContext.client.logon(argumentsList[0]);
|
|
158
|
+
else if (namespace == "xtkSession" && methodNameLC == "logoff")
|
|
159
|
+
return callContext.client.logoff();
|
|
160
|
+
else if (namespace == "xtkSession" && methodNameLC == "getoption") {
|
|
161
|
+
var promise = callContext.client._callMethod(methodName, callContext, argumentsList);
|
|
162
|
+
return promise.then(function(optionAndValue) {
|
|
163
|
+
const optionName = argumentsList[0];
|
|
164
|
+
client._optionCache.put(optionName, optionAndValue);
|
|
165
|
+
return optionAndValue;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// static method
|
|
169
|
+
var result = callContext.client._callMethod(methodName, callContext, argumentsList);
|
|
170
|
+
return result;
|
|
147
171
|
};
|
|
148
|
-
}
|
|
149
172
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
if (methodName == "create") {
|
|
174
|
+
return function(body) {
|
|
175
|
+
callContext.object = body;
|
|
176
|
+
return new Proxy(callContext, xtkObjectHandler);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return new Proxy(caller, {
|
|
181
|
+
apply: function(target, thisArg, argumentsList) {
|
|
182
|
+
return target(thisArg, argumentsList);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
};
|
|
158
189
|
};
|
|
159
190
|
|
|
160
191
|
// ========================================================================================
|
|
@@ -234,6 +265,11 @@ class Credentials {
|
|
|
234
265
|
* @property {Utils.Transport} transport - Overrides the transport (i.e. HTTP layer)
|
|
235
266
|
* @property {boolean} noStorage - De-activate using of local storage. By default, and in addition to in-memory cache, entities, methods, and options are also persisted in local storage if there is one.
|
|
236
267
|
* @property {Storage} storage - Overrides the storage interface (i.e. LocalStorage)
|
|
268
|
+
* @property {function} refreshClient - An async callback function with the SDK client as parameter, which will be called when the ACC session is expired
|
|
269
|
+
* @property {string} charset - The charset encoding used for http requests. Defaults to UTF-8 since SDK version 1.1.1
|
|
270
|
+
* @property {{ name:string, value:string}} extraHttpHeaders - optional key/value pair of HTTP header (will override any other headers)
|
|
271
|
+
* @property {string} clientApp - optional name/version of the application client of the SDK. This will be passed in HTTP headers for troubleshooting
|
|
272
|
+
* @property {boolean} noSDKHeaders - set to disable "ACC-SDK" HTTP headers
|
|
237
273
|
* @memberOf Campaign
|
|
238
274
|
*/
|
|
239
275
|
|
|
@@ -297,6 +333,13 @@ class ConnectionParameters {
|
|
|
297
333
|
}
|
|
298
334
|
this._options._storage = storage;
|
|
299
335
|
this._options.refreshClient = options.refreshClient;
|
|
336
|
+
this._options.charset = options.charset === undefined ? "UTF-8": options.charset;
|
|
337
|
+
this._options.extraHttpHeaders = {};
|
|
338
|
+
if (options.extraHttpHeaders) {
|
|
339
|
+
for (let h in options.extraHttpHeaders) this._options.extraHttpHeaders[h] = options.extraHttpHeaders[h];
|
|
340
|
+
}
|
|
341
|
+
this._options.clientApp = options.clientApp;
|
|
342
|
+
this._options.noSDKHeaders = !!options.noSDKHeaders;
|
|
300
343
|
}
|
|
301
344
|
|
|
302
345
|
/**
|
|
@@ -474,7 +517,7 @@ class Client {
|
|
|
474
517
|
this._entityCache = new XtkEntityCache(this._storage, `${rootKey}.XtkEntityCache`, connectionParameters._options.entityCacheTTL);
|
|
475
518
|
this._methodCache = new MethodCache(this._storage, `${rootKey}.MethodCache`, connectionParameters._options.methodCacheTTL);
|
|
476
519
|
this._optionCache = new OptionCache(this._storage, `${rootKey}.OptionCache`, connectionParameters._options.optionCacheTTL);
|
|
477
|
-
this.NLWS = new Proxy(this, clientHandler);
|
|
520
|
+
this.NLWS = new Proxy(this, clientHandler());
|
|
478
521
|
|
|
479
522
|
this._transport = connectionParameters._options.transport;
|
|
480
523
|
this._traceAPICalls = connectionParameters._options.traceAPICalls;
|
|
@@ -669,11 +712,15 @@ class Client {
|
|
|
669
712
|
* @private
|
|
670
713
|
* @param {string} urn is the API name space, usually the schema. For instance xtk:session
|
|
671
714
|
* @param {string} method is the method to call, for instance Logon
|
|
715
|
+
* @param {boolean} internal is a boolean indicating whether the SOAP call is performed by the SDK (internal = true) or on behalf of a user
|
|
672
716
|
* @return {SOAP.SoapMethodCall} a SoapMethodCall which have been initialized with security tokens... and to which the method
|
|
673
717
|
* parameters should be set
|
|
674
718
|
*/
|
|
675
|
-
_prepareSoapCall(urn, method, internal) {
|
|
676
|
-
const soapCall = new SoapMethodCall(this._transport, urn, method,
|
|
719
|
+
_prepareSoapCall(urn, method, internal, extraHttpHeaders) {
|
|
720
|
+
const soapCall = new SoapMethodCall(this._transport, urn, method,
|
|
721
|
+
this._sessionToken, this._securityToken,
|
|
722
|
+
this._getUserAgentString(), this._connectionParameters._options.charset,
|
|
723
|
+
extraHttpHeaders);
|
|
677
724
|
soapCall.internal = !!internal;
|
|
678
725
|
return soapCall;
|
|
679
726
|
}
|
|
@@ -687,6 +734,7 @@ class Client {
|
|
|
687
734
|
*/
|
|
688
735
|
async _retrySoapCall(soapCall) {
|
|
689
736
|
soapCall.retry = false;
|
|
737
|
+
soapCall._retryCount = soapCall._retryCount + 1;
|
|
690
738
|
var newClient = await this._refreshClient(this);
|
|
691
739
|
soapCall.finalize(newClient._soapEndPoint(), newClient);
|
|
692
740
|
if (this._traceAPICalls) {
|
|
@@ -761,6 +809,18 @@ class Client {
|
|
|
761
809
|
this._securityToken = "";
|
|
762
810
|
const credentials = this._connectionParameters._credentials;
|
|
763
811
|
|
|
812
|
+
const sdkVersion = this.sdk.getSDKVersion();
|
|
813
|
+
const version = `${sdkVersion.name} ${sdkVersion.version}`;
|
|
814
|
+
const clientApp = this._connectionParameters._options.clientApp;
|
|
815
|
+
if (!this._connectionParameters._options.noSDKHeaders) {
|
|
816
|
+
this._connectionParameters._options.extraHttpHeaders["ACC-SDK-Version"] = version;
|
|
817
|
+
this._connectionParameters._options.extraHttpHeaders["ACC-SDK-Auth"] = `${credentials._type}`;
|
|
818
|
+
if (clientApp)
|
|
819
|
+
this._connectionParameters._options.extraHttpHeaders["ACC-SDK-Client-App"] = clientApp;
|
|
820
|
+
}
|
|
821
|
+
// See NEO-35259
|
|
822
|
+
this._connectionParameters._options.extraHttpHeaders['X-Query-Source'] = `${version}${clientApp? "," + clientApp : ""}`;
|
|
823
|
+
|
|
764
824
|
// Clear session token cookie to ensure we're not inheriting an expired cookie. See NEO-26589
|
|
765
825
|
if (credentials._type != "SecurityToken" && typeof document != "undefined") {
|
|
766
826
|
document.cookie = '__sessiontoken=;path=/;';
|
|
@@ -773,8 +833,8 @@ class Client {
|
|
|
773
833
|
that.application = new Application(that);
|
|
774
834
|
return Promise.resolve();
|
|
775
835
|
}
|
|
776
|
-
else if (credentials._type == "SecurityToken") {
|
|
777
|
-
|
|
836
|
+
else if (credentials._type == "SecurityToken") {
|
|
837
|
+
that._sessionInfo = undefined;
|
|
778
838
|
that._installedPackages = {};
|
|
779
839
|
that._sessionToken = "";
|
|
780
840
|
that._securityToken = credentials._securityToken;
|
|
@@ -782,12 +842,14 @@ class Client {
|
|
|
782
842
|
return Promise.resolve();
|
|
783
843
|
}
|
|
784
844
|
else if (credentials._type == "UserPassword" || credentials._type == "BearerToken") {
|
|
785
|
-
const soapCall = that._prepareSoapCall("xtk:session", credentials._type === "UserPassword" ? "Logon" : "BearerTokenLogon");
|
|
845
|
+
const soapCall = that._prepareSoapCall("xtk:session", credentials._type === "UserPassword" ? "Logon" : "BearerTokenLogon", false, this._connectionParameters._options.extraHttpHeaders);
|
|
786
846
|
// No retry for logon SOAP methods
|
|
787
847
|
soapCall.retry = false;
|
|
788
848
|
if (credentials._type == "UserPassword") {
|
|
789
849
|
const user = credentials._getUser();
|
|
790
850
|
const password = credentials._getPassword();
|
|
851
|
+
if (!this._connectionParameters._options.noSDKHeaders)
|
|
852
|
+
this._connectionParameters._options.extraHttpHeaders["ACC-SDK-Auth"] = `${credentials._type} ${user}`;
|
|
791
853
|
soapCall.writeString("login", user);
|
|
792
854
|
soapCall.writeString("password", password);
|
|
793
855
|
var parameters = null;
|
|
@@ -855,7 +917,7 @@ class Client {
|
|
|
855
917
|
if (!that.isLogged()) return;
|
|
856
918
|
const credentials = this._connectionParameters._credentials;
|
|
857
919
|
if (credentials._type != "SessionToken" && credentials._type != "AnonymousUser") {
|
|
858
|
-
var soapCall = that._prepareSoapCall("xtk:session", "Logoff");
|
|
920
|
+
var soapCall = that._prepareSoapCall("xtk:session", "Logoff", false, this._connectionParameters._options.extraHttpHeaders);
|
|
859
921
|
return this._makeSoapCall(soapCall).then(function() {
|
|
860
922
|
that._sessionToken = "";
|
|
861
923
|
that._securityToken = "";
|
|
@@ -960,7 +1022,7 @@ class Client {
|
|
|
960
1022
|
* @returns {boolean} a boolean indicating if the package is installed or not
|
|
961
1023
|
*/
|
|
962
1024
|
hasPackage(packageId, optionalName) {
|
|
963
|
-
if (optionalName
|
|
1025
|
+
if (optionalName !== undefined)
|
|
964
1026
|
packageId = `${packageId}:${optionalName}`;
|
|
965
1027
|
if (!this.isLogged())
|
|
966
1028
|
throw CampaignException.NOT_LOGGED_IN(undefined, `Cannot call hasPackage: session not connected`);
|
|
@@ -974,7 +1036,7 @@ class Client {
|
|
|
974
1036
|
* @private
|
|
975
1037
|
* @deprecated since version 1.0.0
|
|
976
1038
|
*/
|
|
977
|
-
|
|
1039
|
+
async _getSecretKeyCipher() {
|
|
978
1040
|
var that = this;
|
|
979
1041
|
if (this._secretKeyCipher) return this._secretKeyCipher;
|
|
980
1042
|
return that.getOption("XtkSecretKey").then(function(secretKey) {
|
|
@@ -997,7 +1059,7 @@ class Client {
|
|
|
997
1059
|
*/
|
|
998
1060
|
async getEntityIfMoreRecent(entityType, fullName, representation, internal) {
|
|
999
1061
|
const that = this;
|
|
1000
|
-
const soapCall = this._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", internal);
|
|
1062
|
+
const soapCall = this._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", internal, this._connectionParameters._options.extraHttpHeaders);
|
|
1001
1063
|
soapCall.writeString("pk", entityType + "|" + fullName);
|
|
1002
1064
|
soapCall.writeString("md5", "");
|
|
1003
1065
|
soapCall.writeBoolean("mustExist", false);
|
|
@@ -1100,7 +1162,7 @@ class Client {
|
|
|
1100
1162
|
// console.log(method.toXMLString());
|
|
1101
1163
|
|
|
1102
1164
|
var urn = that._methodCache.getSoapUrn(schemaId, methodName);
|
|
1103
|
-
var soapCall = that._prepareSoapCall(urn, methodName);
|
|
1165
|
+
var soapCall = that._prepareSoapCall(urn, methodName, false, callContext.headers);
|
|
1104
1166
|
|
|
1105
1167
|
// If method is called with one parameter which is a function, then we assume it's a hook: the function will return
|
|
1106
1168
|
// the actual list of parameters
|
|
@@ -1117,7 +1179,7 @@ class Client {
|
|
|
1117
1179
|
throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Cannot call non-static method '${methodName}' of schema '${schemaId}' : no object was specified`);
|
|
1118
1180
|
|
|
1119
1181
|
const rootName = schemaId.substr(schemaId.indexOf(':') + 1);
|
|
1120
|
-
object = that._fromRepresentation(rootName, object);
|
|
1182
|
+
object = that._fromRepresentation(rootName, object, callContext.representation);
|
|
1121
1183
|
soapCall.writeDocument("document", object);
|
|
1122
1184
|
}
|
|
1123
1185
|
|
|
@@ -1141,6 +1203,8 @@ class Client {
|
|
|
1141
1203
|
soapCall.writeByte(paramName, XtkCaster.asByte(paramValue));
|
|
1142
1204
|
else if (type == "short")
|
|
1143
1205
|
soapCall.writeShort(paramName, XtkCaster.asShort(paramValue));
|
|
1206
|
+
else if (type == "int")
|
|
1207
|
+
soapCall.writeLong(paramName, XtkCaster.asLong(paramValue));
|
|
1144
1208
|
else if (type == "long")
|
|
1145
1209
|
soapCall.writeLong(paramName, XtkCaster.asLong(paramValue));
|
|
1146
1210
|
else if (type == "int64")
|
|
@@ -1165,7 +1229,8 @@ class Client {
|
|
|
1165
1229
|
const index = xtkschema.indexOf(":");
|
|
1166
1230
|
docName = xtkschema.substr(index+1);
|
|
1167
1231
|
}
|
|
1168
|
-
|
|
1232
|
+
if (!docName) docName = paramName; // Use te parameter name as the XML root element
|
|
1233
|
+
var xmlValue = that._fromRepresentation(docName, paramValue, callContext.representation);
|
|
1169
1234
|
if (type == "DOMDocument")
|
|
1170
1235
|
soapCall.writeDocument(paramName, xmlValue);
|
|
1171
1236
|
else
|
|
@@ -1184,7 +1249,7 @@ class Client {
|
|
|
1184
1249
|
// the method is called. This is the new version of the object (in XML form)
|
|
1185
1250
|
const entity = soapCall.getEntity();
|
|
1186
1251
|
if (entity) {
|
|
1187
|
-
callContext.object = that._toRepresentation(entity);
|
|
1252
|
+
callContext.object = that._toRepresentation(entity, callContext.representation);
|
|
1188
1253
|
}
|
|
1189
1254
|
}
|
|
1190
1255
|
|
|
@@ -1215,7 +1280,7 @@ class Client {
|
|
|
1215
1280
|
returnValue = soapCall.getNextDate();
|
|
1216
1281
|
else if (type == "DOMDocument") {
|
|
1217
1282
|
returnValue = soapCall.getNextDocument();
|
|
1218
|
-
returnValue = that._toRepresentation(returnValue);
|
|
1283
|
+
returnValue = that._toRepresentation(returnValue, callContext.representation);
|
|
1219
1284
|
if (schemaId === "xtk:queryDef" && methodName === "ExecuteQuery" && paramName === "output") {
|
|
1220
1285
|
// https://github.com/adobe/acc-js-sdk/issues/3
|
|
1221
1286
|
// Check if query operation is "getIfExists". The "object" variable at this point
|
|
@@ -1235,7 +1300,7 @@ class Client {
|
|
|
1235
1300
|
}
|
|
1236
1301
|
else if (type == "DOMElement") {
|
|
1237
1302
|
returnValue = soapCall.getNextElement();
|
|
1238
|
-
returnValue = that._toRepresentation(returnValue);
|
|
1303
|
+
returnValue = that._toRepresentation(returnValue, callContext.representation);
|
|
1239
1304
|
}
|
|
1240
1305
|
else {
|
|
1241
1306
|
// type can reference a schema element. The naming convension is that the type name
|
|
@@ -1249,7 +1314,7 @@ class Client {
|
|
|
1249
1314
|
if (element.getAttribute("name") == shortTypeName) {
|
|
1250
1315
|
// Type found in schema: Process as a DOM element
|
|
1251
1316
|
returnValue = soapCall.getNextElement();
|
|
1252
|
-
returnValue = that._toRepresentation(returnValue);
|
|
1317
|
+
returnValue = that._toRepresentation(returnValue, callContext.representation);
|
|
1253
1318
|
break;
|
|
1254
1319
|
}
|
|
1255
1320
|
element = DomUtil.getNextSiblingElement(element, "element");
|
|
@@ -1304,8 +1369,11 @@ class Client {
|
|
|
1304
1369
|
*/
|
|
1305
1370
|
async test() {
|
|
1306
1371
|
const request = {
|
|
1307
|
-
url: `${this._connectionParameters._endpoint}/r/test
|
|
1372
|
+
url: `${this._connectionParameters._endpoint}/r/test`,
|
|
1373
|
+
headers: {}
|
|
1308
1374
|
};
|
|
1375
|
+
for (let h in this._connectionParameters._options.extraHttpHeaders)
|
|
1376
|
+
request.headers[h] = this._connectionParameters._options.extraHttpHeaders[h];
|
|
1309
1377
|
const body = await this._makeHttpCall(request);
|
|
1310
1378
|
const xml = DomUtil.parse(body);
|
|
1311
1379
|
const result = this._toRepresentation(xml);
|
|
@@ -1325,6 +1393,8 @@ class Client {
|
|
|
1325
1393
|
'Cookie': '__sessiontoken=' + this._sessionToken
|
|
1326
1394
|
}
|
|
1327
1395
|
};
|
|
1396
|
+
for (let h in this._connectionParameters._options.extraHttpHeaders)
|
|
1397
|
+
request.headers[h] = this._connectionParameters._options.extraHttpHeaders[h];
|
|
1328
1398
|
const body = await this._makeHttpCall(request);
|
|
1329
1399
|
const lines = body.split('\n');
|
|
1330
1400
|
const doc = DomUtil.newDocument("ping");
|
|
@@ -1354,6 +1424,8 @@ class Client {
|
|
|
1354
1424
|
'Cookie': '__sessiontoken=' + this._sessionToken
|
|
1355
1425
|
}
|
|
1356
1426
|
};
|
|
1427
|
+
for (let h in this._connectionParameters._options.extraHttpHeaders)
|
|
1428
|
+
request.headers[h] = this._connectionParameters._options.extraHttpHeaders[h];
|
|
1357
1429
|
const body = await this._makeHttpCall(request);
|
|
1358
1430
|
const lines = body.split('\n');
|
|
1359
1431
|
const doc = DomUtil.newDocument("ping");
|
package/src/soap.js
CHANGED
|
@@ -78,11 +78,13 @@ const NS_XSD = "http://www.w3.org/2001/XMLSchema";
|
|
|
78
78
|
* @param {string} sessionToken Campaign session token
|
|
79
79
|
* @param {string} securityToken Campaign security token
|
|
80
80
|
* @param {string} userAgentString The user agent string to use for HTTP requests
|
|
81
|
+
* @param {string} charset The charset encoding used for http requests, usually UTF-8
|
|
82
|
+
* @param {{ name:string, value:string}} extraHttpHeaders key/value pair of HTTP header (will override any other headers)
|
|
81
83
|
* @memberof SOAP
|
|
82
84
|
*/
|
|
83
85
|
class SoapMethodCall {
|
|
84
86
|
|
|
85
|
-
constructor(transport, urn, methodName, sessionToken, securityToken, userAgentString) {
|
|
87
|
+
constructor(transport, urn, methodName, sessionToken, securityToken, userAgentString, charset, extraHttpHeaders) {
|
|
86
88
|
this.request = undefined; // The HTTP request (object litteral passed to the transport layer)
|
|
87
89
|
this.response = undefined; // The HTTP response object (in case of success)
|
|
88
90
|
|
|
@@ -95,10 +97,13 @@ class SoapMethodCall {
|
|
|
95
97
|
this.internal = false;
|
|
96
98
|
// Enable soap retry
|
|
97
99
|
this.retry = true;
|
|
100
|
+
this._retryCount = 0;
|
|
98
101
|
|
|
99
102
|
this._sessionToken = sessionToken || "";
|
|
100
103
|
this._securityToken = securityToken || "";
|
|
101
104
|
this._userAgentString = userAgentString;
|
|
105
|
+
this._charset = charset || "";
|
|
106
|
+
this._extraHttpHeaders = extraHttpHeaders || {};
|
|
102
107
|
|
|
103
108
|
// THe SOAP call being built
|
|
104
109
|
this._doc = undefined; // XML document for SOAP call
|
|
@@ -211,7 +216,7 @@ class SoapMethodCall {
|
|
|
211
216
|
* @param {string} tag the parameter name
|
|
212
217
|
* @param {*} value the parameter value, which will be casted to a int32 according to xtk rules
|
|
213
218
|
*/
|
|
214
|
-
|
|
219
|
+
writeLong(tag, value) {
|
|
215
220
|
value = XtkCaster.asLong(value);
|
|
216
221
|
this._addNode(tag, "xsd:int", XtkCaster.asString(value), SOAP_ENCODING_NATIVE);
|
|
217
222
|
}
|
|
@@ -297,7 +302,8 @@ class SoapMethodCall {
|
|
|
297
302
|
writeDocument(tag, document) {
|
|
298
303
|
const node = this._addNode(tag, "", null, SOAP_ENCODING_XML);
|
|
299
304
|
if (document !== null && document !== undefined) {
|
|
300
|
-
const
|
|
305
|
+
const element = document.nodeType === 1 ? document : document.documentElement;
|
|
306
|
+
const child = this._doc.importNode(element, true);
|
|
301
307
|
node.appendChild(child);
|
|
302
308
|
}
|
|
303
309
|
}
|
|
@@ -512,20 +518,37 @@ class SoapMethodCall {
|
|
|
512
518
|
* @returns {Object} an options object describing the HTTP request, with cookies, headers and body
|
|
513
519
|
*/
|
|
514
520
|
_createHTTPRequest(url) {
|
|
521
|
+
|
|
522
|
+
const headers = {
|
|
523
|
+
'Content-type': `application/soap+xml${this._charset ? ";charset=" + this._charset : ""}`,
|
|
524
|
+
'SoapAction': `${this.urn}#${this.methodName}`,
|
|
525
|
+
'X-Security-Token': this._securityToken
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
// Add HTTP headers specific to the SOAP call for better tracing/troubleshooting
|
|
529
|
+
if (this._extraHttpHeaders && this._extraHttpHeaders['ACC-SDK-Version']) {
|
|
530
|
+
// "this.retry" means that the call can be retried, not that it is being retried. The HTTP header howerver, indicates that this
|
|
531
|
+
// is actually a retry of a previously failed call (expired token)
|
|
532
|
+
if (this._retryCount > 0) headers["ACC-SDK-Call-RetryCount"] = `${this._retryCount}`;
|
|
533
|
+
if (this.internal) headers["ACC-SDK-Call-Internal"] = "1";
|
|
534
|
+
}
|
|
535
|
+
|
|
515
536
|
const options = {
|
|
516
537
|
url: url,
|
|
517
538
|
method: 'POST',
|
|
518
|
-
headers:
|
|
519
|
-
'Content-type': 'application/soap+xml',
|
|
520
|
-
'SoapAction': `${this.urn}#${this.methodName}`,
|
|
521
|
-
'X-Security-Token': this._securityToken
|
|
522
|
-
},
|
|
539
|
+
headers: headers,
|
|
523
540
|
data: DomUtil.toXMLString(this._doc)
|
|
524
541
|
};
|
|
525
542
|
if (this._sessionToken)
|
|
526
543
|
options.headers.Cookie = '__sessiontoken=' + this._sessionToken;
|
|
527
544
|
if (this._userAgentString)
|
|
528
545
|
options.headers['User-Agent'] = this._userAgentString;
|
|
546
|
+
|
|
547
|
+
// Override http headers with custom headers
|
|
548
|
+
for (let h in this._extraHttpHeaders) {
|
|
549
|
+
options.headers[h] = this._extraHttpHeaders[h];
|
|
550
|
+
}
|
|
551
|
+
|
|
529
552
|
return options;
|
|
530
553
|
}
|
|
531
554
|
|
|
@@ -56,12 +56,12 @@ describe('ACC Client (has package)', () => {
|
|
|
56
56
|
client._transport.mockReturnValueOnce(LOGON_RESPONSE);
|
|
57
57
|
await client.NLWS.xtkSession.logon();
|
|
58
58
|
|
|
59
|
-
expect(client.hasPackage("nms:campaign"));
|
|
60
|
-
expect(client.hasPackage("nms", "campaign"));
|
|
61
|
-
expect(
|
|
62
|
-
expect(
|
|
63
|
-
expect(client.hasPackage("nms:core"));
|
|
64
|
-
expect(client.hasPackage("nms", "core"));
|
|
59
|
+
expect(client.hasPackage("nms:campaign")).toBeTruthy();
|
|
60
|
+
expect(client.hasPackage("nms", "campaign")).toBeTruthy();
|
|
61
|
+
expect(client.hasPackage("nms:mrm")).toBeFalsy();
|
|
62
|
+
expect(client.hasPackage("nms", "mrm")).toBeFalsy();
|
|
63
|
+
expect(client.hasPackage("nms:core")).toBeTruthy();
|
|
64
|
+
expect(client.hasPackage("nms", "core")).toBeTruthy();
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
it('should fail when unlogged', async () => {
|
package/test/client.test.js
CHANGED
|
@@ -2283,15 +2283,15 @@ describe('ACC Client', function () {
|
|
|
2283
2283
|
it("Should ignore protocol for local storage root key", async () => {
|
|
2284
2284
|
var connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", {});
|
|
2285
2285
|
var client = await sdk.init(connectionParameters);
|
|
2286
|
-
expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.
|
|
2286
|
+
expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.3.acc-sdk:8080.cache.OptionCache$");
|
|
2287
2287
|
|
|
2288
2288
|
connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("https://acc-sdk:8080", "admin", "admin", {});
|
|
2289
2289
|
client = await sdk.init(connectionParameters);
|
|
2290
|
-
expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.
|
|
2290
|
+
expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.3.acc-sdk:8080.cache.OptionCache$");
|
|
2291
2291
|
|
|
2292
2292
|
connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("acc-sdk:8080", "admin", "admin", {});
|
|
2293
2293
|
client = await sdk.init(connectionParameters);
|
|
2294
|
-
expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.
|
|
2294
|
+
expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.3.acc-sdk:8080.cache.OptionCache$");
|
|
2295
2295
|
})
|
|
2296
2296
|
|
|
2297
2297
|
it("Should support no storage", async () => {
|
|
@@ -2422,4 +2422,385 @@ describe('ACC Client', function () {
|
|
|
2422
2422
|
expect(paramsFn.mock.calls[0][1]).toMatchObject({ schemaId: "xtk:session", namespace: "xtkSession" });
|
|
2423
2423
|
});
|
|
2424
2424
|
});
|
|
2425
|
+
|
|
2426
|
+
describe("Method-level representation", () => {
|
|
2427
|
+
it("Should force an xml representation", async () => {
|
|
2428
|
+
const client = await Mock.makeClient();
|
|
2429
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2430
|
+
await client.NLWS.xtkSession.logon();
|
|
2431
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2432
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2433
|
+
const queryDef = DomUtil.parse(`
|
|
2434
|
+
<queryDef schema="nms:extAccount" operation="select">
|
|
2435
|
+
<select>
|
|
2436
|
+
<node expr="@id"/>
|
|
2437
|
+
<node expr="@name"/>
|
|
2438
|
+
</select>
|
|
2439
|
+
</queryDef>
|
|
2440
|
+
`);
|
|
2441
|
+
const query = client.NLWS.xml.xtkQueryDef.create(queryDef);
|
|
2442
|
+
const result = await query.executeQuery();
|
|
2443
|
+
const xml = DomUtil.toXMLString(result);
|
|
2444
|
+
expect(xml).toBe(`<extAccount-collection xmlns="urn:xtk:queryDef">
|
|
2445
|
+
<extAccount id="1816" name="defaultPopAccount"/>
|
|
2446
|
+
<extAccount id="1818" name="defaultOther"/>
|
|
2447
|
+
<extAccount id="1849" name="billingReport"/>
|
|
2448
|
+
<extAccount id="12070" name="TST_EXT_ACCOUNT_POSTGRESQL"/>
|
|
2449
|
+
<extAccount id="1817" name="defaultEmailBulk"/>
|
|
2450
|
+
<extAccount id="2087" name="ffda"/>
|
|
2451
|
+
<extAccount id="2088" name="defaultEmailMid"/>
|
|
2452
|
+
</extAccount-collection>`);
|
|
2453
|
+
});
|
|
2454
|
+
|
|
2455
|
+
it("Should force an json representation", async () => {
|
|
2456
|
+
const client = await Mock.makeClient();
|
|
2457
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2458
|
+
await client.NLWS.xtkSession.logon();
|
|
2459
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2460
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2461
|
+
const queryDef = {
|
|
2462
|
+
"schema": "nms:extAccount",
|
|
2463
|
+
"operation": "select",
|
|
2464
|
+
"select": {
|
|
2465
|
+
"node": [
|
|
2466
|
+
{ "expr": "@id" },
|
|
2467
|
+
{ "expr": "@name" }
|
|
2468
|
+
]
|
|
2469
|
+
}
|
|
2470
|
+
};
|
|
2471
|
+
const query = client.NLWS.json.xtkQueryDef.create(queryDef);
|
|
2472
|
+
const result = await query.executeQuery();
|
|
2473
|
+
const json = JSON.stringify(result);
|
|
2474
|
+
expect(json).toBe('{"#text":[],"extAccount":[{"id":"1816","name":"defaultPopAccount"},{"id":"1818","name":"defaultOther"},{"id":"1849","name":"billingReport"},{"id":"12070","name":"TST_EXT_ACCOUNT_POSTGRESQL"},{"id":"1817","name":"defaultEmailBulk"},{"id":"2087","name":"ffda"},{"id":"2088","name":"defaultEmailMid"}]}');
|
|
2475
|
+
});
|
|
2476
|
+
});
|
|
2477
|
+
|
|
2478
|
+
describe('Support for int type parameters such as nms:extAccount#UpdateMCSynchWkf', () => {
|
|
2479
|
+
it("Should call nms:extAccount#UpdateMCSynchWkf", async () => {
|
|
2480
|
+
const client = await Mock.makeClient();
|
|
2481
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2482
|
+
await client.NLWS.xtkSession.logon();
|
|
2483
|
+
|
|
2484
|
+
client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
|
|
2485
|
+
<SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
|
|
2486
|
+
<SOAP-ENV:Body>
|
|
2487
|
+
<GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
|
|
2488
|
+
<pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
|
|
2489
|
+
<schema name="extAccount" namespace="nms" xtkschema="xtk:schema">
|
|
2490
|
+
<element name="extAccount"></element>
|
|
2491
|
+
<methods>
|
|
2492
|
+
<method library="nms:messageCenter.js" name="UpdateMCSynchWkf" static="true" hidden="true">
|
|
2493
|
+
<parameters>
|
|
2494
|
+
<param name="extAccountId" type="int" desc="Message Center external account identifier"/>
|
|
2495
|
+
</parameters>
|
|
2496
|
+
</method>
|
|
2497
|
+
</methods>
|
|
2498
|
+
</schema>
|
|
2499
|
+
</pdomDoc>
|
|
2500
|
+
</GetEntityIfMoreRecentResponse>
|
|
2501
|
+
</SOAP-ENV:Body>
|
|
2502
|
+
</SOAP-ENV:Envelope>`));
|
|
2503
|
+
|
|
2504
|
+
client._transport.mockReturnValueOnce(Promise.resolve(`<?xml version='1.0'?>
|
|
2505
|
+
<SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:nms:extAccount' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
|
|
2506
|
+
<SOAP-ENV:Body>
|
|
2507
|
+
<UpdateMCSynchWkfResponse xmlns='urn:nms:extAccount' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
|
|
2508
|
+
</UpdateMCSynchWkfResponse>
|
|
2509
|
+
</SOAP-ENV:Body>
|
|
2510
|
+
</SOAP-ENV:Envelope>`));
|
|
2511
|
+
|
|
2512
|
+
await client.NLWS.nmsExtAccount.updateMCSynchWkf(1);
|
|
2513
|
+
})
|
|
2514
|
+
});
|
|
2515
|
+
|
|
2516
|
+
describe("Method-level HTTP headers", () => {
|
|
2517
|
+
it("Should set header", async () => {
|
|
2518
|
+
const client = await Mock.makeClient();
|
|
2519
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2520
|
+
await client.NLWS.xtkSession.logon();
|
|
2521
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2522
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2523
|
+
const queryDef = {
|
|
2524
|
+
"schema": "nms:extAccount",
|
|
2525
|
+
"operation": "select",
|
|
2526
|
+
"select": {
|
|
2527
|
+
"node": [
|
|
2528
|
+
{ "expr": "@id" },
|
|
2529
|
+
{ "expr": "@name" }
|
|
2530
|
+
]
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
const query = client.NLWS.headers({'X-Test': 'hello'}).xtkQueryDef.create(queryDef);
|
|
2534
|
+
|
|
2535
|
+
let headers = {};
|
|
2536
|
+
client.registerObserver({
|
|
2537
|
+
onSOAPCall: (soapCall) => {
|
|
2538
|
+
const request = soapCall.request;
|
|
2539
|
+
headers = request.headers;
|
|
2540
|
+
}
|
|
2541
|
+
});
|
|
2542
|
+
await query.executeQuery();
|
|
2543
|
+
expect(headers).toMatchObject({
|
|
2544
|
+
"SoapAction": "xtk:queryDef#ExecuteQuery",
|
|
2545
|
+
"X-Test": "hello"
|
|
2546
|
+
});
|
|
2547
|
+
});
|
|
2548
|
+
|
|
2549
|
+
it("Should support global and method-level http headers", async () => {
|
|
2550
|
+
const client = await Mock.makeClient({
|
|
2551
|
+
extraHttpHeaders: {
|
|
2552
|
+
"X-Test": "world",
|
|
2553
|
+
"X-Test-Global": "global"
|
|
2554
|
+
}
|
|
2555
|
+
});
|
|
2556
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2557
|
+
await client.NLWS.xtkSession.logon();
|
|
2558
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2559
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2560
|
+
const queryDef = {
|
|
2561
|
+
"schema": "nms:extAccount",
|
|
2562
|
+
"operation": "select",
|
|
2563
|
+
"select": {
|
|
2564
|
+
"node": [
|
|
2565
|
+
{ "expr": "@id" },
|
|
2566
|
+
{ "expr": "@name" }
|
|
2567
|
+
]
|
|
2568
|
+
}
|
|
2569
|
+
};
|
|
2570
|
+
const query = client.NLWS.headers({'X-Test': 'hello'}).xtkQueryDef.create(queryDef);
|
|
2571
|
+
|
|
2572
|
+
let headers = {};
|
|
2573
|
+
client.registerObserver({
|
|
2574
|
+
onSOAPCall: (soapCall) => {
|
|
2575
|
+
const request = soapCall.request;
|
|
2576
|
+
headers = request.headers;
|
|
2577
|
+
}
|
|
2578
|
+
});
|
|
2579
|
+
await query.executeQuery();
|
|
2580
|
+
expect(headers).toMatchObject({
|
|
2581
|
+
"SoapAction": "xtk:queryDef#ExecuteQuery",
|
|
2582
|
+
"X-Test": "hello",
|
|
2583
|
+
"X-Test-Global": "global"
|
|
2584
|
+
});
|
|
2585
|
+
})
|
|
2586
|
+
|
|
2587
|
+
it("Should support undefined method headers", async () => {
|
|
2588
|
+
const client = await Mock.makeClient({
|
|
2589
|
+
extraHttpHeaders: {
|
|
2590
|
+
"X-Test": "world",
|
|
2591
|
+
"X-Test-Global": "global"
|
|
2592
|
+
}
|
|
2593
|
+
});
|
|
2594
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2595
|
+
await client.NLWS.xtkSession.logon();
|
|
2596
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2597
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2598
|
+
const queryDef = {
|
|
2599
|
+
"schema": "nms:extAccount",
|
|
2600
|
+
"operation": "select",
|
|
2601
|
+
"select": {
|
|
2602
|
+
"node": [
|
|
2603
|
+
{ "expr": "@id" },
|
|
2604
|
+
{ "expr": "@name" }
|
|
2605
|
+
]
|
|
2606
|
+
}
|
|
2607
|
+
};
|
|
2608
|
+
// missing headers
|
|
2609
|
+
const query = client.NLWS.headers().xtkQueryDef.create(queryDef);
|
|
2610
|
+
|
|
2611
|
+
let headers = {};
|
|
2612
|
+
client.registerObserver({
|
|
2613
|
+
onSOAPCall: (soapCall) => {
|
|
2614
|
+
const request = soapCall.request;
|
|
2615
|
+
headers = request.headers;
|
|
2616
|
+
}
|
|
2617
|
+
});
|
|
2618
|
+
await query.executeQuery();
|
|
2619
|
+
expect(headers).toMatchObject({
|
|
2620
|
+
"SoapAction": "xtk:queryDef#ExecuteQuery",
|
|
2621
|
+
"X-Test": "world",
|
|
2622
|
+
"X-Test-Global": "global"
|
|
2623
|
+
});
|
|
2624
|
+
})
|
|
2625
|
+
|
|
2626
|
+
it("Should set http headers with an xml representation", async () => {
|
|
2627
|
+
const client = await Mock.makeClient();
|
|
2628
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2629
|
+
await client.NLWS.xtkSession.logon();
|
|
2630
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2631
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2632
|
+
const queryDef = DomUtil.parse(`
|
|
2633
|
+
<queryDef schema="nms:extAccount" operation="select">
|
|
2634
|
+
<select>
|
|
2635
|
+
<node expr="@id"/>
|
|
2636
|
+
<node expr="@name"/>
|
|
2637
|
+
</select>
|
|
2638
|
+
</queryDef>
|
|
2639
|
+
`);
|
|
2640
|
+
const query = client.NLWS
|
|
2641
|
+
.headers({'X-Test': 'hello', 'X-Test-Before': 'before'})
|
|
2642
|
+
.xml
|
|
2643
|
+
.headers({'X-Test': 'world', 'X-Test-After': 'after'})
|
|
2644
|
+
.xtkQueryDef.create(queryDef);
|
|
2645
|
+
let headers = {};
|
|
2646
|
+
client.registerObserver({
|
|
2647
|
+
onSOAPCall: (soapCall) => {
|
|
2648
|
+
const request = soapCall.request;
|
|
2649
|
+
headers = request.headers;
|
|
2650
|
+
}
|
|
2651
|
+
});
|
|
2652
|
+
await query.executeQuery();
|
|
2653
|
+
console.log(headers);
|
|
2654
|
+
expect(headers).toMatchObject({
|
|
2655
|
+
"SoapAction": "xtk:queryDef#ExecuteQuery",
|
|
2656
|
+
"X-Test": "world",
|
|
2657
|
+
"X-Test-Before": "before",
|
|
2658
|
+
"X-Test-After": "after"
|
|
2659
|
+
});
|
|
2660
|
+
});
|
|
2661
|
+
});
|
|
2662
|
+
|
|
2663
|
+
describe("ACC-SDK HTTP headers", () => {
|
|
2664
|
+
|
|
2665
|
+
const collectHeaders = async (client, callback) => {
|
|
2666
|
+
let headers = {};
|
|
2667
|
+
client.registerObserver({
|
|
2668
|
+
onSOAPCall: (soapCall) => {
|
|
2669
|
+
const request = soapCall.request;
|
|
2670
|
+
headers = request.headers;
|
|
2671
|
+
},
|
|
2672
|
+
onHTTPCall: (request) => {
|
|
2673
|
+
headers = request.headers;
|
|
2674
|
+
}
|
|
2675
|
+
});
|
|
2676
|
+
await callback();
|
|
2677
|
+
return headers;
|
|
2678
|
+
};
|
|
2679
|
+
|
|
2680
|
+
it("Should set headers by default", async () => {
|
|
2681
|
+
const client = await Mock.makeClient();
|
|
2682
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2683
|
+
await client.NLWS.xtkSession.logon();
|
|
2684
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2685
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2686
|
+
const queryDef = {
|
|
2687
|
+
"schema": "nms:extAccount",
|
|
2688
|
+
"operation": "select",
|
|
2689
|
+
"select": {
|
|
2690
|
+
"node": [
|
|
2691
|
+
{ "expr": "@id" },
|
|
2692
|
+
{ "expr": "@name" }
|
|
2693
|
+
]
|
|
2694
|
+
}
|
|
2695
|
+
};
|
|
2696
|
+
const query = client.NLWS.xtkQueryDef.create(queryDef);
|
|
2697
|
+
|
|
2698
|
+
const headers = await collectHeaders(client, async() => {
|
|
2699
|
+
await query.executeQuery();
|
|
2700
|
+
});
|
|
2701
|
+
|
|
2702
|
+
expect(headers).toMatchObject({
|
|
2703
|
+
"ACC-SDK-Version": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version}`,
|
|
2704
|
+
"ACC-SDK-Auth": "UserPassword admin",
|
|
2705
|
+
"X-Query-Source": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version}`,
|
|
2706
|
+
});
|
|
2707
|
+
// This header is only set if "clientApp" connection parameter is set
|
|
2708
|
+
expect(headers["ACC-SDK-Client-App"]).toBeUndefined();
|
|
2709
|
+
});
|
|
2710
|
+
|
|
2711
|
+
it("Should disable ACC-SDK headers", async () => {
|
|
2712
|
+
const client = await Mock.makeClient({
|
|
2713
|
+
noSDKHeaders: true
|
|
2714
|
+
});
|
|
2715
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2716
|
+
await client.NLWS.xtkSession.logon();
|
|
2717
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2718
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2719
|
+
const queryDef = {
|
|
2720
|
+
"schema": "nms:extAccount",
|
|
2721
|
+
"operation": "select",
|
|
2722
|
+
"select": {
|
|
2723
|
+
"node": [
|
|
2724
|
+
{ "expr": "@id" },
|
|
2725
|
+
{ "expr": "@name" }
|
|
2726
|
+
]
|
|
2727
|
+
}
|
|
2728
|
+
};
|
|
2729
|
+
const query = client.NLWS.xtkQueryDef.create(queryDef);
|
|
2730
|
+
|
|
2731
|
+
const headers = await collectHeaders(client, async() => {
|
|
2732
|
+
await query.executeQuery();
|
|
2733
|
+
});
|
|
2734
|
+
expect(headers["ACC-SDK-Version"]).toBeUndefined();
|
|
2735
|
+
expect(headers["ACC-SDK-Auth"]).toBeUndefined();
|
|
2736
|
+
expect(headers["X-Query-Source"]).toBe(`${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version}`);
|
|
2737
|
+
});
|
|
2738
|
+
|
|
2739
|
+
it("Should support ACC-SDK-Client-App header", async () => {
|
|
2740
|
+
const client = await Mock.makeClient({
|
|
2741
|
+
clientApp: 'Test client app'
|
|
2742
|
+
});
|
|
2743
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2744
|
+
await client.NLWS.xtkSession.logon();
|
|
2745
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
|
|
2746
|
+
client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
|
|
2747
|
+
const queryDef = {
|
|
2748
|
+
"schema": "nms:extAccount",
|
|
2749
|
+
"operation": "select",
|
|
2750
|
+
"select": {
|
|
2751
|
+
"node": [
|
|
2752
|
+
{ "expr": "@id" },
|
|
2753
|
+
{ "expr": "@name" }
|
|
2754
|
+
]
|
|
2755
|
+
}
|
|
2756
|
+
};
|
|
2757
|
+
const query = client.NLWS.xtkQueryDef.create(queryDef);
|
|
2758
|
+
|
|
2759
|
+
const headers = await collectHeaders(client, async() => {
|
|
2760
|
+
await query.executeQuery();
|
|
2761
|
+
});
|
|
2762
|
+
expect(headers).toMatchObject({
|
|
2763
|
+
"ACC-SDK-Version": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version}`,
|
|
2764
|
+
"ACC-SDK-Auth": "UserPassword admin",
|
|
2765
|
+
"ACC-SDK-Client-App": "Test client app",
|
|
2766
|
+
"X-Query-Source": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version},Test client app`,
|
|
2767
|
+
});
|
|
2768
|
+
});
|
|
2769
|
+
|
|
2770
|
+
it("Should set ACC-SDK headers on ping JSP", async () => {
|
|
2771
|
+
const client = await Mock.makeClient({
|
|
2772
|
+
clientApp: 'Test client app'
|
|
2773
|
+
});
|
|
2774
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2775
|
+
await client.NLWS.xtkSession.logon();
|
|
2776
|
+
const headers = await collectHeaders(client, async() => {
|
|
2777
|
+
client._transport.mockReturnValueOnce(Mock.PING);
|
|
2778
|
+
await client.ping();
|
|
2779
|
+
});
|
|
2780
|
+
expect(headers).toMatchObject({
|
|
2781
|
+
"ACC-SDK-Version": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version}`,
|
|
2782
|
+
"ACC-SDK-Auth": "UserPassword admin",
|
|
2783
|
+
"ACC-SDK-Client-App": "Test client app",
|
|
2784
|
+
"X-Query-Source": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version},Test client app`,
|
|
2785
|
+
});
|
|
2786
|
+
});
|
|
2787
|
+
|
|
2788
|
+
it("Should set ACC-SDK headers on mcping JSP", async () => {
|
|
2789
|
+
const client = await Mock.makeClient({
|
|
2790
|
+
clientApp: 'Test client app'
|
|
2791
|
+
});
|
|
2792
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
2793
|
+
await client.NLWS.xtkSession.logon();
|
|
2794
|
+
const headers = await collectHeaders(client, async() => {
|
|
2795
|
+
client._transport.mockReturnValueOnce(Mock.MC_PING);
|
|
2796
|
+
await client.mcPing();
|
|
2797
|
+
});
|
|
2798
|
+
expect(headers).toMatchObject({
|
|
2799
|
+
"ACC-SDK-Version": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version}`,
|
|
2800
|
+
"ACC-SDK-Auth": "UserPassword admin",
|
|
2801
|
+
"ACC-SDK-Client-App": "Test client app",
|
|
2802
|
+
"X-Query-Source": `${sdk.getSDKVersion().name} ${sdk.getSDKVersion().version},Test client app`,
|
|
2803
|
+
});
|
|
2804
|
+
});
|
|
2805
|
+
});
|
|
2425
2806
|
});
|
package/test/soap.test.js
CHANGED
|
@@ -21,11 +21,12 @@ const { SoapMethodCall } = require('../src/soap.js');
|
|
|
21
21
|
const { CampaignException, makeCampaignException } = require('../src/campaign.js');
|
|
22
22
|
const { DomUtil } = require('../src/domUtil.js');
|
|
23
23
|
const assert = require('assert');
|
|
24
|
+
const sdk = require('../src/index.js');
|
|
24
25
|
|
|
25
26
|
const URL = "https://soap-test/nl/jsp/soaprouter.jsp";
|
|
26
27
|
|
|
27
|
-
function makeSoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString) {
|
|
28
|
-
const call = new SoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString);
|
|
28
|
+
function makeSoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString, optionalCharset, charset, extraHttpHeaders) {
|
|
29
|
+
const call = new SoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString, optionalCharset, charset, extraHttpHeaders);
|
|
29
30
|
return call;
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -387,6 +388,22 @@ describe('SOAP', function() {
|
|
|
387
388
|
expect(actualElement.getAttribute("att")).toBe("Hello");
|
|
388
389
|
});
|
|
389
390
|
|
|
391
|
+
it('Should support passing DOM elements instead of document parameters', function() {
|
|
392
|
+
const xml = '<root att="Hello"><child/></root>';
|
|
393
|
+
const doc = DomUtil.parse(xml);
|
|
394
|
+
|
|
395
|
+
const call = makeSoapMethodCall(undefined, "xtk:session", "Document", "$session$", "$security$");
|
|
396
|
+
call.writeDocument("p", doc.documentElement);
|
|
397
|
+
const request = call._createHTTPRequest(URL);
|
|
398
|
+
const env = DomUtil.parse(request.data).documentElement;
|
|
399
|
+
const body = hasChildElement(env, "SOAP-ENV:Body");
|
|
400
|
+
const method = hasChildElement(body, "m:Document");
|
|
401
|
+
const param = hasChildElement(method, "p");
|
|
402
|
+
const actualElement = hasChildElement(param, "root");
|
|
403
|
+
expect(actualElement).toBeTruthy();
|
|
404
|
+
expect(actualElement.getAttribute("att")).toBe("Hello");
|
|
405
|
+
});
|
|
406
|
+
|
|
390
407
|
it('Should write null document', function() {
|
|
391
408
|
const call = makeSoapMethodCall(undefined, "xtk:session", "Document", "$session$", "$security$");
|
|
392
409
|
call.writeDocument("p", null);
|
|
@@ -682,6 +699,56 @@ describe('SOAP', function() {
|
|
|
682
699
|
});
|
|
683
700
|
})
|
|
684
701
|
});
|
|
702
|
+
|
|
703
|
+
describe("Charset encoding", function() {
|
|
704
|
+
|
|
705
|
+
it("Should support no encoding", function() {
|
|
706
|
+
const call = makeSoapMethodCall(undefined, "xtk:session", "Empty");
|
|
707
|
+
const request = call._createHTTPRequest(URL);
|
|
708
|
+
assert.equal(request.url, URL);
|
|
709
|
+
assert.equal(request.headers["Content-type"], "application/soap+xml");
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
it("Should support UTF-8 encoding", function() {
|
|
713
|
+
const call = makeSoapMethodCall(undefined, "xtk:session", "Empty", undefined, undefined, undefined, "UTF-8");
|
|
714
|
+
const request = call._createHTTPRequest(URL);
|
|
715
|
+
assert.equal(request.url, URL);
|
|
716
|
+
assert.equal(request.headers["Content-type"], "application/soap+xml;charset=UTF-8");
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
it("Default encoding should be UTF-8", async () => {
|
|
720
|
+
const connectionParameters = sdk.ConnectionParameters.ofSessionToken("http://acc-sdk:8080", "mc/");
|
|
721
|
+
const client = await sdk.init(connectionParameters);
|
|
722
|
+
client._transport = jest.fn();
|
|
723
|
+
expect(client._connectionParameters._options.charset).toBe('UTF-8');
|
|
724
|
+
const soapCall = client._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", true);
|
|
725
|
+
expect (soapCall._charset).toBe('UTF-8');
|
|
726
|
+
const request = soapCall._createHTTPRequest(URL);
|
|
727
|
+
assert.equal(request.headers["Content-type"], "application/soap+xml;charset=UTF-8");
|
|
728
|
+
})
|
|
729
|
+
|
|
730
|
+
it("Default support forcing an empty encoding", async () => {
|
|
731
|
+
const connectionParameters = sdk.ConnectionParameters.ofSessionToken("http://acc-sdk:8080", "mc/", { charset: "" });
|
|
732
|
+
const client = await sdk.init(connectionParameters);
|
|
733
|
+
client._transport = jest.fn();
|
|
734
|
+
expect(client._connectionParameters._options.charset).toBe('');
|
|
735
|
+
const soapCall = client._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", true);
|
|
736
|
+
expect (soapCall._charset).toBe('');
|
|
737
|
+
const request = soapCall._createHTTPRequest(URL);
|
|
738
|
+
assert.equal(request.headers["Content-type"], "application/soap+xml");
|
|
739
|
+
})
|
|
740
|
+
|
|
741
|
+
it("Default support forcing an ISO charset", async () => {
|
|
742
|
+
const connectionParameters = sdk.ConnectionParameters.ofSessionToken("http://acc-sdk:8080", "mc/", { charset: "ISO-8859-1" });
|
|
743
|
+
const client = await sdk.init(connectionParameters);
|
|
744
|
+
client._transport = jest.fn();
|
|
745
|
+
expect(client._connectionParameters._options.charset).toBe('ISO-8859-1');
|
|
746
|
+
const soapCall = client._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", true);
|
|
747
|
+
expect (soapCall._charset).toBe('ISO-8859-1');
|
|
748
|
+
const request = soapCall._createHTTPRequest(URL);
|
|
749
|
+
assert.equal(request.headers["Content-type"], "application/soap+xml;charset=ISO-8859-1");
|
|
750
|
+
})
|
|
751
|
+
});
|
|
685
752
|
|
|
686
753
|
});
|
|
687
754
|
|
|
@@ -799,5 +866,23 @@ describe("Campaign exception", () => {
|
|
|
799
866
|
expect(req.headers["X-Security-Token"].indexOf("$security$")).toBe(-1);
|
|
800
867
|
})
|
|
801
868
|
|
|
869
|
+
describe('Extra Http headers', () => {
|
|
870
|
+
it("Should take additional headers", () => {
|
|
871
|
+
const call = makeSoapMethodCall(undefined, "xtk:session", "Date", "$session$", "$security$", "My User Agent", undefined, { 'X-ACC-UI-Version': '1.0' });
|
|
872
|
+
const request = call._createHTTPRequest(URL);
|
|
873
|
+
expect(request.headers['User-Agent']).toBe("My User Agent");
|
|
874
|
+
expect(request.headers['X-ACC-UI-Version']).toBe("1.0");
|
|
875
|
+
expect(request.headers['SoapAction']).toBe("xtk:session#Date");
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
it("Should override default headers headers", () => {
|
|
879
|
+
const call = makeSoapMethodCall(undefined, "xtk:session", "Date", "$session$", "$security$", "My User Agent", undefined, { 'X-ACC-UI-Version': '1.0', 'SoapAction': 'My soap action' });
|
|
880
|
+
const request = call._createHTTPRequest(URL);
|
|
881
|
+
expect(request.headers['User-Agent']).toBe("My User Agent");
|
|
882
|
+
expect(request.headers['X-ACC-UI-Version']).toBe("1.0");
|
|
883
|
+
expect(request.headers['SoapAction']).toBe("My soap action");
|
|
884
|
+
});
|
|
885
|
+
});
|
|
886
|
+
|
|
802
887
|
});
|
|
803
888
|
|