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
- .NET
- Java
var ssr = builder.SsrAdapterBuilder()
.WithBaseUrl(new Uri("http://localhost:8080"))
.Build();
var ssr = new SsrAdapterBuilder(builder)
.withBaseUrl(URI.create("http://localhost:8080"))
.build();
Each build() call creates a fresh HttpClient with its own CookieManager. Cookies from one adapter instance do not bleed into another.
HTTP verbs
- .NET
- Java
ssr.Get("/page")
ssr.Post("/form")
ssr.Request("/resource", HttpMethodVerb.Patch)
ssr.Request("/resource", HttpMethodVerb.Put)
ssr.Request("/resource", HttpMethodVerb.Delete)
ssr.get("/page")
ssr.post("/form")
ssr.request("/resource", HttpMethodVerb.PATCH)
ssr.request("/resource", HttpMethodVerb.PUT)
ssr.request("/resource", HttpMethodVerb.DELETE)
Same as the REST adapter: GET, PUT, DELETE retry until assertions pass. POST, PATCH execute once and fail immediately on assertion failure.
Form content
- .NET
- Java
// 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();
// Eager — evaluated at step registration time
ssr.post("/auth/login")
.withFormContent(SsrExtensions.toForm(new LoginRequest(username, password)))
.assertSuccess();
// Lazy — evaluated at execution time
ssr.post("/auth/login")
.withFormContent(() -> SsrExtensions.toForm(new LoginRequest(username, password)))
.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
- Java
// .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.
// Java — SsrExtensions.toForm via reflection
record RegisterRequest(String username, String password) {}
// Usage:
SsrExtensions.toForm(new RegisterRequest("alice", "secret"))
// → {"username": "alice", "password": "secret"}
SsrExtensions.toForm(Object) reads all declared fields and converts their values to strings. Field names become form keys.
Cookie persistence — login flow
Cookies set by a response are automatically carried in subsequent requests from the same adapter instance:
- .NET
- Java
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));
});
Xcepto.given(scenario, builder -> {
var ssr = new SsrAdapterBuilder(builder)
.withBaseUrl(scenario.baseUri)
.build();
ssr.post("/auth/register")
.withFormContent(SsrExtensions.toForm(
new RegisterRequest(username, password)))
.assertSuccess()
.assertThatResponseContentString(
html -> !html.contains("id=\"errors\""));
ssr.post("/auth/login")
.withFormContent(SsrExtensions.toForm(
new LoginRequest(username, password)))
.assertSuccess();
// Session cookie is automatically carried
ssr.get("/")
.assertThatResponseContentString(
html -> html.contains(username));
}, TIMEOUT, Duration.ofMillis(50));
Cookie isolation between adapter instances
Each adapter instance has its own cookie jar. Two adapter instances built from the same builder do not share cookies:
- .NET
- Java
var admin = builder.SsrAdapterBuilder().WithBaseUrl(baseUri).Build();
var user = builder.SsrAdapterBuilder().WithBaseUrl(baseUri).Build();
// admin and user have completely independent cookie jars
var admin = new SsrAdapterBuilder(builder).withBaseUrl(baseUri).build();
var user = new SsrAdapterBuilder(builder).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:
- .NET
- Java
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();
Promise<String> pageHtml = ssr.post("/token/create")
.withFormContent(SsrExtensions.toForm(
new TokenCreateRequest("deploy-key")))
.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.
- .NET
- Java
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();
});
Xcepto.given(scenario, builder -> {
var ssr = new SsrAdapterBuilder(builder)
.withBaseUrl(scenario.guiAddress)
.build();
var rest = new RestAdapterBuilder(builder)
.withBaseUrl(scenario.apiAddress)
.withSerializer(new GsonSerializer())
.build();
Promise<String> pageHtml = ssr.post("/token/create")
.withFormContent(SsrExtensions.toForm(
new TokenCreateRequest("deploy-key")))
.assertSuccess()
.promiseResponse();
rest.post("/api/env/create")
.withBearerTokenClient(
() -> extractToken(pageHtml.resolve()))
.assertSuccess();
}, TIMEOUT, Duration.ofMillis(100));