@serenity-js/rest 3.41.2 → 3.42.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.
Files changed (213) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/esm/index.d.ts +3 -0
  3. package/esm/index.d.ts.map +1 -0
  4. package/esm/index.js +3 -0
  5. package/esm/index.js.map +1 -0
  6. package/esm/io/AxiosRequestConfigDefaults.d.ts +15 -0
  7. package/esm/io/AxiosRequestConfigDefaults.d.ts.map +1 -0
  8. package/esm/io/AxiosRequestConfigDefaults.js +2 -0
  9. package/esm/io/AxiosRequestConfigDefaults.js.map +1 -0
  10. package/esm/io/EnvironmentVariables.d.ts +9 -0
  11. package/esm/io/EnvironmentVariables.d.ts.map +1 -0
  12. package/esm/io/EnvironmentVariables.js +35 -0
  13. package/esm/io/EnvironmentVariables.js.map +1 -0
  14. package/esm/io/ProxyAgent.d.ts +52 -0
  15. package/esm/io/ProxyAgent.d.ts.map +1 -0
  16. package/esm/io/ProxyAgent.js +83 -0
  17. package/esm/io/ProxyAgent.js.map +1 -0
  18. package/esm/io/ProxyBypass.d.ts +6 -0
  19. package/esm/io/ProxyBypass.d.ts.map +1 -0
  20. package/esm/io/ProxyBypass.js +66 -0
  21. package/esm/io/ProxyBypass.js.map +1 -0
  22. package/esm/io/createAxios.d.ts +9 -0
  23. package/esm/io/createAxios.d.ts.map +1 -0
  24. package/esm/io/createAxios.js +40 -0
  25. package/esm/io/createAxios.js.map +1 -0
  26. package/esm/io/createUrl.d.ts +9 -0
  27. package/esm/io/createUrl.d.ts.map +1 -0
  28. package/esm/io/createUrl.js +26 -0
  29. package/esm/io/createUrl.js.map +1 -0
  30. package/esm/io/index.d.ts +3 -0
  31. package/esm/io/index.d.ts.map +1 -0
  32. package/esm/io/index.js +3 -0
  33. package/esm/io/index.js.map +1 -0
  34. package/esm/io/proxy.d.ts +14 -0
  35. package/esm/io/proxy.d.ts.map +1 -0
  36. package/esm/io/proxy.js +66 -0
  37. package/esm/io/proxy.js.map +1 -0
  38. package/esm/screenplay/abilities/AxiosRequestConfigDefaults.d.ts +14 -0
  39. package/esm/screenplay/abilities/AxiosRequestConfigDefaults.d.ts.map +1 -0
  40. package/esm/screenplay/abilities/AxiosRequestConfigDefaults.js +2 -0
  41. package/esm/screenplay/abilities/AxiosRequestConfigDefaults.js.map +1 -0
  42. package/esm/screenplay/abilities/CallAnApi.d.ts +443 -0
  43. package/esm/screenplay/abilities/CallAnApi.d.ts.map +1 -0
  44. package/esm/screenplay/abilities/CallAnApi.js +555 -0
  45. package/esm/screenplay/abilities/CallAnApi.js.map +1 -0
  46. package/esm/screenplay/abilities/index.d.ts +2 -0
  47. package/esm/screenplay/abilities/index.d.ts.map +1 -0
  48. package/esm/screenplay/abilities/index.js +2 -0
  49. package/esm/screenplay/abilities/index.js.map +1 -0
  50. package/esm/screenplay/index.d.ts +5 -0
  51. package/esm/screenplay/index.d.ts.map +1 -0
  52. package/esm/screenplay/index.js +5 -0
  53. package/esm/screenplay/index.js.map +1 -0
  54. package/esm/screenplay/interactions/ChangeApiConfig.d.ts +135 -0
  55. package/esm/screenplay/interactions/ChangeApiConfig.d.ts.map +1 -0
  56. package/esm/screenplay/interactions/ChangeApiConfig.js +212 -0
  57. package/esm/screenplay/interactions/ChangeApiConfig.js.map +1 -0
  58. package/esm/screenplay/interactions/Send.d.ts +48 -0
  59. package/esm/screenplay/interactions/Send.d.ts.map +1 -0
  60. package/esm/screenplay/interactions/Send.js +83 -0
  61. package/esm/screenplay/interactions/Send.js.map +1 -0
  62. package/esm/screenplay/interactions/index.d.ts +3 -0
  63. package/esm/screenplay/interactions/index.d.ts.map +1 -0
  64. package/esm/screenplay/interactions/index.js +3 -0
  65. package/esm/screenplay/interactions/index.js.map +1 -0
  66. package/esm/screenplay/models/DeleteRequest.d.ts +66 -0
  67. package/esm/screenplay/models/DeleteRequest.d.ts.map +1 -0
  68. package/esm/screenplay/models/DeleteRequest.js +69 -0
  69. package/esm/screenplay/models/DeleteRequest.js.map +1 -0
  70. package/esm/screenplay/models/GetRequest.d.ts +73 -0
  71. package/esm/screenplay/models/GetRequest.d.ts.map +1 -0
  72. package/esm/screenplay/models/GetRequest.js +76 -0
  73. package/esm/screenplay/models/GetRequest.js.map +1 -0
  74. package/esm/screenplay/models/HTTPRequest.d.ts +40 -0
  75. package/esm/screenplay/models/HTTPRequest.d.ts.map +1 -0
  76. package/esm/screenplay/models/HTTPRequest.js +62 -0
  77. package/esm/screenplay/models/HTTPRequest.js.map +1 -0
  78. package/esm/screenplay/models/HeadRequest.d.ts +58 -0
  79. package/esm/screenplay/models/HeadRequest.d.ts.map +1 -0
  80. package/esm/screenplay/models/HeadRequest.js +61 -0
  81. package/esm/screenplay/models/HeadRequest.js.map +1 -0
  82. package/esm/screenplay/models/OptionsRequest.d.ts +61 -0
  83. package/esm/screenplay/models/OptionsRequest.d.ts.map +1 -0
  84. package/esm/screenplay/models/OptionsRequest.js +64 -0
  85. package/esm/screenplay/models/OptionsRequest.js.map +1 -0
  86. package/esm/screenplay/models/PatchRequest.d.ts +65 -0
  87. package/esm/screenplay/models/PatchRequest.d.ts.map +1 -0
  88. package/esm/screenplay/models/PatchRequest.js +70 -0
  89. package/esm/screenplay/models/PatchRequest.js.map +1 -0
  90. package/esm/screenplay/models/PostRequest.d.ts +105 -0
  91. package/esm/screenplay/models/PostRequest.d.ts.map +1 -0
  92. package/esm/screenplay/models/PostRequest.js +110 -0
  93. package/esm/screenplay/models/PostRequest.js.map +1 -0
  94. package/esm/screenplay/models/PutRequest.d.ts +75 -0
  95. package/esm/screenplay/models/PutRequest.d.ts.map +1 -0
  96. package/esm/screenplay/models/PutRequest.js +80 -0
  97. package/esm/screenplay/models/PutRequest.js.map +1 -0
  98. package/esm/screenplay/models/index.d.ts +9 -0
  99. package/esm/screenplay/models/index.d.ts.map +1 -0
  100. package/esm/screenplay/models/index.js +9 -0
  101. package/esm/screenplay/models/index.js.map +1 -0
  102. package/esm/screenplay/questions/LastResponse.d.ts +189 -0
  103. package/esm/screenplay/questions/LastResponse.d.ts.map +1 -0
  104. package/esm/screenplay/questions/LastResponse.js +205 -0
  105. package/esm/screenplay/questions/LastResponse.js.map +1 -0
  106. package/esm/screenplay/questions/index.d.ts +2 -0
  107. package/esm/screenplay/questions/index.d.ts.map +1 -0
  108. package/esm/screenplay/questions/index.js +2 -0
  109. package/esm/screenplay/questions/index.js.map +1 -0
  110. package/lib/index.d.ts +2 -2
  111. package/lib/index.d.ts.map +1 -1
  112. package/lib/index.js +2 -2
  113. package/lib/index.js.map +1 -1
  114. package/lib/io/ProxyBypass.js +2 -2
  115. package/lib/io/ProxyBypass.js.map +1 -1
  116. package/lib/io/createAxios.d.ts +1 -1
  117. package/lib/io/createAxios.d.ts.map +1 -1
  118. package/lib/io/createAxios.js +2 -2
  119. package/lib/io/createAxios.js.map +1 -1
  120. package/lib/io/index.d.ts +2 -2
  121. package/lib/io/index.d.ts.map +1 -1
  122. package/lib/io/index.js +2 -2
  123. package/lib/io/index.js.map +1 -1
  124. package/lib/io/proxy.d.ts +2 -2
  125. package/lib/io/proxy.d.ts.map +1 -1
  126. package/lib/io/proxy.js +9 -9
  127. package/lib/io/proxy.js.map +1 -1
  128. package/lib/package.json +1 -0
  129. package/lib/screenplay/abilities/CallAnApi.d.ts +1 -1
  130. package/lib/screenplay/abilities/CallAnApi.d.ts.map +1 -1
  131. package/lib/screenplay/abilities/CallAnApi.js +4 -4
  132. package/lib/screenplay/abilities/CallAnApi.js.map +1 -1
  133. package/lib/screenplay/abilities/index.d.ts +1 -1
  134. package/lib/screenplay/abilities/index.d.ts.map +1 -1
  135. package/lib/screenplay/abilities/index.js +1 -1
  136. package/lib/screenplay/abilities/index.js.map +1 -1
  137. package/lib/screenplay/index.d.ts +4 -4
  138. package/lib/screenplay/index.d.ts.map +1 -1
  139. package/lib/screenplay/index.js +4 -4
  140. package/lib/screenplay/index.js.map +1 -1
  141. package/lib/screenplay/interactions/ChangeApiConfig.js +4 -4
  142. package/lib/screenplay/interactions/ChangeApiConfig.js.map +1 -1
  143. package/lib/screenplay/interactions/Send.js +3 -3
  144. package/lib/screenplay/interactions/Send.js.map +1 -1
  145. package/lib/screenplay/interactions/index.d.ts +2 -2
  146. package/lib/screenplay/interactions/index.d.ts.map +1 -1
  147. package/lib/screenplay/interactions/index.js +2 -2
  148. package/lib/screenplay/interactions/index.js.map +1 -1
  149. package/lib/screenplay/models/DeleteRequest.d.ts +1 -1
  150. package/lib/screenplay/models/DeleteRequest.d.ts.map +1 -1
  151. package/lib/screenplay/models/DeleteRequest.js +2 -2
  152. package/lib/screenplay/models/DeleteRequest.js.map +1 -1
  153. package/lib/screenplay/models/GetRequest.d.ts +1 -1
  154. package/lib/screenplay/models/GetRequest.d.ts.map +1 -1
  155. package/lib/screenplay/models/GetRequest.js +2 -2
  156. package/lib/screenplay/models/GetRequest.js.map +1 -1
  157. package/lib/screenplay/models/HTTPRequest.js +1 -1
  158. package/lib/screenplay/models/HTTPRequest.js.map +1 -1
  159. package/lib/screenplay/models/HeadRequest.d.ts +1 -1
  160. package/lib/screenplay/models/HeadRequest.d.ts.map +1 -1
  161. package/lib/screenplay/models/HeadRequest.js +2 -2
  162. package/lib/screenplay/models/HeadRequest.js.map +1 -1
  163. package/lib/screenplay/models/OptionsRequest.d.ts +1 -1
  164. package/lib/screenplay/models/OptionsRequest.d.ts.map +1 -1
  165. package/lib/screenplay/models/OptionsRequest.js +2 -2
  166. package/lib/screenplay/models/OptionsRequest.js.map +1 -1
  167. package/lib/screenplay/models/PatchRequest.d.ts +1 -1
  168. package/lib/screenplay/models/PatchRequest.d.ts.map +1 -1
  169. package/lib/screenplay/models/PatchRequest.js +2 -2
  170. package/lib/screenplay/models/PatchRequest.js.map +1 -1
  171. package/lib/screenplay/models/PostRequest.d.ts +1 -1
  172. package/lib/screenplay/models/PostRequest.d.ts.map +1 -1
  173. package/lib/screenplay/models/PostRequest.js +2 -2
  174. package/lib/screenplay/models/PostRequest.js.map +1 -1
  175. package/lib/screenplay/models/PutRequest.d.ts +1 -1
  176. package/lib/screenplay/models/PutRequest.d.ts.map +1 -1
  177. package/lib/screenplay/models/PutRequest.js +2 -2
  178. package/lib/screenplay/models/PutRequest.js.map +1 -1
  179. package/lib/screenplay/models/index.d.ts +8 -8
  180. package/lib/screenplay/models/index.d.ts.map +1 -1
  181. package/lib/screenplay/models/index.js +8 -8
  182. package/lib/screenplay/models/index.js.map +1 -1
  183. package/lib/screenplay/questions/LastResponse.js +5 -5
  184. package/lib/screenplay/questions/LastResponse.js.map +1 -1
  185. package/lib/screenplay/questions/index.d.ts +1 -1
  186. package/lib/screenplay/questions/index.d.ts.map +1 -1
  187. package/lib/screenplay/questions/index.js +1 -1
  188. package/lib/screenplay/questions/index.js.map +1 -1
  189. package/package.json +28 -10
  190. package/src/index.ts +2 -2
  191. package/src/io/ProxyBypass.ts +1 -1
  192. package/src/io/createAxios.ts +2 -2
  193. package/src/io/index.ts +2 -2
  194. package/src/io/proxy.ts +5 -5
  195. package/src/screenplay/abilities/CallAnApi.ts +3 -3
  196. package/src/screenplay/abilities/index.ts +1 -1
  197. package/src/screenplay/index.ts +4 -4
  198. package/src/screenplay/interactions/ChangeApiConfig.ts +1 -1
  199. package/src/screenplay/interactions/Send.ts +3 -3
  200. package/src/screenplay/interactions/index.ts +2 -2
  201. package/src/screenplay/models/DeleteRequest.ts +1 -1
  202. package/src/screenplay/models/GetRequest.ts +1 -1
  203. package/src/screenplay/models/HTTPRequest.ts +1 -1
  204. package/src/screenplay/models/HeadRequest.ts +1 -1
  205. package/src/screenplay/models/OptionsRequest.ts +1 -1
  206. package/src/screenplay/models/PatchRequest.ts +1 -1
  207. package/src/screenplay/models/PostRequest.ts +1 -1
  208. package/src/screenplay/models/PutRequest.ts +1 -1
  209. package/src/screenplay/models/index.ts +8 -8
  210. package/src/screenplay/questions/LastResponse.ts +1 -1
  211. package/src/screenplay/questions/index.ts +1 -1
  212. package/tsconfig-cjs.build.json +17 -0
  213. package/tsconfig-esm.build.json +18 -0
@@ -0,0 +1,555 @@
1
+ import { URL } from 'node:url';
2
+ import { Ability, ConfigurationError, LogicError, TestCompromisedError } from '@serenity-js/core';
3
+ import { Agent } from 'agent-base';
4
+ import { isObject } from 'tiny-types/lib/objects/index.js';
5
+ import { createAxios } from '../../io/index.js';
6
+ /**
7
+ * An [ability](https://serenity-js.org/api/core/class/Ability/) that wraps [axios client](https://axios-http.com/docs/api_intro) and enables
8
+ * the [actor](https://serenity-js.org/api/core/class/Actor/) to [send](https://serenity-js.org/api/rest/class/Send/)
9
+ * [HTTP requests](https://serenity-js.org/api/rest/class/HTTPRequest/) to HTTP APIs.
10
+ *
11
+ * ## Configuring the ability to call an API
12
+ *
13
+ * The easiest way to configure the ability to `CallAnApi` is to provide the `baseURL` of your HTTP API,
14
+ * and rely on Serenity/JS to offer other sensible defaults:
15
+ *
16
+ * ```ts
17
+ * import { actorCalled } from '@serenity-js/core'
18
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
19
+ * import { Ensure, equals } from '@serenity-js/assertions'
20
+ *
21
+ * await actorCalled('Apisitt')
22
+ * .whoCan(
23
+ * CallAnApi.at('https://api.example.org/')
24
+ * )
25
+ * .attemptsTo(
26
+ * Send.a(GetRequest.to('/v1/users/2')), // GET https://api.example.org/v1/users/2
27
+ * Ensure.that(LastResponse.status(), equals(200)),
28
+ * )
29
+ * ```
30
+ *
31
+ * Please note that the following Serenity/JS test runner adapters already provide the ability to `CallAnApi` as part of their default configuration,
32
+ * so you don't need to configure it yourself:
33
+ * - [Playwright Test](https://serenity-js.org/handbook/test-runners/playwright-test/)
34
+ * - [WebdriverIO](https://serenity-js.org/handbook/test-runners/webdriverio/)
35
+ * - [Protractor](https://serenity-js.org/handbook/test-runners/protractor/)
36
+ *
37
+ * ### Resolving relative URLs
38
+ *
39
+ * Serenity/JS resolves request URLs using Node.js [WHATWG URL API](https://nodejs.org/api/url.html#new-urlinput-base).
40
+ * This means that the request URL is determined using the resource path resolved in the context of base URL, i.e. `new URL(resourcePath, [baseURL])`.
41
+ *
42
+ * Consider the following example:
43
+ *
44
+ * ```ts
45
+ * import { actorCalled } from '@serenity-js/core'
46
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
47
+ * import { Ensure, equals } from '@serenity-js/assertions'
48
+ *
49
+ * await actorCalled('Apisitt')
50
+ * .whoCan(
51
+ * CallAnApi.at(baseURL)
52
+ * )
53
+ * .attemptsTo(
54
+ * Send.a(GetRequest.to(resourcePath)),
55
+ * Ensure.that(LastResponse.status(), equals(200)),
56
+ * )
57
+ * ```
58
+ *
59
+ * In the above example:
60
+ * - when `resourcePath` is defined as a full URL, it overrides the base URL
61
+ * - when `resourcePath` starts with a forward slash `/`, it replaces any path defined in the base URL
62
+ * - when `resourcePath` is not a full URL and doesn't start with a forward slash, it gets appended to the base URL
63
+ *
64
+ * | baseURL | resourcePath | result |
65
+ * | ----------------------------- | -------------------------- | ------------------------------------ |
66
+ * | `https://api.example.org/` | `/v1/users/2` | `https://api.example.org/v1/users/2` |
67
+ * | `https://example.org/api/v1/` | `users/2` | `https://example.org/api/v1/users/2` |
68
+ * | `https://example.org/api/v1/` | `/secure/oauth` | `https://example.org/secure/oauth` |
69
+ * | `https://v1.example.org/api/` | `https://v2.example.org/` | `https://v2.example.org/` |
70
+ *
71
+ * ### Using Axios configuration object
72
+ *
73
+ * When you need more control over how your Axios instance is configured, provide
74
+ * an [Axios configuration object](https://axios-http.com/docs/req_config). For example:
75
+ *
76
+ * ```ts
77
+ * import { actorCalled } from '@serenity-js/core'
78
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
79
+ * import { Ensure, equals } from '@serenity-js/assertions'
80
+ *
81
+ * await actorCalled('Apisitt')
82
+ * .whoCan(
83
+ * CallAnApi.using({
84
+ * baseURL: 'https://api.example.org/',
85
+ * timeout: 30_000,
86
+ * // ... other configuration options
87
+ * })
88
+ * )
89
+ * .attemptsTo(
90
+ * Send.a(GetRequest.to('/users/2')),
91
+ * Ensure.that(LastResponse.status(), equals(200)),
92
+ * )
93
+ * ```
94
+ *
95
+ * ## Working with proxy servers
96
+ *
97
+ * `CallAnApi` uses an approach described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
98
+ * to automatically detect proxy server configuration based on your environment variables.
99
+ *
100
+ * You can override this default proxy detection mechanism by providing your own proxy configuration object.
101
+ *
102
+ * ### Automatic proxy support
103
+ *
104
+ * When the URL you're sending the request to uses the HTTP protocol, Serenity/JS will automatically detect your proxy configuration based on the following environment variables:
105
+ * - `npm_config_http_proxy`
106
+ * - `http_proxy` and `HTTP_PROXY`
107
+ * - `npm_config_proxy`
108
+ * - `all_proxy`
109
+ *
110
+ * Similarly, when the request target URL uses the HTTPS protocol, the following environment variables are used instead:
111
+ * - `npm_config_https_proxy`
112
+ * - `https_proxy` and `HTTPS_PROXY`
113
+ * - `npm_config_proxy`
114
+ * - `all_proxy`
115
+ *
116
+ * Proxy configuration is ignored for both HTTP and HTTPS target URLs matching the proxy bypass rules defined in the following environment variables:
117
+ * - `npm_config_no_proxy`
118
+ * - `no_proxy` and `NO_PROXY`
119
+ *
120
+ * ### Custom proxy configuration
121
+ *
122
+ * To override the automatic proxy detection based on the environment variables, provide a proxy configuration object:
123
+ *
124
+ * ```ts
125
+ * import { actorCalled } from '@serenity-js/core'
126
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
127
+ * import { Ensure, equals } from '@serenity-js/assertions'
128
+ *
129
+ * await actorCalled('Apisitt')
130
+ * .whoCan(
131
+ * CallAnApi.using({
132
+ * baseURL: 'https://api.example.org/',
133
+ * proxy: {
134
+ * protocol: 'http',
135
+ * host: 'proxy.example.org',
136
+ * port: 9000,
137
+ * auth: { // optional
138
+ * username: 'proxy-username',
139
+ * password: 'proxy-password',
140
+ * },
141
+ * bypass: 'status.example.org, internal.example.org' // optional
142
+ * }
143
+ * // ... other configuration options
144
+ * })
145
+ * )
146
+ * .attemptsTo(
147
+ * Send.a(GetRequest.to('/users/2')),
148
+ * Ensure.that(LastResponse.status(), equals(200)),
149
+ * )
150
+ * ```
151
+ *
152
+ * Note that Serenity/JS uses [proxy-agents](https://github.com/TooTallNate/proxy-agents)
153
+ * and the approach described in ["Node.js Axios behind corporate proxies"](https://janmolak.com/node-js-axios-behind-corporate-proxies-8b17a6f31f9d)
154
+ * to work around [limited proxy support capabilities](https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+proxy) in Axios itself.
155
+ *
156
+ * ### Bypassing proxy configuration
157
+ *
158
+ * To bypass the proxy configuration for specific hostnames and IP addresses, you can either:
159
+ * - provide the `bypass` property in the proxy configuration object, or
160
+ * - use the `no_proxy` environment variable.
161
+ *
162
+ * The value of the `bypass` property or the `no_proxy` environment variable should be a comma-separated list of hostnames and IP addresses
163
+ * that should not be routed through the proxy server, for example: `.com, .serenity-js.org, .domain.com`.
164
+ *
165
+ * Note that setting the `bypass` property to `example.org` makes the requests to following URLs bypass the proxy server:
166
+ * - `api.example.org`
167
+ * - `sub.sub.example.org`
168
+ * - `example.org`
169
+ * - `my-example.org`
170
+ *
171
+ * :::info
172
+ * Serenity/JS doesn't currently support `bypass` rules expressed using CIDR notation, like `192.168.17.0/24`.
173
+ * Instead, it uses a simple comma-separated list of hostnames and IP addresses.
174
+ * If you need support for CIDR notation, please [raise an issue](https://github.com/serenity-js/serenity-js/issues).
175
+ * :::
176
+ *
177
+ * ### Using Axios instance with proxy support
178
+ *
179
+ * To have full control over the Axios instance used by the ability to `CallAnApi`, you can create it yourself
180
+ * and inject it into the ability.
181
+ * This approach allows you to still benefit from automated proxy detection in configuration, while taking advantage
182
+ * of the many [Axios plugins](https://www.npmjs.com/search?q=axios).
183
+ *
184
+ * ```ts
185
+ * import { actorCalled } from '@serenity-js/core'
186
+ * import { createAxios, CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
187
+ * import { Ensure, equals } from '@serenity-js/assertions'
188
+ *
189
+ * import axiosRetry from 'axios-retry'
190
+ *
191
+ * const instance = createAxios({ baseURL: 'https://api.example.org/' })
192
+ * axiosRetry(instance, { retries: 3 })
193
+ *
194
+ * await actorCalled('Apisitt')
195
+ * .whoCan(
196
+ * CallAnApi.using(instance)
197
+ * )
198
+ * .attemptsTo(
199
+ * Send.a(GetRequest.to('/users/2')),
200
+ * Ensure.that(LastResponse.status(), equals(200)),
201
+ * )
202
+ * ```
203
+ *
204
+ * ### Using raw Axios instance
205
+ *
206
+ * If you don't want Serenity/JS to enhance your Axios instance with proxy support, instantiate the ability to
207
+ * `CallAnApi` using its constructor directly.
208
+ * Note, however, that by using this approach you're taking the responsibility for all the aspects of configuring Axios.
209
+ *
210
+ * ```ts
211
+ * import { actorCalled } from '@serenity-js/core'
212
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
213
+ * import { Ensure, equals } from '@serenity-js/assertions'
214
+ *
215
+ * import { axiosCreate } from '@serenity-js/rest'
216
+ * import axiosRetry from 'axios-retry'
217
+ *
218
+ * const instance = axiosCreate({ baseURL: 'https://api.example.org/' })
219
+ * axiosRetry(instance, { retries: 3 })
220
+ *
221
+ * await actorCalled('Apisitt')
222
+ * .whoCan(
223
+ * new CallAnApi(instance) // using the constructor ensures your axios instance is not modified in any way.
224
+ * )
225
+ * .attemptsTo(
226
+ * // ...
227
+ * )
228
+ * ```
229
+ *
230
+ * ### Serenity/JS defaults
231
+ *
232
+ * When using [`CallAnApi.at`](https://serenity-js.org/api/rest/class/CallAnApi/#at) or [`CallAnApi.using`](https://serenity-js.org/api/rest/class/CallAnApi/#using) with a configuration object, Serenity/JS
233
+ * merges your [Axios request configuration](https://axios-http.com/docs/req_config) with the following defaults:
234
+ * - `timeout`: 10 seconds
235
+ *
236
+ *
237
+ * You can override them by specifying the given property in your configuration object, for example:
238
+ * ```ts
239
+ * import { actorCalled } from '@serenity-js/core'
240
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
241
+ * import { Ensure, equals } from '@serenity-js/assertions'
242
+ *
243
+ * await actorCalled('Apisitt')
244
+ * .whoCan(
245
+ * CallAnApi.using({
246
+ * baseURL: 'https://api.example.org/',
247
+ * timeout: 30_000
248
+ * })
249
+ * )
250
+ * .attemptsTo(
251
+ * Send.a(GetRequest.to('/users/2')),
252
+ * Ensure.that(LastResponse.status(), equals(200)),
253
+ * )
254
+ * ```
255
+ *
256
+ * ## Interacting with multiple APIs
257
+ *
258
+ * Some test scenarios might require you to interact with multiple HTTP APIs. With Serenity/JS you can do this
259
+ * using either API-specific actors, or by specifying full URLs when performing the requests.
260
+ *
261
+ * The following examples will assume that the test scenarios needs to interact with the following APIs:
262
+ * - `https://testdata.example.org/api/v1/`
263
+ * - `https://shop.example.org/api/v1/`
264
+ *
265
+ * Let's also assume that the `testdata` API allows the automation to manage the test data used by the `shop` API.
266
+ *
267
+ * ### Using API-specific actors
268
+ *
269
+ * To create API-specific actors, configure your [test runner](https://serenity-js.org/handbook/test-runners/) with a [cast](https://serenity-js.org/api/core/class/Cast/)
270
+ * that gives your actors appropriate abilities based, for example, on their name:
271
+ *
272
+ * ```ts
273
+ * import { beforeEach } from 'mocha'
274
+ * import { Actor, Cast, engage } from '@serenity-js/core'
275
+ * import { CallAnApi } from '@serenity-js/rest'
276
+ *
277
+ * export class MyActors implements Cast {
278
+ * prepare(actor: Actor): Actor {
279
+ * switch(actor.name) {
280
+ * case 'Ted':
281
+ * return actor.whoCan(CallAnApi.at('https://testdata.example.org/api/v1/'))
282
+ * case 'Shelly':
283
+ * return actor.whoCan(CallAnApi.at('https://shop.example.org/api/v1/'))
284
+ * default:
285
+ * return actor;
286
+ * }
287
+ * }
288
+ * }
289
+ *
290
+ * beforeEach(() => engage(new MyActors()))
291
+ * ```
292
+ *
293
+ * Next, retrieve the appropriate actor in your test scenario using [`actorCalled`](https://serenity-js.org/api/core/function/actorCalled/), for example:
294
+ *
295
+ * ```ts
296
+ * import { describe, it, beforeEach } from 'mocha'
297
+ * import { actorCalled, engage } from '@serenity-js/core
298
+ * import { Send, GetRequest, PostRequest, LastResponse } from '@serenity-js/rest'
299
+ * import { Ensure, equals } from '@serenity-js/assertions'
300
+ *
301
+ * describe('Multi-actor API testing', () => {
302
+ * beforeEach(() => engage(new MyActors()))
303
+ *
304
+ * it('allows each actor to interact with their API', async () => {
305
+ *
306
+ * await actorCalled('Ted').attemptsTo(
307
+ * Send.a(PostRequest.to('products').with({ name: 'Apples', price: '£2.50' })),
308
+ * Ensure.that(LastResponse.status(), equals(201)),
309
+ * )
310
+ *
311
+ * await actorCalled('Shelly').attemptsTo(
312
+ * Send.a(GetRequest.to('?product=Apples')),
313
+ * Ensure.that(LastResponse.status(), equals(200)),
314
+ * Ensure.that(LastResponse.body(), equals([
315
+ * { name: 'Apples', price: '£2.50' }
316
+ * ])),
317
+ * )
318
+ * })
319
+ * })
320
+ * ```
321
+ *
322
+ * ### Using full URLs
323
+ *
324
+ * If you prefer to have a single actor interacting with multiple APIs, you can specify the full URL for every request:
325
+ *
326
+ * ```ts
327
+ * import { describe, it, beforeEach } from 'mocha'
328
+ * import { actorCalled, Cast, engage } from '@serenity-js/core
329
+ * import { CallAnApi, Send, GetRequest, PostRequest, LastResponse } from '@serenity-js/rest'
330
+ * import { Ensure, equals } from '@serenity-js/assertions'
331
+ *
332
+ * describe('Multi-actor API testing', () => {
333
+ * beforeEach(() => engage(
334
+ * Cast.where(actor => actor.whoCan(CallAnApi.using({})))
335
+ * ))
336
+ *
337
+ * it('allows each actor to interact with their API', async () => {
338
+ *
339
+ * await actorCalled('Alice').attemptsTo(
340
+ * Send.a(PostRequest.to('https://testdata.example.org/api/v1/products')
341
+ * .with({ name: 'Apples', price: '£2.50' })),
342
+ * Ensure.that(LastResponse.status(), equals(201)),
343
+ *
344
+ * Send.a(GetRequest.to('https://shop.example.org/api/v1/?product=Apples')),
345
+ * Ensure.that(LastResponse.status(), equals(200)),
346
+ * Ensure.that(LastResponse.body(), equals([
347
+ * { name: 'Apples', price: '£2.50' }
348
+ * ])),
349
+ * )
350
+ * })
351
+ * })
352
+ * ```
353
+ *
354
+ * ## Learn more
355
+ * - [Axios: Configuring requests](https://axios-http.com/docs/req_config)
356
+ * - [MDN: HTTP methods documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
357
+ *
358
+ * @group Abilities
359
+ */
360
+ export class CallAnApi extends Ability {
361
+ axiosInstance;
362
+ lastResponse;
363
+ /**
364
+ * Produces an [ability](https://serenity-js.org/api/core/class/Ability/) to call a REST API at a specified `baseURL`;
365
+ *
366
+ * This is the same as invoking `CallAnApi.using({ baseURL: 'https://example.org' })`
367
+ *
368
+ * @param baseURL
369
+ */
370
+ static at(baseURL) {
371
+ return CallAnApi.using({
372
+ baseURL: baseURL instanceof URL
373
+ ? baseURL.toString()
374
+ : baseURL
375
+ });
376
+ }
377
+ /**
378
+ * Produces an [ability](https://serenity-js.org/api/core/class/Ability/) to call an HTTP API using the given Axios instance,
379
+ * or an Axios request configuration object.
380
+ *
381
+ * When you provide an [Axios configuration object](https://axios-http.com/docs/req_config),
382
+ * it gets shallow-merged with the following defaults:
383
+ * - request timeout of 10 seconds
384
+ * - automatic proxy support based on
385
+ * your [environment variables](https://www.npmjs.com/package/proxy-from-env#environment-variables)
386
+ *
387
+ * When you provide an Axios instance, it's enhanced with proxy support and no other modifications are made.
388
+ *
389
+ * If you don't want Serenity/JS to augment or modify your Axios instance in any way,
390
+ * please use the [`CallAnApi.constructor`](https://serenity-js.org/api/rest/class/CallAnApi/#constructor) directly.
391
+ *
392
+ * @param axiosInstanceOrConfig
393
+ */
394
+ static using(axiosInstanceOrConfig) {
395
+ return new CallAnApi(createAxios(axiosInstanceOrConfig));
396
+ }
397
+ /**
398
+ * #### Learn more
399
+ * - [AxiosInstance](https://axios-http.com/docs/instance)
400
+ *
401
+ * @param axiosInstance
402
+ * A pre-configured instance of the Axios HTTP client
403
+ */
404
+ constructor(axiosInstance) {
405
+ super();
406
+ this.axiosInstance = axiosInstance;
407
+ }
408
+ /**
409
+ * Allows for the original Axios config to be changed after
410
+ * the [ability](https://serenity-js.org/api/core/class/Ability/) to [`CallAnApi`](https://serenity-js.org/api/rest/class/CallAnApi/)
411
+ * has been instantiated and given to the [`Actor`](https://serenity-js.org/api/core/class/Actor/).
412
+ *
413
+ * #### Learn more
414
+ * - [AxiosRequestConfig](https://axios-http.com/docs/req_config)
415
+ *
416
+ * @param fn
417
+ */
418
+ modifyConfig(fn) {
419
+ fn(this.axiosInstance.defaults);
420
+ }
421
+ /**
422
+ * Sends an HTTP request to a specified url.
423
+ * Response will be cached and available via [`CallAnApi.mapLastResponse`](https://serenity-js.org/api/rest/class/CallAnApi/#mapLastResponse).
424
+ *
425
+ * #### Learn more
426
+ * - [AxiosRequestConfig](https://axios-http.com/docs/req_config)
427
+ * - [AxiosResponse](https://axios-http.com/docs/res_schema)
428
+ *
429
+ * @param config
430
+ * Axios request configuration, which can be used to override the defaults
431
+ * provided when the [ability](https://serenity-js.org/api/core/class/Ability/)
432
+ * to [`CallAnApi`](https://serenity-js.org/api/rest/class/CallAnApi/) was instantiated.
433
+ */
434
+ async request(config) {
435
+ let url;
436
+ try {
437
+ url = this.resolveUrl(config);
438
+ this.lastResponse = await this.axiosInstance.request({
439
+ ...config,
440
+ url,
441
+ });
442
+ return this.lastResponse;
443
+ }
444
+ catch (error) {
445
+ const description = `${config.method.toUpperCase()} ${url || config.url}`;
446
+ switch (true) {
447
+ case /timeout.*exceeded/.test(error.message):
448
+ throw new TestCompromisedError(`The request has timed out: ${description}`, error);
449
+ case /Network Error/.test(error.message):
450
+ throw new TestCompromisedError(`A network error has occurred: ${description}`, error);
451
+ case error instanceof TypeError:
452
+ throw new ConfigurationError(`Looks like there was an issue with Axios configuration`, error);
453
+ case !error.response:
454
+ throw new TestCompromisedError(`The API call has failed: ${description}`, error);
455
+ default:
456
+ this.lastResponse = error.response;
457
+ return error.response;
458
+ }
459
+ }
460
+ }
461
+ /**
462
+ * Resolves the final URL, based on the [`AxiosRequestConfig`](https://axios-http.com/docs/req_config) provided
463
+ * and any defaults that the [`AxiosInstance`](https://axios-http.com/docs/instance) has been configured with.
464
+ *
465
+ * Note that unlike Axios, this method uses the Node.js [WHATWG URL API](https://nodejs.org/api/url.html#new-urlinput-base)
466
+ * to ensure URLs are correctly resolved.
467
+ *
468
+ * @param config
469
+ */
470
+ resolveUrl(config) {
471
+ const baseURL = this.axiosInstance.defaults.baseURL || config.baseURL;
472
+ return baseURL
473
+ ? new URL(config.url, baseURL).toString()
474
+ : config.url;
475
+ }
476
+ /**
477
+ * Maps the last cached response to another type.
478
+ * Useful when you need to extract a portion of the [`AxiosResponse`](https://axios-http.com/docs/res_schema) object.
479
+ *
480
+ * #### Learn more
481
+ * - [AxiosResponse](https://axios-http.com/docs/res_schema)
482
+ *
483
+ * @param mappingFunction
484
+ */
485
+ mapLastResponse(mappingFunction) {
486
+ if (!this.lastResponse) {
487
+ throw new LogicError(`Make sure to perform a HTTP API call before checking on the response`);
488
+ }
489
+ return mappingFunction(this.lastResponse);
490
+ }
491
+ toJSON() {
492
+ const simplifiedConfig = {
493
+ baseURL: this.axiosInstance.defaults.baseURL,
494
+ headers: this.axiosInstance.defaults.headers,
495
+ timeout: this.axiosInstance.defaults.timeout,
496
+ proxy: proxyConfigFrom(this.axiosInstance.defaults),
497
+ };
498
+ return {
499
+ ...super.toJSON(),
500
+ options: {
501
+ ...recursivelyRemove([isUndefined, isEmptyObject], simplifiedConfig),
502
+ }
503
+ };
504
+ }
505
+ }
506
+ function proxyConfigFrom(defaults) {
507
+ if (defaults.proxy === undefined) {
508
+ return undefined;
509
+ }
510
+ if (!(defaults.proxy === false && defaults.httpAgent instanceof Agent)) {
511
+ return undefined;
512
+ }
513
+ const proxyUrl = defaults.httpAgent.getProxyForUrl(defaults.baseURL);
514
+ try {
515
+ const url = new URL(proxyUrl);
516
+ return {
517
+ protocol: url.protocol?.replace(/:$/, ''),
518
+ host: url.hostname,
519
+ port: url.port ? Number(url.port) : undefined,
520
+ auth: url.username
521
+ ? {
522
+ username: url.username || undefined,
523
+ password: url.password || undefined,
524
+ }
525
+ : undefined,
526
+ };
527
+ }
528
+ catch {
529
+ return undefined;
530
+ }
531
+ }
532
+ function isUndefined(value) {
533
+ return value === undefined;
534
+ }
535
+ function isEmptyObject(value) {
536
+ return isObject(value) && Object.keys(value).length === 0;
537
+ }
538
+ function recursivelyRemove(matchers, value) {
539
+ if (Array.isArray(value)) {
540
+ return value.map(item => recursivelyRemove(matchers, item));
541
+ }
542
+ if (typeof value === 'object' && value !== null) {
543
+ return Object.keys(value).reduce((acc, key) => {
544
+ if (matchers.some(matcher => matcher(value[key]))) {
545
+ return acc;
546
+ }
547
+ return {
548
+ ...acc,
549
+ [key]: recursivelyRemove(matchers, value[key]),
550
+ };
551
+ }, {});
552
+ }
553
+ return value;
554
+ }
555
+ //# sourceMappingURL=CallAnApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CallAnApi.js","sourceRoot":"","sources":["../../../src/screenplay/abilities/CallAnApi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './CallAnApi.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screenplay/abilities/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './CallAnApi.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/screenplay/abilities/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './abilities/index.js';
2
+ export * from './interactions/index.js';
3
+ export * from './models/index.js';
4
+ export * from './questions/index.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/screenplay/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './abilities/index.js';
2
+ export * from './interactions/index.js';
3
+ export * from './models/index.js';
4
+ export * from './questions/index.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/screenplay/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC"}