Included file scoped namespace
This commit is contained in:
parent
15f5e49134
commit
f53a3e407f
@ -1,16 +1,11 @@
|
|||||||
using Microsoft.AspNetCore.TestHost;
|
namespace FunctionalTests.Extensions;
|
||||||
using System;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Extensions
|
static class HttpClientExtensions
|
||||||
{
|
{
|
||||||
static class HttpClientExtensions
|
public static HttpClient CreateIdempotentClient(this TestServer server)
|
||||||
{
|
{
|
||||||
public static HttpClient CreateIdempotentClient(this TestServer server)
|
var client = server.CreateClient();
|
||||||
{
|
client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString());
|
||||||
var client = server.CreateClient();
|
return client;
|
||||||
client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString());
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,26 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
namespace FunctionalTests.Middleware;
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Middleware
|
class AutoAuthorizeMiddleware
|
||||||
{
|
{
|
||||||
class AutoAuthorizeMiddleware
|
public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00";
|
||||||
|
|
||||||
|
private readonly RequestDelegate _next;
|
||||||
|
|
||||||
|
|
||||||
|
public AutoAuthorizeMiddleware(RequestDelegate rd)
|
||||||
{
|
{
|
||||||
public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00";
|
_next = rd;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly RequestDelegate _next;
|
public async Task Invoke(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var identity = new ClaimsIdentity("cookies");
|
||||||
|
|
||||||
|
identity.AddClaim(new Claim("sub", IDENTITY_ID));
|
||||||
|
identity.AddClaim(new Claim("unique_name", IDENTITY_ID));
|
||||||
|
identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID));
|
||||||
|
|
||||||
public AutoAuthorizeMiddleware(RequestDelegate rd)
|
httpContext.User.AddIdentity(identity);
|
||||||
{
|
await _next.Invoke(httpContext);
|
||||||
_next = rd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Invoke(HttpContext httpContext)
|
|
||||||
{
|
|
||||||
var identity = new ClaimsIdentity("cookies");
|
|
||||||
|
|
||||||
identity.AddClaim(new Claim("sub", IDENTITY_ID));
|
|
||||||
identity.AddClaim(new Claim("unique_name", IDENTITY_ID));
|
|
||||||
identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID));
|
|
||||||
|
|
||||||
httpContext.User.AddIdentity(identity);
|
|
||||||
await _next.Invoke(httpContext);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,42 @@
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
namespace FunctionalTests.Services.Basket;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Services.Basket
|
public class BasketScenariosBase
|
||||||
{
|
{
|
||||||
public class BasketScenariosBase
|
private const string ApiUrlBase = "api/v1/basket";
|
||||||
|
|
||||||
|
|
||||||
|
public TestServer CreateServer()
|
||||||
{
|
{
|
||||||
private const string ApiUrlBase = "api/v1/basket";
|
var path = Assembly.GetAssembly(typeof(BasketScenariosBase))
|
||||||
|
.Location;
|
||||||
|
|
||||||
|
var hostBuilder = new WebHostBuilder()
|
||||||
|
.UseContentRoot(Path.GetDirectoryName(path))
|
||||||
|
.ConfigureAppConfiguration(cb =>
|
||||||
|
{
|
||||||
|
cb.AddJsonFile("Services/Basket/appsettings.json", optional: false)
|
||||||
|
.AddEnvironmentVariables();
|
||||||
|
}).UseStartup<BasketTestsStartup>();
|
||||||
|
|
||||||
public TestServer CreateServer()
|
return new TestServer(hostBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string GetBasket(int id)
|
||||||
{
|
{
|
||||||
var path = Assembly.GetAssembly(typeof(BasketScenariosBase))
|
return $"{ApiUrlBase}/{id}";
|
||||||
.Location;
|
|
||||||
|
|
||||||
var hostBuilder = new WebHostBuilder()
|
|
||||||
.UseContentRoot(Path.GetDirectoryName(path))
|
|
||||||
.ConfigureAppConfiguration(cb =>
|
|
||||||
{
|
|
||||||
cb.AddJsonFile("Services/Basket/appsettings.json", optional: false)
|
|
||||||
.AddEnvironmentVariables();
|
|
||||||
}).UseStartup<BasketTestsStartup>();
|
|
||||||
|
|
||||||
return new TestServer(hostBuilder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Get
|
public static string GetBasketByCustomer(string customerId)
|
||||||
{
|
{
|
||||||
public static string GetBasket(int id)
|
return $"{ApiUrlBase}/{customerId}";
|
||||||
{
|
|
||||||
return $"{ApiUrlBase}/{id}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetBasketByCustomer(string customerId)
|
|
||||||
{
|
|
||||||
return $"{ApiUrlBase}/{customerId}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Post
|
|
||||||
{
|
|
||||||
public static string CreateBasket = $"{ApiUrlBase}/";
|
|
||||||
public static string CheckoutOrder = $"{ApiUrlBase}/checkout";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Post
|
||||||
|
{
|
||||||
|
public static string CreateBasket = $"{ApiUrlBase}/";
|
||||||
|
public static string CheckoutOrder = $"{ApiUrlBase}/checkout";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,21 @@
|
|||||||
using FunctionalTests.Middleware;
|
namespace FunctionalTests.Services.Basket;
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Basket.API;
|
using Microsoft.eShopOnContainers.Services.Basket.API;
|
||||||
using Microsoft.Extensions.Configuration;
|
class BasketTestsStartup : Startup
|
||||||
|
|
||||||
namespace FunctionalTests.Services.Basket
|
|
||||||
{
|
{
|
||||||
class BasketTestsStartup : Startup
|
public BasketTestsStartup(IConfiguration env) : base(env)
|
||||||
{
|
{
|
||||||
public BasketTestsStartup(IConfiguration env) : base(env)
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ConfigureAuth(IApplicationBuilder app)
|
protected override void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant())
|
||||||
{
|
{
|
||||||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant())
|
app.UseMiddleware<AutoAuthorizeMiddleware>();
|
||||||
{
|
app.UseAuthorization();
|
||||||
app.UseMiddleware<AutoAuthorizeMiddleware>();
|
}
|
||||||
app.UseAuthorization();
|
else
|
||||||
}
|
{
|
||||||
else
|
base.ConfigureAuth(app);
|
||||||
{
|
|
||||||
base.ConfigureAuth(app);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,65 +1,53 @@
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
namespace FunctionalTests.Services.Catalog;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API;
|
using Microsoft.eShopOnContainers.Services.Catalog.API;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Services.Catalog
|
public class CatalogScenariosBase
|
||||||
{
|
{
|
||||||
public class CatalogScenariosBase
|
public TestServer CreateServer()
|
||||||
{
|
{
|
||||||
public TestServer CreateServer()
|
var path = Assembly.GetAssembly(typeof(CatalogScenariosBase))
|
||||||
{
|
.Location;
|
||||||
var path = Assembly.GetAssembly(typeof(CatalogScenariosBase))
|
|
||||||
.Location;
|
|
||||||
|
|
||||||
var hostBuilder = new WebHostBuilder()
|
var hostBuilder = new WebHostBuilder()
|
||||||
.UseContentRoot(Path.GetDirectoryName(path))
|
.UseContentRoot(Path.GetDirectoryName(path))
|
||||||
.ConfigureAppConfiguration(cb =>
|
.ConfigureAppConfiguration(cb =>
|
||||||
{
|
|
||||||
cb.AddJsonFile("Services/Catalog/appsettings.json", optional: false)
|
|
||||||
.AddEnvironmentVariables();
|
|
||||||
}).UseStartup<Startup>();
|
|
||||||
|
|
||||||
var testServer = new TestServer(hostBuilder);
|
|
||||||
|
|
||||||
testServer.Host
|
|
||||||
.MigrateDbContext<CatalogContext>((context, services) =>
|
|
||||||
{
|
|
||||||
var env = services.GetService<IWebHostEnvironment>();
|
|
||||||
var settings = services.GetService<IOptions<CatalogSettings>>();
|
|
||||||
var logger = services.GetService<ILogger<CatalogContextSeed>>();
|
|
||||||
|
|
||||||
new CatalogContextSeed()
|
|
||||||
.SeedAsync(context, env, settings, logger)
|
|
||||||
.Wait();
|
|
||||||
})
|
|
||||||
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
|
|
||||||
|
|
||||||
return testServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Get
|
|
||||||
{
|
|
||||||
public static string Orders = "api/v1/orders";
|
|
||||||
|
|
||||||
public static string Items = "api/v1/catalog/items";
|
|
||||||
|
|
||||||
public static string ProductByName(string name)
|
|
||||||
{
|
{
|
||||||
return $"api/v1/catalog/items/withname/{name}";
|
cb.AddJsonFile("Services/Catalog/appsettings.json", optional: false)
|
||||||
}
|
.AddEnvironmentVariables();
|
||||||
}
|
}).UseStartup<Startup>();
|
||||||
|
|
||||||
public static class Put
|
var testServer = new TestServer(hostBuilder);
|
||||||
|
|
||||||
|
testServer.Host
|
||||||
|
.MigrateDbContext<CatalogContext>((context, services) =>
|
||||||
|
{
|
||||||
|
var env = services.GetService<IWebHostEnvironment>();
|
||||||
|
var settings = services.GetService<IOptions<CatalogSettings>>();
|
||||||
|
var logger = services.GetService<ILogger<CatalogContextSeed>>();
|
||||||
|
|
||||||
|
new CatalogContextSeed()
|
||||||
|
.SeedAsync(context, env, settings, logger)
|
||||||
|
.Wait();
|
||||||
|
})
|
||||||
|
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
|
||||||
|
|
||||||
|
return testServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string Orders = "api/v1/orders";
|
||||||
|
|
||||||
|
public static string Items = "api/v1/catalog/items";
|
||||||
|
|
||||||
|
public static string ProductByName(string name)
|
||||||
{
|
{
|
||||||
public static string UpdateCatalogProduct = "api/v1/catalog/items";
|
return $"api/v1/catalog/items/withname/{name}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Put
|
||||||
|
{
|
||||||
|
public static string UpdateCatalogProduct = "api/v1/catalog/items";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,134 +1,122 @@
|
|||||||
using FunctionalTests.Services.Basket;
|
namespace FunctionalTests.Services;
|
||||||
using FunctionalTests.Services.Catalog;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Model;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Services
|
public class IntegrationEventsScenarios
|
||||||
{
|
{
|
||||||
public class IntegrationEventsScenarios
|
[Fact]
|
||||||
|
public async Task Post_update_product_price_and_catalog_and_basket_list_modified()
|
||||||
{
|
{
|
||||||
[Fact]
|
decimal priceModification = 0.15M;
|
||||||
public async Task Post_update_product_price_and_catalog_and_basket_list_modified()
|
string userId = "JohnId";
|
||||||
|
|
||||||
|
using (var catalogServer = new CatalogScenariosBase().CreateServer())
|
||||||
|
using (var basketServer = new BasketScenariosBase().CreateServer())
|
||||||
{
|
{
|
||||||
decimal priceModification = 0.15M;
|
var catalogClient = catalogServer.CreateClient();
|
||||||
string userId = "JohnId";
|
var basketClient = basketServer.CreateClient();
|
||||||
|
|
||||||
using (var catalogServer = new CatalogScenariosBase().CreateServer())
|
// GIVEN a product catalog list
|
||||||
using (var basketServer = new BasketScenariosBase().CreateServer())
|
var originalCatalogProducts = await GetCatalogAsync(catalogClient);
|
||||||
|
|
||||||
|
// AND a user basket filled with products
|
||||||
|
var basket = ComposeBasket(userId, originalCatalogProducts.Data.Take(3));
|
||||||
|
var res = await basketClient.PostAsync(
|
||||||
|
BasketScenariosBase.Post.CreateBasket,
|
||||||
|
new StringContent(JsonSerializer.Serialize(basket), UTF8Encoding.UTF8, "application/json")
|
||||||
|
);
|
||||||
|
|
||||||
|
// WHEN the price of one product is modified in the catalog
|
||||||
|
var itemToModify = basket.Items[2];
|
||||||
|
var oldPrice = itemToModify.UnitPrice;
|
||||||
|
var newPrice = oldPrice + priceModification;
|
||||||
|
var pRes = await catalogClient.PutAsync(CatalogScenariosBase.Put.UpdateCatalogProduct, new StringContent(ChangePrice(itemToModify, newPrice, originalCatalogProducts), UTF8Encoding.UTF8, "application/json"));
|
||||||
|
|
||||||
|
var modifiedCatalogProducts = await GetCatalogAsync(catalogClient);
|
||||||
|
|
||||||
|
var itemUpdated = await GetUpdatedBasketItem(newPrice, itemToModify.ProductId, userId, basketClient);
|
||||||
|
|
||||||
|
if (itemUpdated == null)
|
||||||
{
|
{
|
||||||
var catalogClient = catalogServer.CreateClient();
|
Assert.False(true, $"The basket service has not been updated.");
|
||||||
var basketClient = basketServer.CreateClient();
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//THEN the product price changes in the catalog
|
||||||
|
Assert.Equal(newPrice, modifiedCatalogProducts.Data.Single(it => it.Id == itemToModify.ProductId).Price);
|
||||||
|
|
||||||
// GIVEN a product catalog list
|
// AND the products in the basket reflects the changed priced and the original price
|
||||||
var originalCatalogProducts = await GetCatalogAsync(catalogClient);
|
Assert.Equal(newPrice, itemUpdated.UnitPrice);
|
||||||
|
Assert.Equal(oldPrice, itemUpdated.OldUnitPrice);
|
||||||
// AND a user basket filled with products
|
|
||||||
var basket = ComposeBasket(userId, originalCatalogProducts.Data.Take(3));
|
|
||||||
var res = await basketClient.PostAsync(
|
|
||||||
BasketScenariosBase.Post.CreateBasket,
|
|
||||||
new StringContent(JsonSerializer.Serialize(basket), UTF8Encoding.UTF8, "application/json")
|
|
||||||
);
|
|
||||||
|
|
||||||
// WHEN the price of one product is modified in the catalog
|
|
||||||
var itemToModify = basket.Items[2];
|
|
||||||
var oldPrice = itemToModify.UnitPrice;
|
|
||||||
var newPrice = oldPrice + priceModification;
|
|
||||||
var pRes = await catalogClient.PutAsync(CatalogScenariosBase.Put.UpdateCatalogProduct, new StringContent(ChangePrice(itemToModify, newPrice, originalCatalogProducts), UTF8Encoding.UTF8, "application/json"));
|
|
||||||
|
|
||||||
var modifiedCatalogProducts = await GetCatalogAsync(catalogClient);
|
|
||||||
|
|
||||||
var itemUpdated = await GetUpdatedBasketItem(newPrice, itemToModify.ProductId, userId, basketClient);
|
|
||||||
|
|
||||||
if (itemUpdated == null)
|
|
||||||
{
|
|
||||||
Assert.False(true, $"The basket service has not been updated.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//THEN the product price changes in the catalog
|
|
||||||
Assert.Equal(newPrice, modifiedCatalogProducts.Data.Single(it => it.Id == itemToModify.ProductId).Price);
|
|
||||||
|
|
||||||
// AND the products in the basket reflects the changed priced and the original price
|
|
||||||
Assert.Equal(newPrice, itemUpdated.UnitPrice);
|
|
||||||
Assert.Equal(oldPrice, itemUpdated.OldUnitPrice);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<BasketItem> GetUpdatedBasketItem(decimal newPrice, int productId, string userId, HttpClient basketClient)
|
private async Task<BasketItem> GetUpdatedBasketItem(decimal newPrice, int productId, string userId, HttpClient basketClient)
|
||||||
|
{
|
||||||
|
bool continueLoop = true;
|
||||||
|
var counter = 0;
|
||||||
|
BasketItem itemUpdated = null;
|
||||||
|
|
||||||
|
while (continueLoop && counter < 20)
|
||||||
{
|
{
|
||||||
bool continueLoop = true;
|
//get the basket and verify that the price of the modified product is updated
|
||||||
var counter = 0;
|
var basketGetResponse = await basketClient.GetAsync(BasketScenariosBase.Get.GetBasketByCustomer(userId));
|
||||||
BasketItem itemUpdated = null;
|
var basketUpdated = JsonSerializer.Deserialize<CustomerBasket>(await basketGetResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions
|
||||||
|
|
||||||
while (continueLoop && counter < 20)
|
|
||||||
{
|
|
||||||
//get the basket and verify that the price of the modified product is updated
|
|
||||||
var basketGetResponse = await basketClient.GetAsync(BasketScenariosBase.Get.GetBasketByCustomer(userId));
|
|
||||||
var basketUpdated = JsonSerializer.Deserialize<CustomerBasket>(await basketGetResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true
|
|
||||||
});
|
|
||||||
|
|
||||||
itemUpdated = basketUpdated.Items.Single(pr => pr.ProductId == productId);
|
|
||||||
|
|
||||||
if (itemUpdated.UnitPrice == newPrice)
|
|
||||||
{
|
|
||||||
continueLoop = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
counter++;
|
|
||||||
await Task.Delay(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return itemUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<PaginatedItemsViewModel<CatalogItem>> GetCatalogAsync(HttpClient catalogClient)
|
|
||||||
{
|
|
||||||
var response = await catalogClient.GetAsync(CatalogScenariosBase.Get.Items);
|
|
||||||
var items = await response.Content.ReadAsStringAsync();
|
|
||||||
return JsonSerializer.Deserialize<PaginatedItemsViewModel<CatalogItem>>(items, new JsonSerializerOptions
|
|
||||||
{
|
{
|
||||||
PropertyNameCaseInsensitive = true
|
PropertyNameCaseInsensitive = true
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private string ChangePrice(BasketItem itemToModify, decimal newPrice, PaginatedItemsViewModel<CatalogItem> catalogProducts)
|
itemUpdated = basketUpdated.Items.Single(pr => pr.ProductId == productId);
|
||||||
{
|
|
||||||
var catalogProduct = catalogProducts.Data.Single(pr => pr.Id == itemToModify.ProductId);
|
|
||||||
catalogProduct.Price = newPrice;
|
|
||||||
return JsonSerializer.Serialize(catalogProduct);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CustomerBasket ComposeBasket(string customerId, IEnumerable<CatalogItem> items)
|
if (itemUpdated.UnitPrice == newPrice)
|
||||||
{
|
|
||||||
var basket = new CustomerBasket(customerId);
|
|
||||||
foreach (var item in items)
|
|
||||||
{
|
{
|
||||||
basket.Items.Add(new BasketItem()
|
continueLoop = false;
|
||||||
{
|
}
|
||||||
Id = Guid.NewGuid().ToString(),
|
else
|
||||||
UnitPrice = item.Price,
|
{
|
||||||
PictureUrl = item.PictureUri,
|
counter++;
|
||||||
ProductId = item.Id,
|
await Task.Delay(100);
|
||||||
OldUnitPrice = 0,
|
|
||||||
ProductName = item.Name,
|
|
||||||
Quantity = 1
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return basket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return itemUpdated;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private async Task<PaginatedItemsViewModel<CatalogItem>> GetCatalogAsync(HttpClient catalogClient)
|
||||||
|
{
|
||||||
|
var response = await catalogClient.GetAsync(CatalogScenariosBase.Get.Items);
|
||||||
|
var items = await response.Content.ReadAsStringAsync();
|
||||||
|
return JsonSerializer.Deserialize<PaginatedItemsViewModel<CatalogItem>>(items, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ChangePrice(BasketItem itemToModify, decimal newPrice, PaginatedItemsViewModel<CatalogItem> catalogProducts)
|
||||||
|
{
|
||||||
|
var catalogProduct = catalogProducts.Data.Single(pr => pr.Id == itemToModify.ProductId);
|
||||||
|
catalogProduct.Price = newPrice;
|
||||||
|
return JsonSerializer.Serialize(catalogProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomerBasket ComposeBasket(string customerId, IEnumerable<CatalogItem> items)
|
||||||
|
{
|
||||||
|
var basket = new CustomerBasket(customerId);
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
basket.Items.Add(new BasketItem()
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid().ToString(),
|
||||||
|
UnitPrice = item.Price,
|
||||||
|
PictureUrl = item.PictureUri,
|
||||||
|
ProductId = item.Id,
|
||||||
|
OldUnitPrice = 0,
|
||||||
|
ProductName = item.Name,
|
||||||
|
Quantity = 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return basket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,156 +1,141 @@
|
|||||||
using FunctionalTests.Extensions;
|
namespace FunctionalTests.Services.Ordering;
|
||||||
using FunctionalTests.Services.Basket;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
|
||||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
|
||||||
using System;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using WebMVC.Services.ModelDTOs;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Services.Ordering
|
public class OrderingScenarios : OrderingScenariosBase
|
||||||
{
|
{
|
||||||
public class OrderingScenarios : OrderingScenariosBase
|
[Fact]
|
||||||
|
public async Task Cancel_basket_and_check_order_status_cancelled()
|
||||||
{
|
{
|
||||||
[Fact]
|
using (var orderServer = new OrderingScenariosBase().CreateServer())
|
||||||
public async Task Cancel_basket_and_check_order_status_cancelled()
|
using (var basketServer = new BasketScenariosBase().CreateServer())
|
||||||
{
|
{
|
||||||
using (var orderServer = new OrderingScenariosBase().CreateServer())
|
// Expected data
|
||||||
using (var basketServer = new BasketScenariosBase().CreateServer())
|
var cityExpected = $"city-{Guid.NewGuid()}";
|
||||||
{
|
var orderStatusExpected = "cancelled";
|
||||||
// Expected data
|
|
||||||
var cityExpected = $"city-{Guid.NewGuid()}";
|
|
||||||
var orderStatusExpected = "cancelled";
|
|
||||||
|
|
||||||
var basketClient = basketServer.CreateIdempotentClient();
|
var basketClient = basketServer.CreateIdempotentClient();
|
||||||
var orderClient = orderServer.CreateIdempotentClient();
|
var orderClient = orderServer.CreateIdempotentClient();
|
||||||
|
|
||||||
// GIVEN a basket is created
|
// GIVEN a basket is created
|
||||||
var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json");
|
var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json");
|
||||||
await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket);
|
await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket);
|
||||||
|
|
||||||
// AND basket checkout is sent
|
// AND basket checkout is sent
|
||||||
await basketClient.PostAsync(BasketScenariosBase.Post.CheckoutOrder, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json"));
|
await basketClient.PostAsync(BasketScenariosBase.Post.CheckoutOrder, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json"));
|
||||||
|
|
||||||
// WHEN Order is created in Ordering.api
|
// WHEN Order is created in Ordering.api
|
||||||
var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient);
|
var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient);
|
||||||
|
|
||||||
// AND Order is cancelled in Ordering.api
|
// AND Order is cancelled in Ordering.api
|
||||||
await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json"));
|
await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json"));
|
||||||
|
|
||||||
// AND the requested order is retrieved
|
// AND the requested order is retrieved
|
||||||
var order = await TryGetOrder(newOrder.OrderNumber, orderClient);
|
var order = await TryGetOrder(newOrder.OrderNumber, orderClient);
|
||||||
|
|
||||||
// THEN check status
|
// THEN check status
|
||||||
Assert.Equal(orderStatusExpected, order.Status);
|
Assert.Equal(orderStatusExpected, order.Status);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async Task<Order> TryGetOrder(string orderNumber, HttpClient orderClient)
|
async Task<Order> TryGetOrder(string orderNumber, HttpClient orderClient)
|
||||||
|
{
|
||||||
|
var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders);
|
||||||
|
var orders = JsonSerializer.Deserialize<List<Order>>(ordersGetResponse, new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
|
PropertyNameCaseInsensitive = true
|
||||||
|
});
|
||||||
|
|
||||||
|
return orders.Single(o => o.OrderNumber == orderNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Order> TryGetNewOrderCreated(string city, HttpClient orderClient)
|
||||||
|
{
|
||||||
|
var counter = 0;
|
||||||
|
Order order = null;
|
||||||
|
|
||||||
|
while (counter < 20)
|
||||||
|
{
|
||||||
|
//get the orders and verify that the new order has been created
|
||||||
var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders);
|
var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders);
|
||||||
var orders = JsonSerializer.Deserialize<List<Order>>(ordersGetResponse, new JsonSerializerOptions
|
var orders = JsonSerializer.Deserialize<List<Order>>(ordersGetResponse, new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
PropertyNameCaseInsensitive = true
|
PropertyNameCaseInsensitive = true
|
||||||
});
|
});
|
||||||
|
|
||||||
return orders.Single(o => o.OrderNumber == orderNumber);
|
if (orders == null || orders.Count == 0)
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Order> TryGetNewOrderCreated(string city, HttpClient orderClient)
|
|
||||||
{
|
|
||||||
var counter = 0;
|
|
||||||
Order order = null;
|
|
||||||
|
|
||||||
while (counter < 20)
|
|
||||||
{
|
{
|
||||||
//get the orders and verify that the new order has been created
|
counter++;
|
||||||
var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders);
|
await Task.Delay(100);
|
||||||
var orders = JsonSerializer.Deserialize<List<Order>>(ordersGetResponse, new JsonSerializerOptions
|
continue;
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (orders == null || orders.Count == 0)
|
|
||||||
{
|
|
||||||
counter++;
|
|
||||||
await Task.Delay(100);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastOrder = orders.OrderByDescending(o => o.Date).First();
|
|
||||||
int.TryParse(lastOrder.OrderNumber, out int id);
|
|
||||||
var orderDetails = await orderClient.GetStringAsync(OrderingScenariosBase.Get.OrderBy(id));
|
|
||||||
order = JsonSerializer.Deserialize<Order>(orderDetails, new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true
|
|
||||||
});
|
|
||||||
|
|
||||||
order.City = city;
|
|
||||||
|
|
||||||
if (IsOrderCreated(order, city))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return order;
|
var lastOrder = orders.OrderByDescending(o => o.Date).First();
|
||||||
}
|
int.TryParse(lastOrder.OrderNumber, out int id);
|
||||||
|
var orderDetails = await orderClient.GetStringAsync(OrderingScenariosBase.Get.OrderBy(id));
|
||||||
private bool IsOrderCreated(Order order, string city)
|
order = JsonSerializer.Deserialize<Order>(orderDetails, new JsonSerializerOptions
|
||||||
{
|
|
||||||
return order.City == city;
|
|
||||||
}
|
|
||||||
|
|
||||||
string BuildBasket()
|
|
||||||
{
|
|
||||||
var order = new CustomerBasket("9e3163b9-1ae6-4652-9dc6-7898ab7b7a00");
|
|
||||||
order.Items = new List<Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem>()
|
|
||||||
{
|
{
|
||||||
new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem()
|
PropertyNameCaseInsensitive = true
|
||||||
{
|
});
|
||||||
Id = "1",
|
|
||||||
ProductName = "ProductName",
|
order.City = city;
|
||||||
ProductId = 1,
|
|
||||||
UnitPrice = 10,
|
|
||||||
Quantity = 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return JsonSerializer.Serialize(order);
|
|
||||||
}
|
|
||||||
|
|
||||||
string BuildCancelOrder(string orderId)
|
if (IsOrderCreated(order, city))
|
||||||
{
|
|
||||||
var order = new OrderDTO()
|
|
||||||
{
|
{
|
||||||
OrderNumber = orderId
|
break;
|
||||||
};
|
}
|
||||||
return JsonSerializer.Serialize(order);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string BuildCheckout(string cityExpected)
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsOrderCreated(Order order, string city)
|
||||||
|
{
|
||||||
|
return order.City == city;
|
||||||
|
}
|
||||||
|
|
||||||
|
string BuildBasket()
|
||||||
|
{
|
||||||
|
var order = new CustomerBasket("9e3163b9-1ae6-4652-9dc6-7898ab7b7a00");
|
||||||
|
order.Items = new List<Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem>()
|
||||||
{
|
{
|
||||||
var checkoutBasket = new BasketDTO()
|
new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem()
|
||||||
{
|
{
|
||||||
City = cityExpected,
|
Id = "1",
|
||||||
Street = "street",
|
ProductName = "ProductName",
|
||||||
State = "state",
|
ProductId = 1,
|
||||||
Country = "coutry",
|
UnitPrice = 10,
|
||||||
ZipCode = "zipcode",
|
Quantity = 1
|
||||||
CardNumber = "1111111111111",
|
}
|
||||||
CardHolderName = "CardHolderName",
|
};
|
||||||
CardExpiration = DateTime.Now.AddYears(1),
|
return JsonSerializer.Serialize(order);
|
||||||
CardSecurityNumber = "123",
|
}
|
||||||
CardTypeId = 1,
|
|
||||||
Buyer = "Buyer",
|
|
||||||
RequestId = Guid.NewGuid()
|
|
||||||
};
|
|
||||||
|
|
||||||
return JsonSerializer.Serialize(checkoutBasket);
|
string BuildCancelOrder(string orderId)
|
||||||
}
|
{
|
||||||
|
var order = new OrderDTO()
|
||||||
|
{
|
||||||
|
OrderNumber = orderId
|
||||||
|
};
|
||||||
|
return JsonSerializer.Serialize(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
string BuildCheckout(string cityExpected)
|
||||||
|
{
|
||||||
|
var checkoutBasket = new BasketDTO()
|
||||||
|
{
|
||||||
|
City = cityExpected,
|
||||||
|
Street = "street",
|
||||||
|
State = "state",
|
||||||
|
Country = "coutry",
|
||||||
|
ZipCode = "zipcode",
|
||||||
|
CardNumber = "1111111111111",
|
||||||
|
CardHolderName = "CardHolderName",
|
||||||
|
CardExpiration = DateTime.Now.AddYears(1),
|
||||||
|
CardSecurityNumber = "123",
|
||||||
|
CardTypeId = 1,
|
||||||
|
Buyer = "Buyer",
|
||||||
|
RequestId = Guid.NewGuid()
|
||||||
|
};
|
||||||
|
|
||||||
|
return JsonSerializer.Serialize(checkoutBasket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,77 +1,63 @@
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
namespace FunctionalTests.Services.Ordering;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Services.Ordering
|
public class OrderingScenariosBase
|
||||||
{
|
{
|
||||||
public class OrderingScenariosBase
|
public TestServer CreateServer()
|
||||||
{
|
{
|
||||||
public TestServer CreateServer()
|
var path = Assembly.GetAssembly(typeof(OrderingScenariosBase))
|
||||||
{
|
.Location;
|
||||||
var path = Assembly.GetAssembly(typeof(OrderingScenariosBase))
|
|
||||||
.Location;
|
|
||||||
|
|
||||||
var hostBuilder = new WebHostBuilder()
|
var hostBuilder = new WebHostBuilder()
|
||||||
.UseContentRoot(Path.GetDirectoryName(path))
|
.UseContentRoot(Path.GetDirectoryName(path))
|
||||||
.ConfigureAppConfiguration(cb =>
|
.ConfigureAppConfiguration(cb =>
|
||||||
{
|
|
||||||
cb.AddJsonFile("Services/Ordering/appsettings.json", optional: false)
|
|
||||||
.AddEnvironmentVariables();
|
|
||||||
}).UseStartup<OrderingTestsStartup>();
|
|
||||||
|
|
||||||
var testServer = new TestServer(hostBuilder);
|
|
||||||
|
|
||||||
testServer.Host
|
|
||||||
.MigrateDbContext<OrderingContext>((context, services) =>
|
|
||||||
{
|
|
||||||
var env = services.GetService<IWebHostEnvironment>();
|
|
||||||
var settings = services.GetService<IOptions<OrderingSettings>>();
|
|
||||||
var logger = services.GetService<ILogger<OrderingContextSeed>>();
|
|
||||||
|
|
||||||
new OrderingContextSeed()
|
|
||||||
.SeedAsync(context, env, settings, logger)
|
|
||||||
.Wait();
|
|
||||||
})
|
|
||||||
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
|
|
||||||
|
|
||||||
return testServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Get
|
|
||||||
{
|
|
||||||
public static string Orders = "api/v1/orders";
|
|
||||||
|
|
||||||
public static string OrderBy(int id)
|
|
||||||
{
|
{
|
||||||
return $"api/v1/orders/{id}";
|
cb.AddJsonFile("Services/Ordering/appsettings.json", optional: false)
|
||||||
}
|
.AddEnvironmentVariables();
|
||||||
}
|
}).UseStartup<OrderingTestsStartup>();
|
||||||
|
|
||||||
public static class Post
|
var testServer = new TestServer(hostBuilder);
|
||||||
{
|
|
||||||
public static string AddNewOrder = "api/v1/orders/new";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Put
|
testServer.Host
|
||||||
{
|
.MigrateDbContext<OrderingContext>((context, services) =>
|
||||||
public static string CancelOrder = "api/v1/orders/cancel";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Delete
|
|
||||||
{
|
|
||||||
public static string OrderBy(int id)
|
|
||||||
{
|
{
|
||||||
return $"api/v1/orders/{id}";
|
var env = services.GetService<IWebHostEnvironment>();
|
||||||
}
|
var settings = services.GetService<IOptions<OrderingSettings>>();
|
||||||
|
var logger = services.GetService<ILogger<OrderingContextSeed>>();
|
||||||
|
|
||||||
|
new OrderingContextSeed()
|
||||||
|
.SeedAsync(context, env, settings, logger)
|
||||||
|
.Wait();
|
||||||
|
})
|
||||||
|
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
|
||||||
|
|
||||||
|
return testServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string Orders = "api/v1/orders";
|
||||||
|
|
||||||
|
public static string OrderBy(int id)
|
||||||
|
{
|
||||||
|
return $"api/v1/orders/{id}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Post
|
||||||
|
{
|
||||||
|
public static string AddNewOrder = "api/v1/orders/new";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Put
|
||||||
|
{
|
||||||
|
public static string CancelOrder = "api/v1/orders/cancel";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Delete
|
||||||
|
{
|
||||||
|
public static string OrderBy(int id)
|
||||||
|
{
|
||||||
|
return $"api/v1/orders/{id}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,22 @@
|
|||||||
using FunctionalTests.Middleware;
|
namespace FunctionalTests.Services.Ordering;
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API;
|
using Microsoft.eShopOnContainers.Services.Ordering.API;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
|
|
||||||
namespace FunctionalTests.Services.Ordering
|
public class OrderingTestsStartup : Startup
|
||||||
{
|
{
|
||||||
public class OrderingTestsStartup : Startup
|
public OrderingTestsStartup(IConfiguration env) : base(env)
|
||||||
{
|
{
|
||||||
public OrderingTestsStartup(IConfiguration env) : base(env)
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ConfigureAuth(IApplicationBuilder app)
|
protected override void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant())
|
||||||
{
|
{
|
||||||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant())
|
app.UseMiddleware<AutoAuthorizeMiddleware>();
|
||||||
{
|
app.UseAuthorization();
|
||||||
app.UseMiddleware<AutoAuthorizeMiddleware>();
|
}
|
||||||
app.UseAuthorization();
|
else
|
||||||
}
|
{
|
||||||
else
|
base.ConfigureAuth(app);
|
||||||
{
|
|
||||||
base.ConfigureAuth(app);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user