import { Answerable } from '@serenity-js/core';
import { AxiosRequestConfig } from 'axios';
import { HTTPRequest } from './HTTPRequest';
/**
* @desc
* The HTTP POST method requests that the origin server accepts
* the entity enclosed in the request as a new subordinate of the resource
* identified by the `resourceUri`.
*
* This means that the POST should be used when you want to create a child resource under
* a collection of resources.
*
* POST request is neither [safe](https://developer.mozilla.org/en-US/docs/Glossary/Safe),
* nor [idempotent](https://developer.mozilla.org/en-US/docs/Glossary/Idempotent).
* This means that if you retry a POST request N times,
* a correctly implemented HTTP REST API will create N resources with N different URIs.
*
* @example
Add new resource to a collection
* import { Actor } from '@serenity-js/core';
* import { CallAnApi, LastResponse, PostRequest, Send } from '@serenity-js/rest'
* import { Ensure, equals } from '@serenity-js/assertions';
*
* const actor = Actor.named('Apisit').whoCan(CallAnApi.at('https://myapp.com/api'));
*
* actor.attemptsTo(
* Send.a(PostRequest.to('/books').with({
* isbn: '0-688-00230-7',
* title: 'Zen and the Art of Motorcycle Maintenance: An Inquiry into Values',
* author: 'Robert M. Pirsig',
* })),
* Ensure.that(LastResponse.status(), equals(201)),
* Ensure.that(LastResponse.header('Location'), equals('/books/0-688-00230-7')),
* );
*
* @example Submit a HTML form
* import { Actor } from '@serenity-js/core';
* import { CallAnApi, LastResponse, PostRequest, Send } from '@serenity-js/rest'
* import { Ensure, equals } from '@serenity-js/assertions';
* import { stringify } from 'querystring';
*
* const
* actor = Actor.named('Apisit').whoCan(CallAnApi.at('https://myapp.com')),
* formData = stringify({
* name: actor.name,
* email: `${ actor.name }@example.com`,
* text: 'Your website is great! Learnt a lot :-)'
* });
*
* actor.attemptsTo(
* Send.a(PostRequest.to('/feedback').with(postData).using({
* headers: {
* 'Content-Type': 'application/x-www-form-urlencoded',
* 'Content-Length': formData.length
* }
* })),
* Ensure.that(LastResponse.status(), equals(200)),
* Ensure.that(LastResponse.header('Location'), equals('/feedback/thank-you.html')),
* );
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
* @see https://tools.ietf.org/html/rfc7231#section-4.3.3
*
* @extends {HTTPRequest}
*/
export class PostRequest extends HTTPRequest {
/**
* @desc
* Configures the object with a destination URI.
*
* When the `resourceUri` is not a fully qualified URL but a path, such as `/products/2`,
* it gets concatenated with the URL provided to the Axios instance
* when the {@link CallAnApi} {@link @serenity-js/core/lib/screenplay~Ability} was instantiated.
*
* @param {@serenity-js/core/lib/screenplay~Answerable} resourceUri
* The URI where the {@link @serenity-js/core/lib/screenplay/actor~Actor}
* should send the {@link HTTPRequest}.
*
* @returns {PostRequest}
*/
static to(resourceUri: Answerable): PostRequest {
return new PostRequest(resourceUri);
}
/**
* @desc
* Configures the object with a request body.
*
* @param {@serenity-js/core/lib/screenplay~Answerable} data
* Data to be sent to the `resourceUri`
*
* @returns {PostRequest}
*/
with(data: Answerable): PostRequest {
return new PostRequest(this.resourceUri, data, this.config);
}
/**
* @desc
* Overrides the default Axios request configuration provided
* when {@link CallAnApi} {@link @serenity-js/core/lib/screenplay~Ability} was instantiated.
*
* @param {@serenity-js/core/lib/screenplay~Answerable} config
* Axios request configuration overrides
*
* @returns {PostRequest}
*/
using(config: AxiosRequestConfig): PostRequest {
return new PostRequest(this.resourceUri, this.data, config);
}
}