Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CSF.Screenplay.Docs/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"**/obj/**",
"Tests/**",
"Old/**",
"CSF.Screenplay.JsonToHtmlReport.Template/**"
"CSF.Screenplay.JsonToHtmlReport.Template/**",
"CSF.Screenplay.SpecFlow/**"
]
}
],
Expand Down
8 changes: 8 additions & 0 deletions CSF.Screenplay.Docs/docs/extensions/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Screenplay extensions

This page lists the officially-supported **[Screenplay Extensions]**.

* **[Selenium](selenium/index.md)**: _remote control Web Browsers using Selenium Web Driver_
* **[Web APIs](webApis/index.md)**: _communicate with Web APIs with an HTTP Client_

[Screenplay Extensions]: ../../glossary/Extension.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Common combinations of requests and endpoints

The appropriate combination of [Request action] type and [Endpoint] type depends upon your use case.
Common use cases are summarised in the table below.
Information about reading this table follows.

| Request payload | Response type | Endpoint type | Request action type |
| --------------- | ------------- | ------------- | ---------------- |
| _None_ | _None_ | [`Endpoint`] | [`SendTheHttpRequest`] |
| _None_ | Deserialized with custom logic | [`Endpoint<TResult>`] | [`SendTheHttpRequestAndGetTheResponse<T>`] |
| _None_ | Deserialized from JSON | [`Endpoint<TResult>`] | [`SendTheHttpRequestAndGetJsonResponse<T>`] |
| Serialized with custom logic | _None_ | Derive from [`ParameterizedEndpoint<TParameters>`] | [`SendTheHttpRequest`] |
| Serialized with custom logic | Deserialized with custom logic | Derive from [`ParameterizedEndpoint<TParameters,TResult>`] | [`SendTheHttpRequestAndGetTheResponse<T>`] |
| Serialized with custom logic | Deserialized from JSON | Derive from [`ParameterizedEndpoint<TParameters,TResult>`] | [`SendTheHttpRequestAndGetJsonResponse<T>`] |
| Serialized with JSON | _None_ | [`JsonEndpoint<TParameters>`] | [`SendTheHttpRequest`] |
| Serialized with JSON | Deserialized with custom logic | [`JsonEndpoint<TParameters,TResult>`] | [`SendTheHttpRequestAndGetTheResponse<T>`] |
| Serialized with JSON | Deserialized from JSON | [`JsonEndpoint<TParameters,TResult>`] | [`SendTheHttpRequestAndGetJsonResponse<T>`] |

> [!TIP]
> To decide which types of endpoint & performable:
> _Choose the **endpoint type** based upon the needs of the **request**, adding an extra generic type parameter if the response is to be strongly-typed.
> Choose the **action type** based upon the technical details of reading the **response**._

[Request action]: Requests.md
[Endpoint]: Endpoints.md
[`Endpoint`]: xref:CSF.Screenplay.WebApis.Endpoint
[`Endpoint<TResult>`]: xref:CSF.Screenplay.WebApis.Endpoint`1
[`ParameterizedEndpoint<TParameters>`]: xref:CSF.Screenplay.WebApis.ParameterizedEndpoint`1
[`ParameterizedEndpoint<TParameters,TResult>`]: xref:CSF.Screenplay.WebApis.ParameterizedEndpoint`2
[`JsonEndpoint<TParameters>`]: xref:CSF.Screenplay.WebApis.JsonEndpoint`1
[`JsonEndpoint<TParameters,TResult>`]: xref:CSF.Screenplay.WebApis.JsonEndpoint`2
[`SendTheHttpRequest`]: xref:CSF.Screenplay.WebApis.SendTheHttpRequest
[`SendTheHttpRequestAndGetTheResponse<T>`]: xref:CSF.Screenplay.WebApis.SendTheHttpRequestAndGetTheResponse`1
[`SendTheHttpRequestAndGetJsonResponse<T>`]: xref:CSF.Screenplay.WebApis.SendTheHttpRequestAndGetJsonResponse`1

## The first two columns

The first two columns indicate:

1. The kind of **request payload** which will be sent<br>
These are the parameters to the API function described by the endpoint
1. The type of the expected **response body**<br>
Where an API function returns a response, this is the .NET type which will be used to represent that response

Where _None_ is listed in either column this means _"not applicable"_.
For example, an API function which uses no parameters will have no request payload.
In the case of responses, _None_ might mean that the response body will be ignored.

## The second two columns

The second two columns indicate the Endpoint type and Request action type which are recommended in this scenario.
40 changes: 40 additions & 0 deletions CSF.Screenplay.Docs/docs/extensions/webApis/Endpoints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Endpoints

**Endpoints** are fundamental to this extension; they are .NET class instances which describe a piece of API functionality which may be consumed.
The single most important (and obvious) piece of information stored in an endpoint object is the URL (route) which is used to communicate with the API function.

## Endpoint classes

The WebAPIs Screenplay extension provides a number of classes by which to describe endpoints.
Developers using this extension are encouraged to create 'libraries' of Endpoints within their own logic.
Such a library might be as simple as a `static class` which contains `public static` get-only properties, each of which returns a named endpoint.
Every endpoint class derives from a base class named [`EndpointBase`].

The endpoint classes available are listed below.
There is also [an article indicating how to choose an appropriate combination] of Endpoint and [Request action].

* [`Endpoint`]
* [`Endpoint<TResponse>`]
* [`ParameterizedEndpoint<TParameters>`] - _intended to be used as a base class_
* [`ParameterizedEndpoint<TParameters,TResponse>`] - _intended to be used as a base class_
* [`JsonEndpoint<TParameters>`]
* [`JsonEndpoint<TParameters,TResponse>`]

[`EndpointBase`]: xref:CSF.Screenplay.WebApis.EndpointBase
[`Endpoint`]: xref:CSF.Screenplay.WebApis.Endpoint
[`Endpoint<TResponse>`]: xref:CSF.Screenplay.WebApis.Endpoint`1
[`ParameterizedEndpoint<TParameters>`]: xref:CSF.Screenplay.WebApis.ParameterizedEndpoint`1
[`ParameterizedEndpoint<TParameters,TResponse>`]: xref:CSF.Screenplay.WebApis.ParameterizedEndpoint`2
[`JsonEndpoint<TParameters>`]: xref:CSF.Screenplay.WebApis.JsonEndpoint`1
[`JsonEndpoint<TParameters,TResponse>`]: xref:CSF.Screenplay.WebApis.JsonEndpoint`2
[an article indicating how to choose an appropriate combination]: ChoosingEndpointsAndRequests.md
[Request action]: Requests.md

## Common to all endpoints

All endpoints describe:

* [The URL pattern to reach the endpoint](xref:CSF.Screenplay.WebApis.EndpointBase.%23ctor(System.Uri,System.Net.Http.HttpMethod))
* [The HTTP method used with the endpoint](xref:CSF.Screenplay.WebApis.EndpointBase.%23ctor(System.Uri,System.Net.Http.HttpMethod))
* [A human-readable name for the endpoint](xref:CSF.Screenplay.WebApis.EndpointBase.Name)
* [An optional timeout for the endpoint](xref:CSF.Screenplay.WebApis.EndpointBase.Timeout)
32 changes: 32 additions & 0 deletions CSF.Screenplay.Docs/docs/extensions/webApis/Requests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Request actions

Sending an HTTP request to an API is accomplished using a Screenplay [Action].
There are three action types available; which to use depends upon the expected response from the API.
[This article helps you choose the appropriate combination of Request Action and Endpoint types].

[Action]: ../../../glossary/Action.md
[This article helps you choose the appropriate combination of Request Action and Endpoint types]: ChoosingEndpointsAndRequests.md

## The three action types

As might be evident from their names, each request action type is used for a different kind of expected response message.
In the case of `SendTheHttpRequest`, there is no response expected (or the response will be ignored).
The other two types are for either a JSON response or a response which requires custom deserialization.

* [`SendTheHttpRequest`](xref:CSF.Screenplay.WebApis.SendTheHttpRequest)
* [`SendTheHttpRequestAndGetJsonResponse<TResponse>`](xref:CSF.Screenplay.WebApis.SendTheHttpRequestAndGetJsonResponse`1)
* [`SendTheHttpRequestAndGetTheResponse<TResponse>`](xref:CSF.Screenplay.WebApis.SendTheHttpRequestAndGetTheResponse`1)

## Use `WebApiBuilder` to simplify usage

A builder/helper class is available to simplify getting the appropriate Request action; this is [`WebApiBuilder`].
The recommended way to consume this is to add `using static CSF.Screenplay.WebApis.WebApiBuilder;` to the source file for any [Performable] you write which consumes Web APIs via this extension.

When an approproate [Endpoint] type has been used, the [`WebApiBuilder`] class will make it very easy to select the correct action, via type inference.
To get a request for an API function which is expected to return a JSON-formatted response, use the method `GetTheJsonResult`.
To get a request for any other API function, use the method `SendTheHttpRequest`.
Both of these methods have several overloads, for each type of endpoint which could use them.

[`WebApiBuilder`]: xref:CSF.Screenplay.WebApis.WebApiBuilder
[Performable]: ../../../glossary/Performable.md
[Endpoint]: Endpoints.md
21 changes: 21 additions & 0 deletions CSF.Screenplay.Docs/docs/extensions/webApis/Responses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Responses

The WebAPIs extension for Screenplay supports two kinds of responses.

## JSON

For JSON-based endpoints, use the [`SendTheHttpRequestAndGetJsonResponse<TResponse>`] [request action type] and the response from the API function will automatically be deserialized into an instance of the `TResponse` type.

[`SendTheHttpRequestAndGetJsonResponse<TResponse>`]: xref:CSF.Screenplay.WebApis.SendTheHttpRequestAndGetJsonResponse`1
[request action type]: Requests.md

## Other response types

For other endpoints with non-JSON responses, it is up to the consumer to deserialize the response using whatever logic is appropriate.
In this case, using the [`SendTheHttpRequestAndGetTheResponse<TResponse>`] request action type, the returned value from `PerformAsAsync` is an instance of [`HttpResponseMessageAndResponseType<TResponse>`].
This model object includes the raw/original [`HttpResponseMessage`] which was returned from the HTTP Client, but the class is generic for the intended type of the response.
This should provide sufficient information to deserialize the response accordingly.

[`SendTheHttpRequestAndGetTheResponse<TResponse>`]: xref:CSF.Screenplay.WebApis.SendTheHttpRequestAndGetTheResponse`1
[`HttpResponseMessageAndResponseType<TResponse>`]: xref:CSF.Screenplay.WebApis.HttpResponseMessageAndResponseType`1
[`HttpResponseMessage`]: xref:System.Net.Http.HttpResponseMessage
64 changes: 63 additions & 1 deletion CSF.Screenplay.Docs/docs/extensions/webApis/index.md
Original file line number Diff line number Diff line change
@@ -1 +1,63 @@
TODO: Write this docs page
---
uid: WebApisArticle
---

# CSF.Screenplay.WebApis Extension

The Web APIs Extension allows [Actors] to communicate with HTTP web API endpoints within a Screenplay [Performance].

[Actors]: xref:CSF.Screenplay.Actor
[Performance]: xref:CSF.Screenplay.IPerformance

## Overview

The fundamentals of this Screenplay extension are shown in the diagram below.
The concepts of the [Actor] and [Ability] (the ability is named [`MakeWebApiRequests`]) are explained in Screenplay's core documentation.
Other concepts are explained below.

This extension provides **[Actions]** which allow the Actor to build and send [HTTP requests] based upon [Endpoint] definitions.
These requests are sent via the HTTP client which is exposed by the [`MakeWebApiRequests`] Ability, to a live API server.
The server returns an [HTTP Response], which the extension formats into a result object.

```mermaid
flowchart
Ability -- "Has ability" --> Actor
Actor -- "Makes requests" --> Request
Endpoint -- "Requests target" --> Request
Request --> api["Live API"]
Ability -- "Facilitates request" --> api
api --> Response

style api fill:#ee9,stroke:#bb6
```

Note that the **Live API** in this diagram _is not a part of Screenplay or this extension_.
The Live API represents an actual HTTP(S) web server which hosts the API with which Screenplay is communicating.

[Actor]: xref:CSF.Screenplay.Actor
[Ability]: xref:AbilityGlossaryItem
[`MakeWebApiRequests`]: xref:CSF.Screenplay.WebApis.MakeWebApiRequests
[Actions]: ../../../glossary/Action.md
[HTTP requests]: Requests.md
[Endpoint]: Endpoints.md
[HTTP Response]: Responses.md

## Usage example

Here is a brief usage example for using a JSON API with a defined endpoint, identified by URL and HTTP method.
The endpoint expects a parameter of a `PersonId` (a fictitious class, which accepts a person's name as a constructor parameter).
The endpoint returns a JSON-formatted response which is a representation of an `Animal` (another fictitious class, which has a string `Name` property).

```csharp
using static CSF.Screenplay.WebApis.WebApiBuilder;

static readonly JsonEndpoint<PersonId,Animal> getFavouriteAnimal = new ("https://api.example.com/person/getFavouriteAnimal", HttpMethod.Post);

// this method would appear as part of a custom-written Task class,
// deriving from IPerformableWithResult<string>
public async ValueTask<string> PerformAsAsync(ICanPerform actor, CancellationToken cancellationToken)
{
var animal = await actor.PerformAsync(GetTheJsonResult(getFavouriteAnimal, new("Jane Doe")), cancellationToken);
return animal.Name;
}
```
10 changes: 10 additions & 0 deletions CSF.Screenplay.Docs/docs/extensions/webApis/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- name: Web APIs
href: index.md
- name: Endpoints
href: Endpoints.md
- name: Requests
href: Requests.md
- name: Choosing endpoint & request types
href: ChoosingEndpointsAndRequests.md
- name: Responses
href: Responses.md
16 changes: 15 additions & 1 deletion CSF.Screenplay.Docs/docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Get started with Screenplay

To get started with Screenplay, the first step is to decide how you'd like to use it:
## 1. Install Screenplay

The first step is to decide how you'd like to use it:

* [As a testing tool, with NUnit 3]
* [As a testing tool, with Reqnroll]
Expand All @@ -11,3 +13,15 @@ To get started with Screenplay, the first step is to decide how you'd like to us
[As a testing tool, with Reqnroll]: gettingStarted/reqnroll/index.md
[the retired SpecFlow]: https://reqnroll.net/news/2025/01/specflow-end-of-life-has-been-announced/
[As a process automation library]: gettingStarted/nonTesting/index.md

## 2. Pick extensions

To get the most from Screenplay you should install one or more [extensions].
These give Screenplay the capability to interact with and control other systems.

Here is [a list of the extensions which are authored alongside Screenplay's core].
If you'd like, you are also encouraged to [write your own extension], adding new capabilities to Screenplay.

[extensions]: ../glossary/Extension.md
[a list of the extensions which are authored alongside Screenplay's core]: extensions/index.md
[write your own extension]: extendingScreenplay/index.md
59 changes: 0 additions & 59 deletions CSF.Screenplay.Docs/docs/performables/WebApis.md

This file was deleted.

Loading
Loading