using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using PowderCoating.Infrastructure.Data; using PowderCoating.Web.Controllers; namespace PowderCoating.UnitTests; public class WebhooksControllerTests { [Fact] public async Task TwilioSms_ReturnsForbid_WhenAuthTokenMissingOutsideDevelopment() { await using var dbContext = CreateDbContext(); var controller = CreateController(dbContext, Array.Empty>(), "Production"); controller.ControllerContext = new ControllerContext { HttpContext = CreateHttpContext() }; var result = await controller.TwilioSms(new TwilioSmsPayload { From = "+15551234567", Body = "STOP" }); Assert.IsType(result); } [Fact] public async Task TwilioSms_AllowsMissingAuthToken_InDevelopment() { await using var dbContext = CreateDbContext(); var controller = CreateController(dbContext, Array.Empty>(), "Development"); controller.ControllerContext = new ControllerContext { HttpContext = CreateHttpContext() }; var result = await controller.TwilioSms(new TwilioSmsPayload()); var content = Assert.IsType(result); Assert.Equal("application/xml", content.ContentType); Assert.Equal("", content.Content); } private static WebhooksController CreateController( ApplicationDbContext dbContext, IEnumerable> configValues, string environmentName) { var configuration = new ConfigurationBuilder() .AddInMemoryCollection(configValues) .Build(); var environment = Mock.Of(x => x.EnvironmentName == environmentName); return new WebhooksController( dbContext, configuration, environment, Mock.Of>()); } private static DefaultHttpContext CreateHttpContext() { var context = new DefaultHttpContext(); context.Request.Method = HttpMethods.Post; context.Request.Scheme = "https"; context.Request.Host = new HostString("example.com"); context.Request.Path = "/Webhooks/TwilioSms"; context.Features.Set(new FormFeature(new FormCollection(new Dictionary { ["From"] = "+15551234567", ["Body"] = "STOP" }))); return context; } private static ApplicationDbContext CreateDbContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; return new ApplicationDbContext(options); } }