@serenity-js/rest 3.0.0-rc.9 → 3.0.1

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 (127) hide show
  1. package/CHANGELOG.md +81 -1852
  2. package/README.md +8 -10
  3. package/lib/index.d.ts +2 -1
  4. package/lib/index.d.ts.map +1 -0
  5. package/lib/index.js +6 -2
  6. package/lib/index.js.map +1 -1
  7. package/lib/models/DeleteRequest.d.ts +66 -0
  8. package/lib/models/DeleteRequest.d.ts.map +1 -0
  9. package/lib/models/DeleteRequest.js +73 -0
  10. package/lib/models/DeleteRequest.js.map +1 -0
  11. package/lib/models/GetRequest.d.ts +73 -0
  12. package/lib/models/GetRequest.d.ts.map +1 -0
  13. package/lib/models/GetRequest.js +80 -0
  14. package/lib/models/GetRequest.js.map +1 -0
  15. package/lib/models/HTTPRequest.d.ts +48 -0
  16. package/lib/models/HTTPRequest.d.ts.map +1 -0
  17. package/lib/{model → models}/HTTPRequest.js +14 -23
  18. package/lib/models/HTTPRequest.js.map +1 -0
  19. package/lib/models/HeadRequest.d.ts +58 -0
  20. package/lib/models/HeadRequest.d.ts.map +1 -0
  21. package/lib/models/HeadRequest.js +65 -0
  22. package/lib/models/HeadRequest.js.map +1 -0
  23. package/lib/models/OptionsRequest.d.ts +61 -0
  24. package/lib/models/OptionsRequest.d.ts.map +1 -0
  25. package/lib/models/OptionsRequest.js +68 -0
  26. package/lib/models/OptionsRequest.js.map +1 -0
  27. package/lib/models/PatchRequest.d.ts +65 -0
  28. package/lib/models/PatchRequest.d.ts.map +1 -0
  29. package/lib/models/PatchRequest.js +74 -0
  30. package/lib/models/PatchRequest.js.map +1 -0
  31. package/lib/models/PostRequest.d.ts +105 -0
  32. package/lib/models/PostRequest.d.ts.map +1 -0
  33. package/lib/models/PostRequest.js +114 -0
  34. package/lib/models/PostRequest.js.map +1 -0
  35. package/lib/models/PutRequest.d.ts +75 -0
  36. package/lib/models/PutRequest.d.ts.map +1 -0
  37. package/lib/models/PutRequest.js +84 -0
  38. package/lib/models/PutRequest.js.map +1 -0
  39. package/lib/{model → models}/index.d.ts +1 -0
  40. package/lib/models/index.d.ts.map +1 -0
  41. package/lib/{model → models}/index.js +5 -1
  42. package/lib/models/index.js.map +1 -0
  43. package/lib/screenplay/abilities/CallAnApi.d.ts +88 -99
  44. package/lib/screenplay/abilities/CallAnApi.d.ts.map +1 -0
  45. package/lib/screenplay/abilities/CallAnApi.js +94 -107
  46. package/lib/screenplay/abilities/CallAnApi.js.map +1 -1
  47. package/lib/screenplay/abilities/index.d.ts +1 -0
  48. package/lib/screenplay/abilities/index.d.ts.map +1 -0
  49. package/lib/screenplay/abilities/index.js +5 -1
  50. package/lib/screenplay/abilities/index.js.map +1 -1
  51. package/lib/screenplay/index.d.ts +1 -0
  52. package/lib/screenplay/index.d.ts.map +1 -0
  53. package/lib/screenplay/index.js +5 -1
  54. package/lib/screenplay/index.js.map +1 -1
  55. package/lib/screenplay/interactions/ChangeApiConfig.d.ts +96 -95
  56. package/lib/screenplay/interactions/ChangeApiConfig.d.ts.map +1 -0
  57. package/lib/screenplay/interactions/ChangeApiConfig.js +98 -107
  58. package/lib/screenplay/interactions/ChangeApiConfig.js.map +1 -1
  59. package/lib/screenplay/interactions/Send.d.ts +24 -41
  60. package/lib/screenplay/interactions/Send.d.ts.map +1 -0
  61. package/lib/screenplay/interactions/Send.js +37 -51
  62. package/lib/screenplay/interactions/Send.js.map +1 -1
  63. package/lib/screenplay/interactions/index.d.ts +1 -1
  64. package/lib/screenplay/interactions/index.d.ts.map +1 -0
  65. package/lib/screenplay/interactions/index.js +5 -2
  66. package/lib/screenplay/interactions/index.js.map +1 -1
  67. package/lib/screenplay/questions/LastResponse.d.ts +152 -98
  68. package/lib/screenplay/questions/LastResponse.d.ts.map +1 -0
  69. package/lib/screenplay/questions/LastResponse.js +149 -97
  70. package/lib/screenplay/questions/LastResponse.js.map +1 -1
  71. package/lib/screenplay/questions/index.d.ts +1 -0
  72. package/lib/screenplay/questions/index.d.ts.map +1 -0
  73. package/lib/screenplay/questions/index.js +5 -1
  74. package/lib/screenplay/questions/index.js.map +1 -1
  75. package/package.json +20 -43
  76. package/src/index.ts +1 -1
  77. package/src/models/DeleteRequest.ts +73 -0
  78. package/src/models/GetRequest.ts +80 -0
  79. package/src/{model → models}/HTTPRequest.ts +17 -26
  80. package/src/models/HeadRequest.ts +65 -0
  81. package/src/models/OptionsRequest.ts +68 -0
  82. package/src/models/PatchRequest.ts +75 -0
  83. package/src/models/PostRequest.ts +115 -0
  84. package/src/models/PutRequest.ts +85 -0
  85. package/src/screenplay/abilities/CallAnApi.ts +90 -108
  86. package/src/screenplay/interactions/ChangeApiConfig.ts +99 -111
  87. package/src/screenplay/interactions/Send.ts +46 -61
  88. package/src/screenplay/interactions/index.ts +0 -1
  89. package/src/screenplay/questions/LastResponse.ts +153 -100
  90. package/tsconfig.build.json +10 -0
  91. package/lib/model/DeleteRequest.d.ts +0 -63
  92. package/lib/model/DeleteRequest.js +0 -70
  93. package/lib/model/DeleteRequest.js.map +0 -1
  94. package/lib/model/GetRequest.d.ts +0 -70
  95. package/lib/model/GetRequest.js +0 -77
  96. package/lib/model/GetRequest.js.map +0 -1
  97. package/lib/model/HTTPRequest.d.ts +0 -56
  98. package/lib/model/HTTPRequest.js.map +0 -1
  99. package/lib/model/HeadRequest.d.ts +0 -55
  100. package/lib/model/HeadRequest.js +0 -62
  101. package/lib/model/HeadRequest.js.map +0 -1
  102. package/lib/model/OptionsRequest.d.ts +0 -58
  103. package/lib/model/OptionsRequest.js +0 -65
  104. package/lib/model/OptionsRequest.js.map +0 -1
  105. package/lib/model/PatchRequest.d.ts +0 -65
  106. package/lib/model/PatchRequest.js +0 -74
  107. package/lib/model/PatchRequest.js.map +0 -1
  108. package/lib/model/PostRequest.d.ts +0 -102
  109. package/lib/model/PostRequest.js +0 -111
  110. package/lib/model/PostRequest.js.map +0 -1
  111. package/lib/model/PutRequest.d.ts +0 -75
  112. package/lib/model/PutRequest.js +0 -84
  113. package/lib/model/PutRequest.js.map +0 -1
  114. package/lib/model/index.js.map +0 -1
  115. package/lib/screenplay/interactions/ChangeApiUrl.d.ts +0 -82
  116. package/lib/screenplay/interactions/ChangeApiUrl.js +0 -97
  117. package/lib/screenplay/interactions/ChangeApiUrl.js.map +0 -1
  118. package/src/model/DeleteRequest.ts +0 -71
  119. package/src/model/GetRequest.ts +0 -78
  120. package/src/model/HeadRequest.ts +0 -63
  121. package/src/model/OptionsRequest.ts +0 -66
  122. package/src/model/PatchRequest.ts +0 -76
  123. package/src/model/PostRequest.ts +0 -113
  124. package/src/model/PutRequest.ts +0 -86
  125. package/src/screenplay/interactions/ChangeApiUrl.ts +0 -97
  126. package/tsconfig.eslint.json +0 -10
  127. /package/src/{model → models}/index.ts +0 -0
@@ -1,65 +1,54 @@
1
1
  import { Answerable, AnswersQuestions, CollectsArtifacts, Interaction, UsesAbilities } from '@serenity-js/core';
2
2
  import { Artifact, HTTPRequestResponse, Name, RequestAndResponse } from '@serenity-js/core/lib/model';
3
- import { AxiosRequestConfig, AxiosResponse } from 'axios';
3
+ import { AxiosHeaders, AxiosRequestConfig, AxiosResponse, AxiosResponseHeaders, RawAxiosResponseHeaders } from 'axios';
4
4
 
5
5
  import { CallAnApi } from '../abilities';
6
6
 
7
7
  /**
8
- * @desc
9
- * Sends a {@link HTTPRequest} to a specified url.
10
- * The response to the request is made available via the {@link LastResponse}
11
- * {@link @serenity-js/core/lib/screenplay~Question}s.
8
+ * Sends a {@apilink HTTPRequest} to a specified url.
12
9
  *
13
- * @example <caption>Send a GET request</caption>
14
- * import { Actor } from '@serenity-js/core';
15
- * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
16
- * import { Ensure, equals } from '@serenity-js/assertions';
10
+ * The response to the request is made available via {@apilink LastResponse}.
17
11
  *
18
- * const actor = Actor.named('Apisit').whoCan(CallAnApi.at('https://myapp.com/api'));
12
+ * ## Send a GET request
19
13
  *
20
- * actor.attemptsTo(
21
- * Send.a(GetRequest.to('/books/0-688-00230-7')),
22
- * Ensure.that(LastResponse.status(), equals(200)),
23
- * );
14
+ * ```ts
15
+ * import { actorCalled } from '@serenity-js/core'
16
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
17
+ * import { Ensure, equals } from '@serenity-js/assertions'
24
18
  *
25
- * @extends {Interaction}
19
+ * await actorCalled('Apisit')
20
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
21
+ * .attemptsTo(
22
+ * Send.a(GetRequest.to('/books/0-688-00230-7')),
23
+ * Ensure.that(LastResponse.status(), equals(200)),
24
+ * )
25
+ * ```
26
+ *
27
+ * @group Activities
26
28
  */
27
29
  export class Send extends Interaction {
28
30
 
29
31
  /**
30
- * @desc
31
- * Instantiates a new {@link Send} {@link @serenity-js/core/lib/screenplay~Interaction}.
32
+ * Instantiates a new {@apilink Interaction|interaction} to {@apilink Send}.
32
33
  *
33
- * @param {@serenity-js/lib/core/screenplay~Answerable<AxiosRequestConfig>} request
34
- * @returns {@serenity-js/core/lib/screenplay~Interaction}
34
+ * #### Learn more
35
+ * - [AxiosRequestConfig](https://github.com/axios/axios/blob/v0.27.2/index.d.ts#L75-L113)
35
36
  *
36
- * @see {@link AxiosRequestConfig}
37
+ * @param request
37
38
  */
38
39
  static a(request: Answerable<AxiosRequestConfig>): Interaction {
39
40
  return new Send(request);
40
41
  }
41
42
 
42
43
  /**
43
- * @param {@serenity-js/core/lib/screenplay~Answerable<AxiosRequestConfig>} request
44
- *
45
- * @see {@link AxiosRequestConfig}
44
+ * @param request
46
45
  */
47
- constructor(private readonly request: Answerable<AxiosRequestConfig>) {
48
- super();
46
+ protected constructor(private readonly request: Answerable<AxiosRequestConfig>) {
47
+ super(`#actor sends ${ request.toString() }`);
49
48
  }
50
49
 
51
50
  /**
52
- * @desc
53
- * Makes the provided {@link @serenity-js/core/lib/screenplay/actor~Actor}
54
- * perform this {@link @serenity-js/core/lib/screenplay~Interaction}.
55
- *
56
- * @param {UsesAbilities & CollectsArtifacts & AnswersQuestions} actor
57
- * @returns {Promise<void>}
58
- *
59
- * @see {@link @serenity-js/core/lib/screenplay/actor~Actor}
60
- * @see {@link @serenity-js/core/lib/screenplay/actor~UsesAbilities}
61
- * @see {@link @serenity-js/core/lib/screenplay/actor~CollectsArtifacts}
62
- * @see {@link @serenity-js/core/lib/screenplay/actor~AnswersQuestions}
51
+ * @inheritDoc
63
52
  */
64
53
  performAs(actor: UsesAbilities & CollectsArtifacts & AnswersQuestions): Promise<void> {
65
54
  const callAnApi = CallAnApi.as(actor);
@@ -77,32 +66,28 @@ export class Send extends Interaction {
77
66
  );
78
67
  }
79
68
 
80
- /**
81
- * @desc
82
- * Generates a description to be used when reporting this {@link @serenity-js/core/lib/screenplay~Activity}.
83
- *
84
- * @returns {string}
85
- */
86
- toString(): string {
87
- return `#actor sends ${ this.request.toString() }`;
88
- }
89
-
90
69
  private responseToArtifact(targetUrl: string, response: AxiosResponse): Artifact {
91
- const
92
- request: AxiosRequestConfig = response.config,
93
- requestAndResponse: RequestAndResponse = {
94
- request: {
95
- method: request.method,
96
- url: targetUrl,
97
- headers: request.headers,
98
- data: request.data,
99
- },
100
- response: {
101
- status: response.status,
102
- headers: response.headers,
103
- data: response.data,
104
- },
105
- };
70
+ const request: AxiosRequestConfig = response.config;
71
+
72
+ const axiosRequestHeaders = request.headers;
73
+ const requestHeaders: Record<string, string | number | boolean> = AxiosHeaders.from(axiosRequestHeaders).toJSON(true) as Record<string, string | number | boolean>;
74
+
75
+ const axiosResponseHeaders: RawAxiosResponseHeaders | AxiosResponseHeaders = response.headers;
76
+ const responseHeaders = AxiosHeaders.from(axiosResponseHeaders).toJSON(false) as RawAxiosResponseHeaders;
77
+
78
+ const requestAndResponse: RequestAndResponse = {
79
+ request: {
80
+ method: request.method,
81
+ url: targetUrl,
82
+ headers: requestHeaders,
83
+ data: request.data,
84
+ },
85
+ response: {
86
+ status: response.status,
87
+ headers: responseHeaders as unknown as Record<string, string> & { 'set-cookie'?: string[] },
88
+ data: response.data,
89
+ },
90
+ };
106
91
 
107
92
  return HTTPRequestResponse.fromJSON(requestAndResponse);
108
93
  }
@@ -1,3 +1,2 @@
1
1
  export * from './ChangeApiConfig';
2
- export * from './ChangeApiUrl';
3
2
  export * from './Send';
@@ -1,66 +1,77 @@
1
1
  import { Question, QuestionAdapter } from '@serenity-js/core';
2
+ import { RawAxiosResponseHeaders } from 'axios';
2
3
 
3
4
  import { CallAnApi } from '../abilities';
4
5
 
5
6
  /**
6
- * @desc
7
- * Provides access to the properties of the last {@link AxiosResponse} object,
8
- * cached on the {@link CallAnApi} {@link @serenity-js/core/lib/screenplay~Ability}.
7
+ * Provides access to the properties of the last {@apilink AxiosResponse} object,
8
+ * cached on the {@apilink Ability|ability} to {@apilink CallAnApi}.
9
9
  *
10
- * @example <caption>Verify response to a GET request</caption>
11
- * import { Actor } from '@serenity-js/core';
12
- * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
13
- * import { Ensure, equals } from '@serenity-js/assertions';
10
+ * ## Verify response to a GET request
14
11
  *
15
- * interface Book {
16
- * title: string;
17
- * author: string
18
- * }
12
+ * ```ts
13
+ * import { actorCalled } from '@serenity-js/core'
14
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
15
+ * import { Ensure, equals } from '@serenity-js/assertions'
19
16
  *
20
- * const actor = Actor.named('Apisit').whoCan(CallAnApi.at('https://myapp.com/api'));
17
+ * interface Book {
18
+ * title: string;
19
+ * author: string;
20
+ * }
21
21
  *
22
- * actor.attemptsTo(
23
- * Send.a(GetRequest.to('/books/0-688-00230-7')),
24
- * Ensure.that(LastResponse.status(), equals(200)),
25
- * Ensure.that(LastResponse.header('Content-Type'), equals('application/json')),
26
- * Ensure.that(LastResponse.body<Book>(), equals({
27
- * title: 'Zen and the Art of Motorcycle Maintenance: An Inquiry into Values',
28
- * author: 'Robert M. Pirsig',
29
- * })),
30
- * );
22
+ * await actorCalled('Apisit')
23
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
24
+ * .attemptsTo(
25
+ * Send.a(GetRequest.to('/books/0-688-00230-7')),
26
+ * Ensure.that(LastResponse.status(), equals(200)),
27
+ * Ensure.that(LastResponse.header('Content-Type'), equals('application/json')),
28
+ * Ensure.that(LastResponse.body<Book>(), equals({
29
+ * title: 'Zen and the Art of Motorcycle Maintenance: An Inquiry into Values',
30
+ * author: 'Robert M. Pirsig',
31
+ * })),
32
+ * )
33
+ * ```
31
34
  *
32
- * @example <caption>Use Serenity/JS adapters to navigate complex response objects</caption>
33
- * import { Actor } from '@serenity-js/core';
34
- * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
35
- * import { Ensure, equals } from '@serenity-js/assertions';
35
+ * ## Use Serenity/JS adapters to navigate complex response objects
36
36
  *
37
- * interface Developer {
38
- * name: string;
39
- * id: string;
40
- * projects: Project[];
41
- * }
37
+ * ```ts
38
+ * import { actorCalled } from '@serenity-js/core'
39
+ * import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
40
+ * import { Ensure, equals } from '@serenity-js/assertions'
42
41
  *
43
- * interface Project {
44
- * name: string;
45
- * repoUrl: string;
46
- * }
42
+ * interface Developer {
43
+ * name: string;
44
+ * id: string;
45
+ * projects: Project[];
46
+ * }
47
47
  *
48
- * const actor = Actor.named('Apisit').whoCan(CallAnApi.at('https://myapp.com/api'));
48
+ * interface Project {
49
+ * name: string;
50
+ * repoUrl: string;
51
+ * }
49
52
  *
50
- * actor.attemptsTo(
51
- * Send.a(GetRequest.to('/developers/jan-molak')),
52
- * Ensure.that(LastResponse.status(), equals(200)),
53
- * Ensure.that(LastResponse.body<Developer>().name, equals('Jan Molak')),
54
- * Ensure.that(LastResponse.body<Developer>().projects[0].name, equals('Serenity/JS')),
55
- * );
53
+ * await actorCalled('Apisitt')
54
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
55
+ * .attemptsTo(
56
+ * Send.a(GetRequest.to('/developers/jan-molak')),
57
+ * Ensure.that(LastResponse.status(), equals(200)),
58
+ * Ensure.that(LastResponse.body<Developer>().name, equals('Jan Molak')),
59
+ * Ensure.that(LastResponse.body<Developer>().projects[0].name, equals('Serenity/JS')),
60
+ * )
61
+ * ```
62
+ *
63
+ * ## Learn more
64
+ * - [AxiosResponse](https://github.com/axios/axios/blob/v0.27.2/index.d.ts#L133-L140)
65
+ *
66
+ * @group Questions
56
67
  */
57
68
  export class LastResponse {
58
69
 
59
70
  /**
60
- * @desc
61
- * Enables asserting on the {@link LastResponse} status
71
+ * Retrieves the status code of the {@apilink LastResponse|last response}
62
72
  *
63
- * @returns {@serenity-js/core/lib/screenplay~Question<number>}
73
+ * #### Learn more
74
+ * - [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
64
75
  */
65
76
  static status(): QuestionAdapter<number> {
66
77
  return Question.about<number>(`the status of the last response`, async actor => {
@@ -69,60 +80,78 @@ export class LastResponse {
69
80
  }
70
81
 
71
82
  /**
72
- * @desc
73
- * Enables asserting on the {@link LastResponse} body
83
+ * Retrieves the body of the {@apilink LastResponse|last response}
84
+ *
85
+ * #### A type-safe approach using generics
74
86
  *
75
- * @example <caption>A type-safe approach using generics</caption>
76
- * interface Book {
77
- * title: string;
78
- * author: string
79
- * }
87
+ * ```ts
88
+ * import { actorCalled } from '@serenity-js/core'
89
+ * import { CallAnApi, LastResponse } from '@serenity-js/rest'
90
+ * import { Ensure, equals } from '@serenity-js/assertions'
80
91
  *
81
- * actor.attemptsTo(
92
+ * interface Book {
93
+ * title: string;
94
+ * author: string;
95
+ * }
96
+ *
97
+ * await actorCalled('Apisitt')
98
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
99
+ * .attemptsTo(
82
100
  * // ...
101
+ *
102
+ * // note body<T>() parameterised with type "Book"
83
103
  * Ensure.that(LastResponse.body<Book>(), equals({
84
- * title: 'Zen and the Art of Motorcycle Maintenance: An Inquiry into Values',
85
- * author: 'Robert M. Pirsig',
104
+ * title: 'Zen and the Art of Motorcycle Maintenance: An Inquiry into Values',
105
+ * author: 'Robert M. Pirsig',
86
106
  * })),
87
- * );
107
+ * )
108
+ * ```
88
109
  *
89
- * @example <caption>A non-type-safe approach using `any`</caption>
90
- * actor.attemptsTo(
110
+ * ## A not type-safe approach using `any`
111
+ *
112
+ * ```ts
113
+ * import { actorCalled } from '@serenity-js/core'
114
+ * import { CallAnApi, LastResponse } from '@serenity-js/rest'
115
+ * import { Ensure, equals } from '@serenity-js/assertions'
116
+ *
117
+ * await actorCalled('Apisitt')
118
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
119
+ * .attemptsTo(
91
120
  * // ...
121
+ *
122
+ * // note body<T>() parameterised with "any" or with no parameter is not type-safe!
92
123
  * Ensure.that(LastResponse.body<any>(), equals({
93
- * title: 'Zen and the Art of Motorcycle Maintenance: An Inquiry into Values',
94
- * author: 'Robert M. Pirsig',
124
+ * title: 'Zen and the Art of Motorcycle Maintenance: An Inquiry into Values',
125
+ * author: 'Robert M. Pirsig',
95
126
  * })),
96
- * );
97
- *
98
- * @example <caption>Retrieving an item at path using Property.of</caption>
99
- * import { Property } from '@serenity-js/core';
100
- *
101
- * actor.attemptsTo(
102
- * Ensure.that(
103
- * Property.of(LastResponse.body<Book>()).title,
104
- * equals('Zen and the Art of Motorcycle Maintenance: An Inquiry into Values'),
105
- * )
106
- * )
107
- *
108
- * @example <caption>Filtering response body using List</caption>
109
- * import { Property } from '@serenity-js/core';
110
- * import { property, startsWith } from '@serenity-js/assertions';
111
- *
112
- * actor.attemptsTo(
113
- * Ensure.that(
114
- * // imagine the API returns an array of books
115
- * List.of(LastResponse.body<Book[]>())
116
- * .where(Property.at<Book>().author, equals('Robert M. Pirsig'))
117
- * .first(),
118
- * property('title', startsWith('Zen and the Art of Motorcycle Maintenance')),
119
- * )
120
- * )
121
- *
122
- * @returns {@serenity-js/core/lib/screenplay~Question<any>}
123
- *
124
- * @see {@link @serenity-js/core/lib/screenplay/questions~Property}
125
- * @see {@link @serenity-js/core/lib/screenplay/questions~List}
127
+ * )
128
+ * ```
129
+ *
130
+ * ## Iterating over the items in the response body
131
+ *
132
+ * ```ts
133
+ * import { actorCalled } from '@serenity-js/core'
134
+ * import { CallAnApi, LastResponse } from '@serenity-js/rest'
135
+ * import { Ensure, equals } from '@serenity-js/assertions'
136
+ *
137
+ * interface Product {
138
+ * id: number;
139
+ * name: string;
140
+ * }
141
+ *
142
+ * await actorCalled('Apisitt')
143
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
144
+ * .attemptsTo(
145
+ * Send.a(GetRequest.to(`/products`)),
146
+ * List.of<Product>(LastResponse.body<{ products: Product[] }>().products)
147
+ * .forEach(({ item, actor }) =>
148
+ * actor.attemptsTo(
149
+ * Send.a(GetRequest.to(`/products/${ item.id }`)),
150
+ * Ensure.that(LastResponse.body<Product>().id, equals(item.id)),
151
+ * )
152
+ * ),
153
+ * )
154
+ * ```
126
155
  */
127
156
  static body<T = any>(): QuestionAdapter<T> {
128
157
  return Question.about<T>(`the body of the last response`, async actor => {
@@ -131,11 +160,24 @@ export class LastResponse {
131
160
  }
132
161
 
133
162
  /**
134
- * @desc
135
- * Enables asserting on one of the {@link LastResponse}'s headers
163
+ * Retrieves a header of the {@apilink LastResponse|last response}, identified by `name`
164
+ *
165
+ * ## Asserting on a header
136
166
  *
137
- * @param {string} name
138
- * @returns {@serenity-js/core/lib/screenplay~Question<string>}
167
+ * ```ts
168
+ * import { actorCalled } from '@serenity-js/core'
169
+ * import { CallAnApi, LastResponse } from '@serenity-js/rest'
170
+ * import { Ensure, equals } from '@serenity-js/assertions'
171
+ *
172
+ * await actorCalled('Apisitt')
173
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
174
+ * .attemptsTo(
175
+ * Send.a(GetRequest.to(`/products`)),
176
+ * Ensure.that(LastResponse.header('Content-Type'), equals('application/json')),
177
+ * )
178
+ * ```
179
+ *
180
+ * @param name
139
181
  */
140
182
  static header(name: string): QuestionAdapter<string> {
141
183
  return Question.about<string>(`the '${ name }' header of the last response`, async actor => {
@@ -144,15 +186,26 @@ export class LastResponse {
144
186
  }
145
187
 
146
188
  /**
147
- * @desc
148
- * Enables asserting on all of the {@link LastResponse}'s headers,
149
- * returned as an object where the keys represent header names.
189
+ * Retrieves all the headers of the {@apilink LastResponse|last response}.
190
+ *
191
+ * ## Asserting on a header
192
+ *
193
+ * ```ts
194
+ * import { actorCalled } from '@serenity-js/core'
195
+ * import { CallAnApi, LastResponse } from '@serenity-js/rest'
196
+ * import { Ensure, equals } from '@serenity-js/assertions'
150
197
  *
151
- * @returns {@serenity-js/core/lib/screenplay~Question<Record<string, string>>}
198
+ * await actorCalled('Apisitt')
199
+ * .whoCan(CallAnApi.at('https://api.example.org/'))
200
+ * .attemptsTo(
201
+ * Send.a(GetRequest.to(`/products`)),
202
+ * Ensure.that(LastResponse.headers()['Content-Type'], equals('application/json')),
203
+ * )
204
+ * ```
152
205
  */
153
- static headers(): QuestionAdapter<Record<string, string>> {
154
- return Question.about<Record<string, string>>(`the headers or the last response`, async actor => {
155
- return CallAnApi.as(actor).mapLastResponse(response => response.headers);
206
+ static headers(): QuestionAdapter<RawAxiosResponseHeaders> {
207
+ return Question.about<RawAxiosResponseHeaders>(`the headers or the last response`, async actor => {
208
+ return CallAnApi.as(actor).mapLastResponse(response => response.headers as RawAxiosResponseHeaders);
156
209
  });
157
210
  }
158
211
  }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.build.json",
3
+ "compilerOptions": {
4
+ "outDir": "lib",
5
+ "rootDir": "src"
6
+ },
7
+ "include": [
8
+ "src/**/*.ts"
9
+ ]
10
+ }
@@ -1,63 +0,0 @@
1
- import { Answerable } from '@serenity-js/core';
2
- import { AxiosRequestConfig } from 'axios';
3
- import { HTTPRequest } from './HTTPRequest';
4
- /**
5
- * @desc
6
- * The DELETE method requests that the origin server remove the
7
- * association between the target resource and its current
8
- * functionality.
9
- *
10
- * @example <caption>Create and remove a resource</caption>
11
- * import { Actor } from '@serenity-js/core';
12
- * import { CallAnApi, DeleteRequest, LastResponse, PostRequest, Send } from '@serenity-js/rest'
13
- * import { Ensure, equals, startsWith } from '@serenity-js/assertions';
14
- *
15
- * const actor = Actor.named('Apisit').whoCan(CallAnApi.at('https://myapp.com/api'));
16
- *
17
- * actor.attemptsTo(
18
- * // create a new test user account
19
- * Send.a(PostRequest.to('/users').with({
20
- * login: 'tester',
21
- * password: 'P@ssword1',
22
- * }),
23
- * Ensure.that(LastResponse.status(), equals(201)),
24
- * Ensure.that(LastResponse.header('Location'), startsWith('/users')),
25
- *
26
- * // delete the test user account
27
- * Send.a(DeleteRequest.to(LastResponse.header('Location'))),
28
- * Ensure.that(LastResponse.status(), equals(200)),
29
- * );
30
- *
31
- * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
32
- * @see https://tools.ietf.org/html/rfc7231#section-4.3.5
33
- *
34
- * @extends {HTTPRequest}
35
- */
36
- export declare class DeleteRequest extends HTTPRequest {
37
- /**
38
- * @desc
39
- * Configures the object with a destination URI.
40
- *
41
- * When the `resourceUri` is not a fully qualified URL but a path, such as `/products/2`,
42
- * it gets concatenated with the URL provided to the Axios instance
43
- * when the {@link CallAnApi} {@link @serenity-js/core/lib/screenplay~Ability} was instantiated.
44
- *
45
- * @param {@serenity-js/core/lib/screenplay~Answerable<string>} resourceUri
46
- * The URI where the {@link @serenity-js/core/lib/screenplay/actor~Actor}
47
- * should send the {@link HTTPRequest}.
48
- *
49
- * @returns {DeleteRequest}
50
- */
51
- static to(resourceUri: Answerable<string>): DeleteRequest;
52
- /**
53
- * @desc
54
- * Overrides the default Axios request configuration provided
55
- * when {@link CallAnApi} {@link @serenity-js/core/lib/screenplay~Ability} was instantiated.
56
- *
57
- * @param {@serenity-js/core/lib/screenplay~Answerable<AxiosRequestConfig>} config
58
- * Axios request configuration overrides
59
- *
60
- * @returns {DeleteRequest}
61
- */
62
- using(config: Answerable<AxiosRequestConfig>): DeleteRequest;
63
- }
@@ -1,70 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DeleteRequest = void 0;
4
- const HTTPRequest_1 = require("./HTTPRequest");
5
- /**
6
- * @desc
7
- * The DELETE method requests that the origin server remove the
8
- * association between the target resource and its current
9
- * functionality.
10
- *
11
- * @example <caption>Create and remove a resource</caption>
12
- * import { Actor } from '@serenity-js/core';
13
- * import { CallAnApi, DeleteRequest, LastResponse, PostRequest, Send } from '@serenity-js/rest'
14
- * import { Ensure, equals, startsWith } from '@serenity-js/assertions';
15
- *
16
- * const actor = Actor.named('Apisit').whoCan(CallAnApi.at('https://myapp.com/api'));
17
- *
18
- * actor.attemptsTo(
19
- * // create a new test user account
20
- * Send.a(PostRequest.to('/users').with({
21
- * login: 'tester',
22
- * password: 'P@ssword1',
23
- * }),
24
- * Ensure.that(LastResponse.status(), equals(201)),
25
- * Ensure.that(LastResponse.header('Location'), startsWith('/users')),
26
- *
27
- * // delete the test user account
28
- * Send.a(DeleteRequest.to(LastResponse.header('Location'))),
29
- * Ensure.that(LastResponse.status(), equals(200)),
30
- * );
31
- *
32
- * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
33
- * @see https://tools.ietf.org/html/rfc7231#section-4.3.5
34
- *
35
- * @extends {HTTPRequest}
36
- */
37
- class DeleteRequest extends HTTPRequest_1.HTTPRequest {
38
- /**
39
- * @desc
40
- * Configures the object with a destination URI.
41
- *
42
- * When the `resourceUri` is not a fully qualified URL but a path, such as `/products/2`,
43
- * it gets concatenated with the URL provided to the Axios instance
44
- * when the {@link CallAnApi} {@link @serenity-js/core/lib/screenplay~Ability} was instantiated.
45
- *
46
- * @param {@serenity-js/core/lib/screenplay~Answerable<string>} resourceUri
47
- * The URI where the {@link @serenity-js/core/lib/screenplay/actor~Actor}
48
- * should send the {@link HTTPRequest}.
49
- *
50
- * @returns {DeleteRequest}
51
- */
52
- static to(resourceUri) {
53
- return new DeleteRequest(resourceUri);
54
- }
55
- /**
56
- * @desc
57
- * Overrides the default Axios request configuration provided
58
- * when {@link CallAnApi} {@link @serenity-js/core/lib/screenplay~Ability} was instantiated.
59
- *
60
- * @param {@serenity-js/core/lib/screenplay~Answerable<AxiosRequestConfig>} config
61
- * Axios request configuration overrides
62
- *
63
- * @returns {DeleteRequest}
64
- */
65
- using(config) {
66
- return new DeleteRequest(this.resourceUri, undefined, config);
67
- }
68
- }
69
- exports.DeleteRequest = DeleteRequest;
70
- //# sourceMappingURL=DeleteRequest.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DeleteRequest.js","sourceRoot":"","sources":["../../src/model/DeleteRequest.ts"],"names":[],"mappings":";;;AAGA,+CAA4C;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAa,aAAc,SAAQ,yBAAW;IAE1C;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,EAAE,CAAC,WAA+B;QACrC,OAAO,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,MAAsC;QACxC,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;CACJ;AAjCD,sCAiCC"}