mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-14 17:54:42 +00:00
321 lines
11 KiB
C#
321 lines
11 KiB
C#
using System.Text;
|
|
using System.Text.Json;
|
|
using Database.Connection;
|
|
using Features.Locations.Repository;
|
|
using FluentAssertions;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Reqnroll;
|
|
|
|
namespace API.Specs.Steps;
|
|
|
|
[Binding]
|
|
public class BrewerySteps(ScenarioContext scenario) : ApiStepsBase(scenario)
|
|
{
|
|
private const string AccessTokenKey = "accessToken";
|
|
private const string CityIdKey = "cityId";
|
|
private const string BreweryPostIdKey = "breweryPostId";
|
|
private const string BreweryRowVersionKey = "breweryRowVersion";
|
|
|
|
private const string FixtureCountryName = "Fixture Country";
|
|
private const string FixtureCountryIsoCode = "FX";
|
|
private const string FixtureStateProvinceName = "Fixture State";
|
|
private const string FixtureStateProvinceIsoCode = "FX-TS";
|
|
private const string FixtureCityName = "Fixture City";
|
|
|
|
private HttpRequestMessage NewAuthenticatedRequest(HttpMethod method, string url)
|
|
{
|
|
HttpRequestMessage requestMessage = new(method, url);
|
|
if (Scenario.TryGetValue<string>(AccessTokenKey, out string? accessToken))
|
|
requestMessage.Headers.Add("Authorization", $"Bearer {accessToken}");
|
|
return requestMessage;
|
|
}
|
|
|
|
private async Task SendAsync(HttpRequestMessage requestMessage)
|
|
{
|
|
HttpClient client = GetClient();
|
|
HttpResponseMessage response = await client.SendAsync(requestMessage);
|
|
string responseBody = await response.Content.ReadAsStringAsync();
|
|
|
|
Scenario[ResponseKey] = response;
|
|
Scenario[ResponseBodyKey] = responseBody;
|
|
}
|
|
|
|
[Given("a city exists")]
|
|
public async Task GivenACityExists()
|
|
{
|
|
ISqlConnectionFactory connectionFactory = GetFactory()
|
|
.Services.GetRequiredService<ISqlConnectionFactory>();
|
|
LocationRepository repository = new(connectionFactory);
|
|
|
|
Guid countryId =
|
|
await repository.GetCountryIdAsync(FixtureCountryIsoCode)
|
|
?? await repository.CreateCountryAsync(FixtureCountryName, FixtureCountryIsoCode);
|
|
|
|
Guid stateProvinceId =
|
|
await repository.GetStateProvinceIdAsync(FixtureStateProvinceIsoCode)
|
|
?? await repository.CreateStateProvinceAsync(
|
|
FixtureStateProvinceName,
|
|
FixtureStateProvinceIsoCode,
|
|
countryId
|
|
);
|
|
|
|
Guid cityId =
|
|
await repository.GetCityIdAsync(FixtureCityName, FixtureStateProvinceIsoCode)
|
|
?? await repository.CreateCityAsync(FixtureCityName, stateProvinceId);
|
|
|
|
Scenario[CityIdKey] = cityId;
|
|
}
|
|
|
|
private async Task CreateBreweryAsync(
|
|
string breweryName,
|
|
string description,
|
|
string addressLine1,
|
|
string postalCode,
|
|
Guid cityId
|
|
)
|
|
{
|
|
var createData = new
|
|
{
|
|
breweryName,
|
|
description,
|
|
location = new
|
|
{
|
|
cityId,
|
|
addressLine1,
|
|
addressLine2 = (string?)null,
|
|
postalCode,
|
|
coordinates = (object?)null,
|
|
},
|
|
};
|
|
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Post,
|
|
"/api/brewery"
|
|
);
|
|
requestMessage.Content = new StringContent(
|
|
JsonSerializer.Serialize(createData),
|
|
Encoding.UTF8,
|
|
"application/json"
|
|
);
|
|
|
|
await SendAsync(requestMessage);
|
|
}
|
|
|
|
[When("I create a brewery with values:")]
|
|
public async Task WhenICreateABreweryWithValues(Table table)
|
|
{
|
|
DataTableRow row = table.Rows[0];
|
|
Guid cityId = Scenario.TryGetValue(CityIdKey, out Guid id) ? id : Guid.NewGuid();
|
|
|
|
await CreateBreweryAsync(
|
|
row["BreweryName"] ?? "",
|
|
row["Description"] ?? "",
|
|
row["AddressLine1"] ?? "",
|
|
row["PostalCode"] ?? "",
|
|
cityId
|
|
);
|
|
}
|
|
|
|
[When("I create a brewery with a non-existent city")]
|
|
public async Task WhenICreateABreweryWithANonExistentCity()
|
|
{
|
|
await CreateBreweryAsync(
|
|
"Ghost City Brewery",
|
|
"A brewery in a city that does not exist",
|
|
"1 Nowhere St",
|
|
"00000",
|
|
Guid.NewGuid()
|
|
);
|
|
}
|
|
|
|
[Given("I have created a brewery")]
|
|
public async Task GivenIHaveCreatedABrewery()
|
|
{
|
|
Guid cityId = Scenario.TryGetValue(CityIdKey, out Guid id)
|
|
? id
|
|
: throw new InvalidOperationException("city ID not found in scenario");
|
|
|
|
await CreateBreweryAsync(
|
|
"Test Brewery",
|
|
"A test brewery",
|
|
"123 Test St",
|
|
"00000",
|
|
cityId
|
|
);
|
|
|
|
Scenario
|
|
.TryGetValue<HttpResponseMessage>(ResponseKey, out HttpResponseMessage? response)
|
|
.Should()
|
|
.BeTrue();
|
|
((int)response!.StatusCode).Should().Be(201, "fixture brewery creation must succeed");
|
|
|
|
Scenario.TryGetValue<string>(ResponseBodyKey, out string? responseBody).Should().BeTrue();
|
|
using JsonDocument doc = JsonDocument.Parse(responseBody!);
|
|
JsonElement payload = doc.RootElement.GetProperty("payload");
|
|
|
|
Scenario[BreweryPostIdKey] = payload.GetProperty("breweryPostId").GetGuid();
|
|
Scenario[BreweryRowVersionKey] = payload.GetProperty("rowVersion").GetString()
|
|
?? throw new InvalidOperationException("rowVersion missing from created brewery");
|
|
}
|
|
|
|
private Guid GetCreatedBreweryPostId()
|
|
{
|
|
return Scenario.TryGetValue(BreweryPostIdKey, out Guid id)
|
|
? id
|
|
: throw new InvalidOperationException("brewery post ID not found in scenario");
|
|
}
|
|
|
|
[When("I retrieve the brewery by ID")]
|
|
public async Task WhenIRetrieveTheBreweryById()
|
|
{
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Get,
|
|
$"/api/brewery/{GetCreatedBreweryPostId()}"
|
|
);
|
|
await SendAsync(requestMessage);
|
|
}
|
|
|
|
[When("I retrieve a brewery by a non-existent ID")]
|
|
public async Task WhenIRetrieveABreweryByANonExistentId()
|
|
{
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Get,
|
|
$"/api/brewery/{Guid.NewGuid()}"
|
|
);
|
|
await SendAsync(requestMessage);
|
|
}
|
|
|
|
[When("I update the brewery with values:")]
|
|
public async Task WhenIUpdateTheBreweryWithValues(Table table)
|
|
{
|
|
DataTableRow row = table.Rows[0];
|
|
Guid breweryPostId = GetCreatedBreweryPostId();
|
|
string rowVersion = Scenario.TryGetValue<string>(BreweryRowVersionKey, out string? rv)
|
|
? rv
|
|
: throw new InvalidOperationException("row version not found in scenario");
|
|
|
|
var updateData = new
|
|
{
|
|
breweryPostId,
|
|
rowVersion,
|
|
breweryName = row["BreweryName"] ?? "",
|
|
description = row["Description"] ?? "",
|
|
location = (object?)null,
|
|
};
|
|
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Put,
|
|
$"/api/brewery/{breweryPostId}"
|
|
);
|
|
requestMessage.Content = new StringContent(
|
|
JsonSerializer.Serialize(updateData),
|
|
Encoding.UTF8,
|
|
"application/json"
|
|
);
|
|
|
|
await SendAsync(requestMessage);
|
|
}
|
|
|
|
[When("I update a non-existent brewery")]
|
|
public async Task WhenIUpdateANonExistentBrewery()
|
|
{
|
|
Guid breweryPostId = Guid.NewGuid();
|
|
var updateData = new
|
|
{
|
|
breweryPostId,
|
|
rowVersion = Convert.ToBase64String([0x00, 0x00, 0x00, 0x00]),
|
|
breweryName = "Nonexistent",
|
|
description = "Nonexistent",
|
|
location = (object?)null,
|
|
};
|
|
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Put,
|
|
$"/api/brewery/{breweryPostId}"
|
|
);
|
|
requestMessage.Content = new StringContent(
|
|
JsonSerializer.Serialize(updateData),
|
|
Encoding.UTF8,
|
|
"application/json"
|
|
);
|
|
|
|
await SendAsync(requestMessage);
|
|
}
|
|
|
|
[When("I delete the brewery")]
|
|
public async Task WhenIDeleteTheBrewery()
|
|
{
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Delete,
|
|
$"/api/brewery/{GetCreatedBreweryPostId()}"
|
|
);
|
|
await SendAsync(requestMessage);
|
|
}
|
|
|
|
[When("I delete a non-existent brewery")]
|
|
public async Task WhenIDeleteANonExistentBrewery()
|
|
{
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Delete,
|
|
$"/api/brewery/{Guid.NewGuid()}"
|
|
);
|
|
await SendAsync(requestMessage);
|
|
}
|
|
|
|
[Given("I am logged in as a different user")]
|
|
public async Task GivenIAmLoggedInAsADifferentUser()
|
|
{
|
|
HttpClient client = GetClient();
|
|
string suffix = Guid.NewGuid().ToString("N")[..8];
|
|
var registrationData = new
|
|
{
|
|
username = $"otheruser-{suffix}",
|
|
firstName = "Other",
|
|
lastName = "User",
|
|
email = $"otheruser-{suffix}@example.com",
|
|
dateOfBirth = "1990-01-01",
|
|
password = "Password1!",
|
|
};
|
|
|
|
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/register")
|
|
{
|
|
Content = new StringContent(
|
|
JsonSerializer.Serialize(registrationData),
|
|
Encoding.UTF8,
|
|
"application/json"
|
|
),
|
|
};
|
|
|
|
HttpResponseMessage response = await client.SendAsync(requestMessage);
|
|
response.EnsureSuccessStatusCode();
|
|
string responseBody = await response.Content.ReadAsStringAsync();
|
|
|
|
using JsonDocument doc = JsonDocument.Parse(responseBody);
|
|
JsonElement payload = doc.RootElement.GetProperty("payload");
|
|
string accessToken =
|
|
(
|
|
payload.TryGetProperty("accessToken", out JsonElement tokenElem)
|
|
? tokenElem.GetString()
|
|
: null
|
|
) ?? throw new InvalidOperationException("accessToken missing from registration payload");
|
|
|
|
Scenario[AccessTokenKey] = accessToken;
|
|
}
|
|
|
|
[Then("retrieving the brewery by ID should now return HTTP status {int}")]
|
|
public async Task ThenRetrievingTheBreweryByIdShouldNowReturnHttpStatus(int expectedCode)
|
|
{
|
|
HttpRequestMessage requestMessage = NewAuthenticatedRequest(
|
|
HttpMethod.Get,
|
|
$"/api/brewery/{GetCreatedBreweryPostId()}"
|
|
);
|
|
await SendAsync(requestMessage);
|
|
|
|
Scenario
|
|
.TryGetValue<HttpResponseMessage>(ResponseKey, out HttpResponseMessage? response)
|
|
.Should()
|
|
.BeTrue();
|
|
((int)response!.StatusCode).Should().Be(expectedCode);
|
|
}
|
|
}
|