Skip to main content

SSR Adapter

The SSR adapter targets server-side rendered HTML pages. It uses a shared CookieManager per adapter instance, so session cookies automatically persist across steps — enabling login → authenticated page flows without any manual session handling.

Setup

var ssr = builder.SsrAdapterBuilder()
.WithBaseUrl(new Uri("http://localhost:8080"))
.Build();

HTTP verbs

ssr.Get("/page")
ssr.Post("/form")
ssr.Request("/resource", HttpMethodVerb.Patch)
ssr.Request("/resource", HttpMethodVerb.Put)
ssr.Request("/resource", HttpMethodVerb.Delete)
Retry behavior

Same as the REST adapter: GET, PUT, DELETE retry until assertions pass. POST, PATCH execute once and fail immediately on assertion failure.

Form content

// Eager — evaluated at step registration time
ssr.Post("/auth/login")
.WithFormContent(new LoginRequest(username, password).ToForm())
.AssertSuccess();

// Lazy — evaluated at execution time
ssr.Post("/auth/login")
.WithFormContent(() => new LoginRequest(username, password).ToForm())
.AssertSuccess();

Form content is sent as application/x-www-form-urlencoded.

SsrExtensions.toForm

toForm converts any POJO or record to a Map<String, String> via reflection:

// .NET — extension method on domain records
public record RegisterRequest(string Username, string Password)
{
public Dictionary<string, string> ToForm() => new()
{
["username"] = Username,
["password"] = Password,
};
}

In .NET, ToForm() is a convention method on the request record itself.

Cookies set by a response are automatically carried in subsequent requests from the same adapter instance:

await XceptoTest.Given(scenario, builder =>
{
var ssr = builder.SsrAdapterBuilder()
.WithBaseUrl(scenario.BaseUri)
.Build();

ssr.Post("/auth/register")
.WithFormContent(new RegisterRequest(username, password).ToForm())
.AssertSuccess()
.AssertThatResponseContentString(
Does.Not.Contain("id=\"errors\""));

ssr.Post("/auth/login")
.WithFormContent(new LoginRequest(username, password).ToForm())
.AssertSuccess();

// Session cookie is automatically carried — no manual session management
ssr.Get("/")
.AssertThatResponseContentString(Does.Contain(username));
});

Each adapter instance has its own cookie jar. Two adapter instances built from the same builder do not share cookies:

var admin = builder.SsrAdapterBuilder().WithBaseUrl(baseUri).Build();
var user = builder.SsrAdapterBuilder().WithBaseUrl(baseUri).Build();
// admin and user have completely independent cookie jars

Promise — capturing HTML body

Use promiseResponse() to capture the HTML body and consume it in a later step:

Promise<string> pageHtml = ssr.Post("/token/create")
.WithFormContent(new TokenCreateRequest("deploy-key").ToForm())
.AssertSuccess()
.PromiseResponse();

rest.Post("/api/env/create")
.WithBearerTokenClient(() => ExtractToken(pageHtml.Resolve()))
.AssertSuccess();

See Patterns → Promise for the full pattern.

Combined REST + SSR

SSR and REST adapters can be used together in one test. A common pattern: acquire a token through the UI, then use it to authenticate a REST call.

await XceptoTest.Given(scenario, builder =>
{
var ssr = builder.SsrAdapterBuilder()
.WithBaseUrl(scenario.GuiAddress)
.Build();

var rest = builder.RestAdapterBuilder()
.WithBaseUrl(scenario.ApiAddress)
.Build();

Promise<string> pageHtml = ssr.Post("/token/create")
.WithFormContent(
new TokenCreateRequest("deploy-key").ToForm())
.AssertSuccess()
.PromiseResponse();

rest.Post("/api/env/create")
.WithBearerTokenClient(
() => ExtractToken(pageHtml.Resolve()))
.AssertSuccess();
});