|
- using System.Net;
- using CartWise.Domain.Entities;
- using CartWise.Domain.Enums;
- using CartWise.Infrastructure.Data;
- using Microsoft.AspNetCore.Mvc.Testing;
- using Microsoft.Extensions.DependencyInjection;
-
- namespace CartWise.Web.Tests;
-
- public class PriceAccessControlTests : IClassFixture<CartWiseWebApplicationFactory>
- {
- private readonly CartWiseWebApplicationFactory _factory;
-
- public PriceAccessControlTests(CartWiseWebApplicationFactory factory)
- {
- _factory = factory;
- }
-
- [Fact]
- public async Task AnonymousUser_IsRedirectedToLoginWhenRequestingPrices()
- {
- var client = _factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });
-
- var response = await client.GetAsync("/prices");
-
- Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
- Assert.Contains("/Account/Login", response.Headers.Location?.ToString());
- }
-
- [Fact]
- public async Task AuthenticatedUser_WithNoObservations_SeesEmptyState()
- {
- var client = _factory.CreateClient();
- await WebTestHelpers.RegisterAsync(client, "pricesempty1@example.com", "Price Watcher");
- await WebTestHelpers.CreateHouseholdAsync(client, "Price Empty Household");
-
- var response = await client.GetAsync("/prices");
-
- response.EnsureSuccessStatusCode();
- var body = await response.Content.ReadAsStringAsync();
- HtmlAssert.Contains("No prices recorded yet", body);
- }
-
- [Fact]
- public async Task ProductPage_ReturnsNotFoundForUnknownProduct()
- {
- var client = _factory.CreateClient();
- await WebTestHelpers.RegisterAsync(client, "pricesunknown1@example.com", "Price Watcher 2");
- await WebTestHelpers.CreateHouseholdAsync(client, "Price Unknown Household");
-
- var response = await client.GetAsync($"/prices/product/{Guid.NewGuid()}");
-
- Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
- }
-
- [Fact]
- public async Task ObserveThenViewProduct_ShowsLoggedPriceInHistory()
- {
- var client = _factory.CreateClient();
- await WebTestHelpers.RegisterAsync(client, "pricesobserve1@example.com", "Price Observer");
- await WebTestHelpers.CreateHouseholdAsync(client, "Price Observe Household");
-
- var productId = SeedProduct("Observed Oats");
-
- var productHtml = await client.GetStringAsync($"/prices/product/{productId}");
- HtmlAssert.Contains("No price history yet", productHtml);
- var token = WebTestHelpers.ExtractAntiForgeryToken(productHtml);
-
- var observeResponse = await client.PostAsync($"/prices/product/{productId}/observe", new FormUrlEncodedContent(new Dictionary<string, string>
- {
- ["__RequestVerificationToken"] = token,
- ["price"] = "3.49"
- }));
- observeResponse.EnsureSuccessStatusCode();
-
- var afterObserveHtml = await observeResponse.Content.ReadAsStringAsync();
- HtmlAssert.Contains("$3.49", afterObserveHtml);
-
- var indexHtml = await client.GetStringAsync("/prices");
- HtmlAssert.Contains("Observed Oats", indexHtml);
- }
-
- [Fact]
- public async Task EachHousehold_OnlySeesItsOwnPriceHistory()
- {
- var clientA = _factory.CreateClient();
- var clientB = _factory.CreateClient();
- await WebTestHelpers.RegisterAsync(clientA, "pricesalice1@example.com", "Price Alice");
- await WebTestHelpers.RegisterAsync(clientB, "pricesbob1@example.com", "Price Bob");
- await WebTestHelpers.CreateHouseholdAsync(clientA, "Price Household A");
- await WebTestHelpers.CreateHouseholdAsync(clientB, "Price Household B");
-
- var productId = SeedProduct("Shared Catalog Item");
-
- var productHtmlA = await clientA.GetStringAsync($"/prices/product/{productId}");
- var tokenA = WebTestHelpers.ExtractAntiForgeryToken(productHtmlA);
- await clientA.PostAsync($"/prices/product/{productId}/observe", new FormUrlEncodedContent(new Dictionary<string, string>
- {
- ["__RequestVerificationToken"] = tokenA,
- ["price"] = "9.99"
- }));
-
- var indexB = await clientB.GetStringAsync("/prices");
-
- Assert.DoesNotContain("Shared Catalog Item", indexB);
- }
-
- private Guid SeedProduct(string name)
- {
- using var scope = _factory.Services.CreateScope();
- var db = scope.ServiceProvider.GetRequiredService<CartWiseDbContext>();
- var product = new Product(name, ProductSourceType.Manual, DateTime.UtcNow);
- db.Products.Add(product);
- db.SaveChanges();
- return product.ProductId;
- }
- }
|