@serenity-js/rest 3.10.2 → 3.10.4

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
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.10.4](https://github.com/serenity-js/serenity-js/compare/v3.10.3...v3.10.4) (2023-09-22)
7
+
8
+ **Note:** Version bump only for package @serenity-js/rest
9
+
10
+
11
+
12
+
13
+
14
+ ## [3.10.3](https://github.com/serenity-js/serenity-js/compare/v3.10.2...v3.10.3) (2023-09-15)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **rest:** correctly resolve relative paths in REST requests ([1bdf3eb](https://github.com/serenity-js/serenity-js/commit/1bdf3eb05701007c8d640e4529f701862f223480))
20
+ * **rest:** improved error messages and error handling for failed requests ([e6eb0c3](https://github.com/serenity-js/serenity-js/commit/e6eb0c36db0979be4c8e861cfe402094b7157024)), closes [#1876](https://github.com/serenity-js/serenity-js/issues/1876)
21
+
22
+
23
+
24
+
25
+
6
26
  ## [3.10.2](https://github.com/serenity-js/serenity-js/compare/v3.10.1...v3.10.2) (2023-09-10)
7
27
 
8
28
 
@@ -135,6 +135,5 @@ export declare class CallAnApi extends Ability {
135
135
  * @param mappingFunction
136
136
  */
137
137
  mapLastResponse<T>(mappingFunction: (response: AxiosResponse) => T): T;
138
- private captureResponseOf;
139
138
  }
140
139
  //# sourceMappingURL=CallAnApi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CallAnApi.d.ts","sourceRoot":"","sources":["../../../src/screenplay/abilities/CallAnApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwD,MAAM,mBAAmB,CAAC;AAClG,OAAO,KAAK,EAAE,aAAa,EAAc,aAAa,EAAgB,kBAAkB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGvH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,SAAU,SAAQ,OAAO;IA8CtB,OAAO,CAAC,QAAQ,CAAC,aAAa;IA5C1C,eAAe;IACf,OAAO,CAAC,YAAY,CAAgB;IAEpC;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS;IAQrC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS;IAIrD;;;;;;OAMG;gBAC0B,aAAa,EAAE,aAAa;IAIzD;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,IAAI;IAI7D;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAI3D;;;;;;;;;OASG;IACH,UAAU,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAI9C;;;;;;;;OAQG;IACH,eAAe,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,CAAC,GAAG,CAAC;IAQtE,OAAO,CAAC,iBAAiB;CA0B5B"}
1
+ {"version":3,"file":"CallAnApi.d.ts","sourceRoot":"","sources":["../../../src/screenplay/abilities/CallAnApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwD,MAAM,mBAAmB,CAAC;AAClG,OAAO,KAAK,EAAE,aAAa,EAAc,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGzG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,SAAU,SAAQ,OAAO;IA8CtB,OAAO,CAAC,QAAQ,CAAC,aAAa;IA5C1C,eAAe;IACf,OAAO,CAAC,YAAY,CAAgB;IAEpC;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS;IAQrC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS;IAIrD;;;;;;OAMG;gBAC0B,aAAa,EAAE,aAAa;IAIzD;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,IAAI;IAI7D;;;;;;;;;;;OAWG;IACG,OAAO,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAgCjE;;;;;;;;;OASG;IACH,UAAU,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAQ9C;;;;;;;;OAQG;IACH,eAAe,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,CAAC,GAAG,CAAC;CAOzE"}
@@ -129,8 +129,32 @@ class CallAnApi extends core_1.Ability {
129
129
  * Axios request configuration, which can be used to override the defaults
130
130
  * provided when the {@apilink Ability|ability} to {@apilink CallAnApi} was instantiated.
131
131
  */
132
- request(config) {
133
- return this.captureResponseOf(this.axiosInstance.request(config));
132
+ async request(config) {
133
+ let url;
134
+ try {
135
+ url = this.resolveUrl(config);
136
+ this.lastResponse = await this.axiosInstance.request({
137
+ ...config,
138
+ url,
139
+ });
140
+ return this.lastResponse;
141
+ }
142
+ catch (error) {
143
+ const description = `${config.method.toUpperCase()} ${url || config.url}`;
144
+ switch (true) {
145
+ case /timeout.*exceeded/.test(error.message):
146
+ throw new core_1.TestCompromisedError(`The request has timed out: ${description}`, error);
147
+ case /Network Error/.test(error.message):
148
+ throw new core_1.TestCompromisedError(`A network error has occurred: ${description}`, error);
149
+ case error instanceof TypeError:
150
+ throw new core_1.ConfigurationError(`Looks like there was an issue with Axios configuration`, error);
151
+ case !error.response:
152
+ throw new core_1.TestCompromisedError(`The API call has failed: ${description}`, error);
153
+ default:
154
+ this.lastResponse = error.response;
155
+ return error.response;
156
+ }
157
+ }
134
158
  }
135
159
  /**
136
160
  * Resolves the final URL, based on the {@apilink AxiosRequestConfig} provided
@@ -143,7 +167,10 @@ class CallAnApi extends core_1.Ability {
143
167
  * @param config
144
168
  */
145
169
  resolveUrl(config) {
146
- return this.axiosInstance.getUri(config);
170
+ const baseURL = this.axiosInstance.defaults.baseURL || config.baseURL;
171
+ return baseURL
172
+ ? new URL(config.url, baseURL).toString()
173
+ : config.url;
147
174
  }
148
175
  /**
149
176
  * Maps the last cached response to another type.
@@ -160,27 +187,6 @@ class CallAnApi extends core_1.Ability {
160
187
  }
161
188
  return mappingFunction(this.lastResponse);
162
189
  }
163
- captureResponseOf(promisedResponse) {
164
- return promisedResponse
165
- .then(lastResponse => {
166
- this.lastResponse = lastResponse;
167
- return lastResponse;
168
- }, error => {
169
- switch (true) {
170
- case /timeout.*exceeded/.test(error.message):
171
- throw new core_1.TestCompromisedError(`The request has timed out`, error);
172
- case /Network Error/.test(error.message):
173
- throw new core_1.TestCompromisedError(`A network error has occurred`, error);
174
- case error instanceof TypeError:
175
- throw new core_1.ConfigurationError(`Looks like there was an issue with Axios configuration`, error);
176
- case !error.response:
177
- throw new core_1.TestCompromisedError(`The API call has failed`, error); // todo: include request url
178
- default:
179
- this.lastResponse = error.response;
180
- return error.response;
181
- }
182
- });
183
- }
184
190
  }
185
191
  exports.CallAnApi = CallAnApi;
186
192
  //# sourceMappingURL=CallAnApi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CallAnApi.js","sourceRoot":"","sources":["../../../src/screenplay/abilities/CallAnApi.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAkG;AAElG,kDAA0B;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,MAAa,SAAU,SAAQ,cAAO;IAKlC;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CAAC,OAAe;QACrB,OAAO,IAAI,SAAS,CAAC,eAAK,CAAC,MAAM,CAAC;YAC9B,OAAO;YACP,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE,MAAM,EAAE,kCAAkC,EAAE;SAC1D,CAAC,CAAC,CAAC;IACR,CAAC;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,KAAK,CAAC,aAA4B;QACrC,OAAO,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;OAMG;IACH,YAA6B,aAA4B;QACrD,KAAK,EAAE,CAAC;QADiB,kBAAa,GAAb,aAAa,CAAe;IAEzD,CAAC;IAED;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAyC;QAClD,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAA0B;QAC9B,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,CAAC;IAED;;;;;;;;;OASG;IACH,UAAU,CAAC,MAA0B;QACjC,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;;;OAQG;IACH,eAAe,CAAI,eAA+C;QAC9D,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACpB,MAAM,IAAI,iBAAU,CAAC,sEAAsE,CAAC,CAAC;SAChG;QAED,OAAO,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9C,CAAC;IAEO,iBAAiB,CAAC,gBAA8B;QACpD,OAAO,gBAAgB;aAClB,IAAI,CACD,YAAY,CAAC,EAAE;YACX,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;YAEjC,OAAO,YAAY,CAAC;QACxB,CAAC,EACD,KAAK,CAAC,EAAE;YACJ,QAAQ,IAAI,EAAE;gBACV,KAAK,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;oBACxC,MAAM,IAAI,2BAAoB,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;gBACvE,KAAK,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;oBACpC,MAAM,IAAI,2BAAoB,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;gBAC1E,KAAK,KAAK,YAAY,SAAS;oBAC3B,MAAM,IAAI,yBAAkB,CAAC,wDAAwD,EAAE,KAAK,CAAC,CAAC;gBAClG,KAAK,CAAG,KAAoB,CAAC,QAAQ;oBACjC,MAAM,IAAI,2BAAoB,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC,CAAG,4BAA4B;gBACpG;oBACI,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC;oBAEnC,OAAO,KAAK,CAAC,QAAQ,CAAC;aAC7B;QACL,CAAC,CACJ,CAAC;IACV,CAAC;CACJ;AAzID,8BAyIC"}
1
+ {"version":3,"file":"CallAnApi.js","sourceRoot":"","sources":["../../../src/screenplay/abilities/CallAnApi.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serenity-js/rest",
3
- "version": "3.10.2",
3
+ "version": "3.10.4",
4
4
  "description": "Test REST APIs with Serenity/JS",
5
5
  "author": {
6
6
  "name": "Jan Molak",
@@ -45,20 +45,20 @@
45
45
  "node": "^16.13 || ^18.12 || ^20"
46
46
  },
47
47
  "dependencies": {
48
- "@serenity-js/core": "3.10.2",
48
+ "@serenity-js/core": "3.10.4",
49
49
  "axios": "^1.5.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@integration/testing-tools": "3.0.0",
53
- "@serenity-js/assertions": "3.10.2",
53
+ "@serenity-js/assertions": "3.10.4",
54
54
  "@types/chai": "^4.3.6",
55
55
  "@types/mocha": "^10.0.1",
56
- "axios-mock-adapter": "1.21.5",
56
+ "axios-mock-adapter": "1.22.0",
57
57
  "c8": "8.0.1",
58
58
  "mocha": "^10.2.0",
59
59
  "mocha-multi": "^1.1.7",
60
60
  "ts-node": "^10.9.1",
61
61
  "typescript": "5.1.6"
62
62
  },
63
- "gitHead": "6834827fffe5dd8dd3d2f39d2fea2c4039ab1d3d"
63
+ "gitHead": "28f12bd6029a9a6c1d8e492486138bf0c83916cd"
64
64
  }
@@ -1,5 +1,5 @@
1
1
  import { Ability, ConfigurationError, LogicError, TestCompromisedError } from '@serenity-js/core';
2
- import type { AxiosDefaults, AxiosError, AxiosInstance, AxiosPromise, AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ import type { AxiosDefaults, AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
3
3
  import axios from 'axios';
4
4
 
5
5
  /**
@@ -132,8 +132,36 @@ export class CallAnApi extends Ability {
132
132
  * Axios request configuration, which can be used to override the defaults
133
133
  * provided when the {@apilink Ability|ability} to {@apilink CallAnApi} was instantiated.
134
134
  */
135
- request(config: AxiosRequestConfig): Promise<AxiosResponse> {
136
- return this.captureResponseOf(this.axiosInstance.request(config));
135
+ async request(config: AxiosRequestConfig): Promise<AxiosResponse> {
136
+ let url: string;
137
+
138
+ try {
139
+ url = this.resolveUrl(config);
140
+ this.lastResponse = await this.axiosInstance.request({
141
+ ...config,
142
+ url,
143
+ });
144
+
145
+ return this.lastResponse;
146
+ }
147
+ catch(error) {
148
+ const description = `${ config.method.toUpperCase() } ${ url || config.url }`;
149
+
150
+ switch (true) {
151
+ case /timeout.*exceeded/.test(error.message):
152
+ throw new TestCompromisedError(`The request has timed out: ${ description }`, error);
153
+ case /Network Error/.test(error.message):
154
+ throw new TestCompromisedError(`A network error has occurred: ${ description }`, error);
155
+ case error instanceof TypeError:
156
+ throw new ConfigurationError(`Looks like there was an issue with Axios configuration`, error);
157
+ case ! (error as AxiosError).response:
158
+ throw new TestCompromisedError(`The API call has failed: ${ description }`, error);
159
+ default:
160
+ this.lastResponse = error.response;
161
+
162
+ return error.response;
163
+ }
164
+ }
137
165
  }
138
166
 
139
167
  /**
@@ -147,7 +175,11 @@ export class CallAnApi extends Ability {
147
175
  * @param config
148
176
  */
149
177
  resolveUrl(config: AxiosRequestConfig): string {
150
- return this.axiosInstance.getUri(config);
178
+ const baseURL = this.axiosInstance.defaults.baseURL || config.baseURL;
179
+
180
+ return baseURL
181
+ ? new URL(config.url, baseURL).toString()
182
+ : config.url;
151
183
  }
152
184
 
153
185
  /**
@@ -166,31 +198,4 @@ export class CallAnApi extends Ability {
166
198
 
167
199
  return mappingFunction(this.lastResponse);
168
200
  }
169
-
170
- private captureResponseOf(promisedResponse: AxiosPromise): AxiosPromise {
171
- return promisedResponse
172
- .then(
173
- lastResponse => {
174
- this.lastResponse = lastResponse;
175
-
176
- return lastResponse;
177
- },
178
- error => {
179
- switch (true) {
180
- case /timeout.*exceeded/.test(error.message):
181
- throw new TestCompromisedError(`The request has timed out`, error);
182
- case /Network Error/.test(error.message):
183
- throw new TestCompromisedError(`A network error has occurred`, error);
184
- case error instanceof TypeError:
185
- throw new ConfigurationError(`Looks like there was an issue with Axios configuration`, error);
186
- case ! (error as AxiosError).response:
187
- throw new TestCompromisedError(`The API call has failed`, error); // todo: include request url
188
- default:
189
- this.lastResponse = error.response;
190
-
191
- return error.response;
192
- }
193
- },
194
- );
195
- }
196
201
  }