From 18c5d3d28c7b9f6adb63a2c1fb4f5f6218189ea8 Mon Sep 17 00:00:00 2001 From: Unai Zorrilla Castro Date: Mon, 25 Jun 2018 11:36:42 +0200 Subject: [PATCH 01/13] Organized test projects for each service --- eShopOnContainers-ServicesAndWebApps.sln | 306 ++++++++++++++++++ .../Base/AutoAuthorizeMiddleware.cs | 26 ++ .../Base/BasketScenarioBase.cs | 38 +++ .../Base/BasketTestStartup.cs | 25 ++ .../Base/HttpClientExtensions.cs | 18 ++ .../Basket.FunctionalTests.csproj | 22 ++ .../Basket.FunctionalTests/BasketScenarios.cs | 94 ++++++ .../RedisBasketRepositoryTests.cs | 78 +++++ test/Basket.FunctionalTests/appsettings.json | 15 + .../Application/BasketWebApiTest.cs | 116 +++++++ .../Application/CartControllerTest.cs | 130 ++++++++ test/Basket.UnitTests/Basket.UnitTests.csproj | 23 ++ .../Application/CatalogControllerTest.cs | 90 ++++++ .../Catalog.UnitTests.csproj | 22 ++ .../Base/AutoAuthorizeMiddleware.cs | 26 ++ .../Base/CampaignScenarioBase.cs | 37 +++ .../Base/CampaignsScenarioBase.cs | 37 +++ .../Base/LocationsScenarioBase.cs | 40 +++ .../Base/LocationsTestStartup.cs | 44 +++ .../Base/MarketingScenarioBase.cs | 36 +++ .../Base/MarketingTestStartup.cs | 28 ++ .../Base/UserLocationRoleScenarioBase.cs | 45 +++ .../Marketing.FunctionalTests.csproj | 30 ++ .../MarketingScenario.cs | 46 +++ .../appsettings.json | 12 + .../Base/AutoAuthorizedMiddleware.cs | 26 ++ .../Base/BasketScenarioBase.cs | 35 ++ .../Base/BasketTestStartup.cs | 25 ++ .../Base/HttpClientExtensions.cs | 18 ++ .../Base/OrderingScenarioBase.cs | 75 +++++ .../Base/OrderingTestStartup.cs | 25 ++ .../Ordering.FunctionalTests.csproj | 29 ++ .../OrderingScenario.cs | 185 +++++++++++ test/Ordering.FunctionalTests/settings.json | 10 + .../IdentifiedCommandHandlerTest.cs | 91 ++++++ .../Application/NewOrderCommandHandlerTest.cs | 94 ++++++ .../Application/OrderControllerTest.cs | 86 +++++ .../Application/OrdersWebApiTest.cs | 141 ++++++++ test/Ordering.UnitTests/Builders.cs | 48 +++ .../Domain/BuyerAggregateTest.cs | 132 ++++++++ .../Domain/OrderAggregateTest.cs | 180 +++++++++++ .../Ordering.UnitTests.csproj | 25 ++ 42 files changed, 2609 insertions(+) create mode 100644 test/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs create mode 100644 test/Basket.FunctionalTests/Base/BasketScenarioBase.cs create mode 100644 test/Basket.FunctionalTests/Base/BasketTestStartup.cs create mode 100644 test/Basket.FunctionalTests/Base/HttpClientExtensions.cs create mode 100644 test/Basket.FunctionalTests/Basket.FunctionalTests.csproj create mode 100644 test/Basket.FunctionalTests/BasketScenarios.cs create mode 100644 test/Basket.FunctionalTests/RedisBasketRepositoryTests.cs create mode 100644 test/Basket.FunctionalTests/appsettings.json create mode 100644 test/Basket.UnitTests/Application/BasketWebApiTest.cs create mode 100644 test/Basket.UnitTests/Application/CartControllerTest.cs create mode 100644 test/Basket.UnitTests/Basket.UnitTests.csproj create mode 100644 test/Catalog.UnitTests/Application/CatalogControllerTest.cs create mode 100644 test/Catalog.UnitTests/Catalog.UnitTests.csproj create mode 100644 test/Marketing.FunctionalTests/Base/AutoAuthorizeMiddleware.cs create mode 100644 test/Marketing.FunctionalTests/Base/CampaignScenarioBase.cs create mode 100644 test/Marketing.FunctionalTests/Base/CampaignsScenarioBase.cs create mode 100644 test/Marketing.FunctionalTests/Base/LocationsScenarioBase.cs create mode 100644 test/Marketing.FunctionalTests/Base/LocationsTestStartup.cs create mode 100644 test/Marketing.FunctionalTests/Base/MarketingScenarioBase.cs create mode 100644 test/Marketing.FunctionalTests/Base/MarketingTestStartup.cs create mode 100644 test/Marketing.FunctionalTests/Base/UserLocationRoleScenarioBase.cs create mode 100644 test/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj create mode 100644 test/Marketing.FunctionalTests/MarketingScenario.cs create mode 100644 test/Marketing.FunctionalTests/appsettings.json create mode 100644 test/Ordering.FunctionalTests/Base/AutoAuthorizedMiddleware.cs create mode 100644 test/Ordering.FunctionalTests/Base/BasketScenarioBase.cs create mode 100644 test/Ordering.FunctionalTests/Base/BasketTestStartup.cs create mode 100644 test/Ordering.FunctionalTests/Base/HttpClientExtensions.cs create mode 100644 test/Ordering.FunctionalTests/Base/OrderingScenarioBase.cs create mode 100644 test/Ordering.FunctionalTests/Base/OrderingTestStartup.cs create mode 100644 test/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj create mode 100644 test/Ordering.FunctionalTests/OrderingScenario.cs create mode 100644 test/Ordering.FunctionalTests/settings.json create mode 100644 test/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs create mode 100644 test/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs create mode 100644 test/Ordering.UnitTests/Application/OrderControllerTest.cs create mode 100644 test/Ordering.UnitTests/Application/OrdersWebApiTest.cs create mode 100644 test/Ordering.UnitTests/Builders.cs create mode 100644 test/Ordering.UnitTests/Domain/BuyerAggregateTest.cs create mode 100644 test/Ordering.UnitTests/Domain/OrderAggregateTest.cs create mode 100644 test/Ordering.UnitTests/Ordering.UnitTests.csproj diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index f9e3e654e..423994cc9 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -128,6 +128,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.BackgroundTasks", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.SignalrHub", "src\Services\Ordering\Ordering.SignalrHub\Ordering.SignalrHub.csproj", "{E1D2B260-4E7F-4A88-BC13-9910F7C44623}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.FunctionalTests", "test\Ordering.FunctionalTests\Ordering.FunctionalTests.csproj", "{022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ordering.UnitTests", "test\Ordering.UnitTests\Ordering.UnitTests.csproj", "{AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Basket.UnitTests", "test\Basket.UnitTests\Basket.UnitTests.csproj", "{3757B89F-742C-441C-BAEF-F36F0F8280C9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Basket.FunctionalTests", "test\Basket.FunctionalTests\Basket.FunctionalTests.csproj", "{9E0439C7-7050-4FFC-99C6-4A0DBD123D89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.UnitTests", "test\Catalog.UnitTests\Catalog.UnitTests.csproj", "{F88BB248-B57B-419C-A443-EB9DC3557412}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marketing.FunctionalTests", "test\Marketing.FunctionalTests\Marketing.FunctionalTests.csproj", "{4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1534,6 +1546,294 @@ Global {E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|x64.Build.0 = Release|Any CPU {E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|x86.ActiveCfg = Release|Any CPU {E1D2B260-4E7F-4A88-BC13-9910F7C44623}.Release|x86.Build.0 = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|ARM.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|iPhone.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|x64.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|x64.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|x86.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.AppStore|x86.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|ARM.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|iPhone.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|x64.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|x64.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|x86.ActiveCfg = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Debug|x86.Build.0 = Debug|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|Any CPU.Build.0 = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|ARM.ActiveCfg = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|ARM.Build.0 = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|iPhone.ActiveCfg = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|iPhone.Build.0 = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|x64.ActiveCfg = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|x64.Build.0 = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|x86.ActiveCfg = Release|Any CPU + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A}.Release|x86.Build.0 = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|ARM.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|iPhone.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|x64.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|x64.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|x86.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.AppStore|x86.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|ARM.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|ARM.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|iPhone.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|x64.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|x86.ActiveCfg = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Debug|x86.Build.0 = Debug|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|Any CPU.Build.0 = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|ARM.ActiveCfg = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|ARM.Build.0 = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|iPhone.ActiveCfg = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|iPhone.Build.0 = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|x64.ActiveCfg = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|x64.Build.0 = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|x86.ActiveCfg = Release|Any CPU + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2}.Release|x86.Build.0 = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|ARM.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|iPhone.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|x64.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|x64.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|x86.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.AppStore|x86.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|ARM.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|iPhone.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|x64.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|x64.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|x86.ActiveCfg = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Debug|x86.Build.0 = Debug|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|Any CPU.Build.0 = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|ARM.ActiveCfg = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|ARM.Build.0 = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|iPhone.ActiveCfg = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|iPhone.Build.0 = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|x64.ActiveCfg = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|x64.Build.0 = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|x86.ActiveCfg = Release|Any CPU + {3757B89F-742C-441C-BAEF-F36F0F8280C9}.Release|x86.Build.0 = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|ARM.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|iPhone.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|x64.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|x64.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|x86.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.AppStore|x86.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|ARM.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|iPhone.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|x64.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|x64.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|x86.ActiveCfg = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Debug|x86.Build.0 = Debug|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|Any CPU.Build.0 = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|ARM.ActiveCfg = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|ARM.Build.0 = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|iPhone.ActiveCfg = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|iPhone.Build.0 = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|x64.ActiveCfg = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|x64.Build.0 = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|x86.ActiveCfg = Release|Any CPU + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89}.Release|x86.Build.0 = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|ARM.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|iPhone.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|x64.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|x64.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|x86.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.AppStore|x86.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|ARM.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|ARM.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|iPhone.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|x64.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|x64.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|x86.ActiveCfg = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Debug|x86.Build.0 = Debug|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|Any CPU.Build.0 = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|ARM.ActiveCfg = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|ARM.Build.0 = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|iPhone.ActiveCfg = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|iPhone.Build.0 = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|x64.ActiveCfg = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|x64.Build.0 = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|x86.ActiveCfg = Release|Any CPU + {F88BB248-B57B-419C-A443-EB9DC3557412}.Release|x86.Build.0 = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|ARM.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|iPhone.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|x64.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|x64.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|x86.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.AppStore|x86.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|ARM.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|ARM.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|iPhone.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|x64.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|x86.ActiveCfg = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Debug|x86.Build.0 = Debug|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|Any CPU.Build.0 = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|ARM.ActiveCfg = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|ARM.Build.0 = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|iPhone.ActiveCfg = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|iPhone.Build.0 = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|x64.ActiveCfg = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|x64.Build.0 = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|x86.ActiveCfg = Release|Any CPU + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1589,6 +1889,12 @@ Global {AF0828DB-8BDD-411A-AEEF-B780FBB8D8C1} = {28C0F5C8-4849-4035-80AB-45639424E73F} {7D63ED4A-3EDA-4BBA-8BBA-F46BD6430931} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} {E1D2B260-4E7F-4A88-BC13-9910F7C44623} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} + {022804A2-D4D5-4F6D-B2C0-3D761F2B5D5A} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} + {AFCED70D-7DA2-44EB-8E7F-D494F9EA3ED2} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} + {3757B89F-742C-441C-BAEF-F36F0F8280C9} = {BF3EF4F3-E4F5-41DA-9D2D-57223687D1A8} + {9E0439C7-7050-4FFC-99C6-4A0DBD123D89} = {BF3EF4F3-E4F5-41DA-9D2D-57223687D1A8} + {F88BB248-B57B-419C-A443-EB9DC3557412} = {326A7FB3-5295-468C-A4FE-67DCB823E1E5} + {4E92B6D3-DFF1-471E-B2E1-B0AFF72412EE} = {A5260DE0-1FDD-467E-9CC1-A028AB081CEE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9} diff --git a/test/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs b/test/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs new file mode 100644 index 000000000..e285cfbf4 --- /dev/null +++ b/test/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Http; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Basket.FunctionalTests.Base +{ + class AutoAuthorizeMiddleware + { + private readonly RequestDelegate _next; + + public AutoAuthorizeMiddleware(RequestDelegate rd) + { + _next = rd; + } + + public async Task Invoke(HttpContext httpContext) + { + var identity = new ClaimsIdentity("cookies"); + + identity.AddClaim(new Claim("sub", "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00")); + httpContext.User.AddIdentity(identity); + + await _next.Invoke(httpContext); + } + } +} diff --git a/test/Basket.FunctionalTests/Base/BasketScenarioBase.cs b/test/Basket.FunctionalTests/Base/BasketScenarioBase.cs new file mode 100644 index 000000000..095578dc3 --- /dev/null +++ b/test/Basket.FunctionalTests/Base/BasketScenarioBase.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Basket.FunctionalTests.Base +{ + public class BasketScenarioBase + { + private const string ApiUrlBase = "api/v1/basket"; + + public TestServer CreateServer() + { + var webHostBuilder = WebHost.CreateDefaultBuilder(); + webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\basket"); + webHostBuilder.UseStartup(); + + return new TestServer(webHostBuilder); + } + + public static class Get + { + public static string GetBasket(int id) + { + return $"{ApiUrlBase}/{id}"; + } + } + + public static class Post + { + public static string Basket = $"{ApiUrlBase}/"; + public static string CheckoutOrder = $"{ApiUrlBase}/checkout"; + } + } +} diff --git a/test/Basket.FunctionalTests/Base/BasketTestStartup.cs b/test/Basket.FunctionalTests/Base/BasketTestStartup.cs new file mode 100644 index 000000000..4d77f6dc5 --- /dev/null +++ b/test/Basket.FunctionalTests/Base/BasketTestStartup.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.eShopOnContainers.Services.Basket.API; +using Microsoft.Extensions.Configuration; + +namespace Basket.FunctionalTests.Base +{ + class BasketTestsStartup : Startup + { + public BasketTestsStartup(IConfiguration env) : base(env) + { + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) + { + app.UseMiddleware(); + } + else + { + base.ConfigureAuth(app); + } + } + } +} diff --git a/test/Basket.FunctionalTests/Base/HttpClientExtensions.cs b/test/Basket.FunctionalTests/Base/HttpClientExtensions.cs new file mode 100644 index 000000000..f2da0b13e --- /dev/null +++ b/test/Basket.FunctionalTests/Base/HttpClientExtensions.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.TestHost; +using System; +using System.Net.Http; + +namespace Basket.FunctionalTests.Base +{ + static class HttpClientExtensions + { + public static HttpClient CreateIdempotentClient(this TestServer server) + { + var client = server.CreateClient(); + + client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); + + return client; + } + } +} diff --git a/test/Basket.FunctionalTests/Basket.FunctionalTests.csproj b/test/Basket.FunctionalTests/Basket.FunctionalTests.csproj new file mode 100644 index 000000000..e0d7316ac --- /dev/null +++ b/test/Basket.FunctionalTests/Basket.FunctionalTests.csproj @@ -0,0 +1,22 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + + + diff --git a/test/Basket.FunctionalTests/BasketScenarios.cs b/test/Basket.FunctionalTests/BasketScenarios.cs new file mode 100644 index 000000000..26a31c37d --- /dev/null +++ b/test/Basket.FunctionalTests/BasketScenarios.cs @@ -0,0 +1,94 @@ +using Basket.FunctionalTests.Base; +using Microsoft.eShopOnContainers.Services.Basket.API.Model; +using Newtonsoft.Json; +using System; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using WebMVC.Models; +using Xunit; + +namespace Basket.FunctionalTests +{ + public class BasketScenarios + : BasketScenarioBase + { + [Fact] + public async Task Post_basket_and_response_ok_status_code() + { + using (var server = CreateServer()) + { + var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateClient() + .PostAsync(Post.Basket, content); + + response.EnsureSuccessStatusCode(); + } + } + + [Fact] + public async Task Get_basket_and_response_ok_status_code() + { + using (var server = CreateServer()) + { + var response = await server.CreateClient() + .GetAsync(Get.GetBasket(1)); + + response.EnsureSuccessStatusCode(); + } + } + + [Fact] + public async Task Send_Checkout_basket_and_response_ok_status_code() + { + using (var server = CreateServer()) + { + var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + await server.CreateClient() + .PostAsync(Post.Basket, contentBasket); + + var contentCheckout = new StringContent(BuildCheckout(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateIdempotentClient() + .PostAsync(Post.CheckoutOrder, contentCheckout); + + response.EnsureSuccessStatusCode(); + } + } + + string BuildBasket() + { + var order = new CustomerBasket("1234"); + + order.Items.Add(new BasketItem + { + ProductId = "1", + ProductName = ".NET Bot Black Hoodie", + UnitPrice = 10, + Quantity = 1 + }); + + return JsonConvert.SerializeObject(order); + } + + string BuildCheckout() + { + var checkoutBasket = new BasketDTO() + { + City = "city", + Street = "street", + State = "state", + Country = "coutry", + ZipCode = "zipcode", + CardNumber = "1234567890123456", + CardHolderName = "CardHolderName", + CardExpiration = DateTime.UtcNow.AddDays(1), + CardSecurityNumber = "123", + CardTypeId = 1, + Buyer = "Buyer", + RequestId = Guid.NewGuid() + }; + + return JsonConvert.SerializeObject(checkoutBasket); + } + } +} diff --git a/test/Basket.FunctionalTests/RedisBasketRepositoryTests.cs b/test/Basket.FunctionalTests/RedisBasketRepositoryTests.cs new file mode 100644 index 000000000..2f2564df8 --- /dev/null +++ b/test/Basket.FunctionalTests/RedisBasketRepositoryTests.cs @@ -0,0 +1,78 @@ +using Microsoft.eShopOnContainers.Services.Basket.API; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Basket.FunctionalTests +{ + //public class RedisBasketRepositoryTests + //{ + // private Mock> _optionsMock; + + // public RedisBasketRepositoryTests() + // { + // _optionsMock = new Mock>(); + // } + + // [Fact] + // public async Task UpdateBasket_return_and_add_basket() + // { + // var redisBasketRepository = BuildBasketRepository(); + + // var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") + // { + // BuyerId = "buyerId", + // Items = BuildBasketItems() + // }); + + // Assert.NotNull(basket); + // Assert.Single(basket.Items); + // } + + // [Fact] + // public async Task Delete_Basket_return_null() + // { + // var redisBasketRepository = BuildBasketRepository(); + + // var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") + // { + // BuyerId = "buyerId", + // Items = BuildBasketItems() + // }); + + // var deleteResult = await redisBasketRepository.DeleteBasketAsync("buyerId"); + + // var result = await redisBasketRepository.GetBasketAsync(basket.BuyerId); + + // Assert.True(deleteResult); + // Assert.Null(result); + // } + + // RedisBasketRepository BuildBasketRepository() + // { + // var loggerFactory = new LoggerFactory(); + // var configuration = ConfigurationOptions.Parse("127.0.0.1", true); + // configuration.ResolveDns = true; + // return new RedisBasketRepository(loggerFactory, ConnectionMultiplexer.Connect(configuration)); + // } + + // List BuildBasketItems() + // { + // return new List() + // { + // new BasketItem() + // { + // Id = "basketId", + // PictureUrl = "pictureurl", + // ProductId = "productId", + // ProductName = "productName", + // Quantity = 1, + // UnitPrice = 1 + // } + // }; + // } + //} +} diff --git a/test/Basket.FunctionalTests/appsettings.json b/test/Basket.FunctionalTests/appsettings.json new file mode 100644 index 000000000..5e8dbc02e --- /dev/null +++ b/test/Basket.FunctionalTests/appsettings.json @@ -0,0 +1,15 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + }, + "IdentityUrl": "http://localhost:5105", + "ConnectionString": "127.0.0.1", + "isTest": "true", + "EventBusConnection": "localhost", + "SubscriptionClientName": "Basket" +} diff --git a/test/Basket.UnitTests/Application/BasketWebApiTest.cs b/test/Basket.UnitTests/Application/BasketWebApiTest.cs new file mode 100644 index 000000000..7e17a9980 --- /dev/null +++ b/test/Basket.UnitTests/Application/BasketWebApiTest.cs @@ -0,0 +1,116 @@ +using Basket.API.IntegrationEvents.Events; +using Basket.API.Model; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.Services.Basket.API.Controllers; +using Microsoft.eShopOnContainers.Services.Basket.API.Model; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using IBasketIdentityService = Microsoft.eShopOnContainers.Services.Basket.API.Services.IIdentityService; + +namespace UnitTest.Basket.Application +{ + public class BasketWebApiTest + { + private readonly Mock _basketRepositoryMock; + private readonly Mock _identityServiceMock; + private readonly Mock _serviceBusMock; + + public BasketWebApiTest() + { + _basketRepositoryMock = new Mock(); + _identityServiceMock = new Mock(); + _serviceBusMock = new Mock(); + } + + [Fact] + public async Task Get_customer_basket_success() + { + //Arrange + var fakeCustomerId = "1"; + var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); + + _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) + .Returns(Task.FromResult(fakeCustomerBasket)); + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + + _serviceBusMock.Setup(x => x.Publish(It.IsAny())); + //Act + var basketController = new BasketController( + _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); + var actionResult = await basketController.Get(fakeCustomerId) as OkObjectResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId); + } + + [Fact] + public async Task Post_customer_basket_success() + { + //Arrange + var fakeCustomerId = "1"; + var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); + + _basketRepositoryMock.Setup(x => x.UpdateBasketAsync(It.IsAny())) + .Returns(Task.FromResult(fakeCustomerBasket)); + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + _serviceBusMock.Setup(x => x.Publish(It.IsAny())); + //Act + var basketController = new BasketController( + _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); + + var actionResult = await basketController.Post(fakeCustomerBasket) as OkObjectResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId); + } + + [Fact] + public async Task Doing_Checkout_Without_Basket_Should_Return_Bad_Request() + { + var fakeCustomerId = "2"; + _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) + .Returns(Task.FromResult((CustomerBasket)null)); + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + //Act + var basketController = new BasketController( + _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); + + var result = await basketController.Checkout(new BasketCheckout(), Guid.NewGuid().ToString()) as BadRequestResult; + Assert.NotNull(result); + } + + [Fact] + public async Task Doing_Checkout_Wit_Basket_Should_Publish_UserCheckoutAccepted_Integration_Event() + { + var fakeCustomerId = "1"; + var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); + _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) + .Returns(Task.FromResult(fakeCustomerBasket)); + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + //Act + var basketController = new BasketController( + _basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); + + var result = await basketController.Checkout(new BasketCheckout(), Guid.NewGuid().ToString()) as AcceptedResult; + _serviceBusMock.Verify(mock => mock.Publish(It.IsAny()), Times.Once); + Assert.NotNull(result); + } + + private CustomerBasket GetCustomerBasketFake(string fakeCustomerId) + { + return new CustomerBasket(fakeCustomerId) + { + Items = new List() + { + new BasketItem() + } + }; + } + } +} diff --git a/test/Basket.UnitTests/Application/CartControllerTest.cs b/test/Basket.UnitTests/Application/CartControllerTest.cs new file mode 100644 index 000000000..bdbf8afd4 --- /dev/null +++ b/test/Basket.UnitTests/Application/CartControllerTest.cs @@ -0,0 +1,130 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.WebMVC.Controllers; +using Microsoft.eShopOnContainers.WebMVC.Services; +using Microsoft.eShopOnContainers.WebMVC.ViewModels; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using BasketModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Basket; + +namespace UnitTest.Basket.Application +{ + public class CartControllerTest + { + private readonly Mock _catalogServiceMock; + private readonly Mock _basketServiceMock; + private readonly Mock> _identityParserMock; + private readonly Mock _contextMock; + + public CartControllerTest() + { + _catalogServiceMock = new Mock(); + _basketServiceMock = new Mock(); + _identityParserMock = new Mock>(); + _contextMock = new Mock(); + } + + [Fact] + public async Task Post_cart_success() + { + //Arrange + var fakeBuyerId = "1"; + var action = string.Empty; + var fakeBasket = GetFakeBasket(fakeBuyerId); + var fakeQuantities = new Dictionary() + { + ["fakeProdA"] = 1, + ["fakeProdB"] = 2 + }; + + _basketServiceMock.Setup(x => x.SetQuantities(It.IsAny(), It.IsAny>())) + .Returns(Task.FromResult(fakeBasket)); + + _basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny())) + .Returns(Task.FromResult(fakeBasket)); + + //Act + var cartController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); + cartController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await cartController.Index(fakeQuantities, action); + + //Assert + var viewResult = Assert.IsType(actionResult); + } + + [Fact] + public async Task Post_cart_checkout_success() + { + //Arrange + var fakeBuyerId = "1"; + var action = "[ Checkout ]"; + var fakeBasket = GetFakeBasket(fakeBuyerId); + var fakeQuantities = new Dictionary() + { + ["fakeProdA"] = 1, + ["fakeProdB"] = 2 + }; + + _basketServiceMock.Setup(x => x.SetQuantities(It.IsAny(), It.IsAny>())) + .Returns(Task.FromResult(fakeBasket)); + + _basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny())) + .Returns(Task.FromResult(fakeBasket)); + + //Act + var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); + orderController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await orderController.Index(fakeQuantities, action); + + //Assert + var redirectToActionResult = Assert.IsType(actionResult); + Assert.Equal("Order", redirectToActionResult.ControllerName); + Assert.Equal("Create", redirectToActionResult.ActionName); + } + + [Fact] + public async Task Add_to_cart_success() + { + //Arrange + var fakeCatalogItem = GetFakeCatalogItem(); + + _basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(1)); + + //Act + var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); + orderController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await orderController.AddToCart(fakeCatalogItem); + + //Assert + var redirectToActionResult = Assert.IsType(actionResult); + Assert.Equal("Catalog", redirectToActionResult.ControllerName); + Assert.Equal("Index", redirectToActionResult.ActionName); + } + + private BasketModel GetFakeBasket(string buyerId) + { + return new BasketModel() + { + BuyerId = buyerId + }; + } + + private CatalogItem GetFakeCatalogItem() + { + return new CatalogItem() + { + Id = 1, + Name = "fakeName", + CatalogBrand = "fakeBrand", + CatalogType = "fakeType", + CatalogBrandId = 2, + CatalogTypeId = 5, + Price = 20 + }; + } + } +} diff --git a/test/Basket.UnitTests/Basket.UnitTests.csproj b/test/Basket.UnitTests/Basket.UnitTests.csproj new file mode 100644 index 000000000..fece4b3e5 --- /dev/null +++ b/test/Basket.UnitTests/Basket.UnitTests.csproj @@ -0,0 +1,23 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + + + + diff --git a/test/Catalog.UnitTests/Application/CatalogControllerTest.cs b/test/Catalog.UnitTests/Application/CatalogControllerTest.cs new file mode 100644 index 000000000..7410551e4 --- /dev/null +++ b/test/Catalog.UnitTests/Application/CatalogControllerTest.cs @@ -0,0 +1,90 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.WebMVC.Controllers; +using Microsoft.eShopOnContainers.WebMVC.Services; +using Microsoft.eShopOnContainers.WebMVC.ViewModels; +using Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels; +using Moq; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using CatalogModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Catalog; + +namespace UnitTest.Catalog.Application +{ + public class CatalogControllerTest + { + private readonly Mock _catalogServiceMock; + + public CatalogControllerTest() + { + _catalogServiceMock = new Mock(); + } + + [Fact] + public async Task Get_catalog_items_success() + { + //Arrange + var fakeBrandFilterApplied = 1; + var fakeTypesFilterApplied = 2; + var fakePage = 2; + var fakeCatalog = GetFakeCatalog(); + + var expectedNumberOfPages = 5; + var expectedTotalPages = 50; + var expectedCurrentPage = 2; + + _catalogServiceMock.Setup(x => x.GetCatalogItems + ( + It.Is(y => y == fakePage), + It.IsAny(), + It.Is(y => y == fakeBrandFilterApplied), + It.Is(y => y == fakeTypesFilterApplied) + )) + .Returns(Task.FromResult(fakeCatalog)); + + //Act + var orderController = new CatalogController(_catalogServiceMock.Object); + var actionResult = await orderController.Index(fakeBrandFilterApplied, fakeTypesFilterApplied, fakePage, null); + + //Assert + var viewResult = Assert.IsType(actionResult); + var model = Assert.IsAssignableFrom(viewResult.ViewData.Model); + Assert.Equal(model.PaginationInfo.TotalPages, expectedNumberOfPages); + Assert.Equal(model.PaginationInfo.TotalItems, expectedTotalPages); + Assert.Equal(model.PaginationInfo.ActualPage, expectedCurrentPage); + Assert.Empty(model.PaginationInfo.Next); + Assert.Empty(model.PaginationInfo.Previous); + } + + private CatalogModel GetFakeCatalog() + { + return new CatalogModel() + { + PageSize = 10, + Count = 50, + PageIndex = 2, + Data = new List() + { + new CatalogItem() + { + Id = 1, + Name = "fakeItemA", + CatalogTypeId = 1 + }, + new CatalogItem() + { + Id = 2, + Name = "fakeItemB", + CatalogTypeId = 1 + }, + new CatalogItem() + { + Id = 3, + Name = "fakeItemC", + CatalogTypeId = 1 + } + } + }; + } + } +} diff --git a/test/Catalog.UnitTests/Catalog.UnitTests.csproj b/test/Catalog.UnitTests/Catalog.UnitTests.csproj new file mode 100644 index 000000000..8611666f2 --- /dev/null +++ b/test/Catalog.UnitTests/Catalog.UnitTests.csproj @@ -0,0 +1,22 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + + + diff --git a/test/Marketing.FunctionalTests/Base/AutoAuthorizeMiddleware.cs b/test/Marketing.FunctionalTests/Base/AutoAuthorizeMiddleware.cs new file mode 100644 index 000000000..cd605e104 --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/AutoAuthorizeMiddleware.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Http; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Marketing.FunctionalTests.Base +{ + class AutoAuthorizeMiddleware + { + private readonly RequestDelegate _next; + + public AutoAuthorizeMiddleware(RequestDelegate rd) + { + _next = rd; + } + + public async Task Invoke(HttpContext httpContext) + { + var identity = new ClaimsIdentity("cookies"); + + identity.AddClaim(new Claim("sub", "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00")); + httpContext.User.AddIdentity(identity); + + await _next.Invoke(httpContext); + } + } +} diff --git a/test/Marketing.FunctionalTests/Base/CampaignScenarioBase.cs b/test/Marketing.FunctionalTests/Base/CampaignScenarioBase.cs new file mode 100644 index 000000000..6c511d8b7 --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/CampaignScenarioBase.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Marketing.FunctionalTests.Base +{ + public class CampaignScenariosBase : MarketingScenariosBase + { + public static class Get + { + public static string Campaigns = CampaignsUrlBase; + + public static string CampaignBy(int id) + => $"{CampaignsUrlBase}/{id}"; + + public static string UserCampaignsByUserId() + => $"{CampaignsUrlBase}/user"; + } + + public static class Post + { + public static string AddNewCampaign = CampaignsUrlBase; + } + + public static class Put + { + public static string CampaignBy(int id) + => $"{CampaignsUrlBase}/{id}"; + } + + public static class Delete + { + public static string CampaignBy(int id) + => $"{CampaignsUrlBase}/{id}"; + } + } +} diff --git a/test/Marketing.FunctionalTests/Base/CampaignsScenarioBase.cs b/test/Marketing.FunctionalTests/Base/CampaignsScenarioBase.cs new file mode 100644 index 000000000..6c511d8b7 --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/CampaignsScenarioBase.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Marketing.FunctionalTests.Base +{ + public class CampaignScenariosBase : MarketingScenariosBase + { + public static class Get + { + public static string Campaigns = CampaignsUrlBase; + + public static string CampaignBy(int id) + => $"{CampaignsUrlBase}/{id}"; + + public static string UserCampaignsByUserId() + => $"{CampaignsUrlBase}/user"; + } + + public static class Post + { + public static string AddNewCampaign = CampaignsUrlBase; + } + + public static class Put + { + public static string CampaignBy(int id) + => $"{CampaignsUrlBase}/{id}"; + } + + public static class Delete + { + public static string CampaignBy(int id) + => $"{CampaignsUrlBase}/{id}"; + } + } +} diff --git a/test/Marketing.FunctionalTests/Base/LocationsScenarioBase.cs b/test/Marketing.FunctionalTests/Base/LocationsScenarioBase.cs new file mode 100644 index 000000000..0adbb694f --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/LocationsScenarioBase.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using System; +using System.IO; + +namespace Marketing.FunctionalTests.Base +{ + public class LocationsScenariosBase + { + public TestServer CreateServer() + { + var webHostBuilder = WebHost.CreateDefaultBuilder(); + webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Location"); + webHostBuilder.UseStartup(); + + return new TestServer(webHostBuilder); + } + + public static class Get + { + public static string Locations = "api/v1/locations"; + + public static string LocationBy(string id) + { + return $"api/v1/locations/{id}"; + } + + public static string UserLocationBy(Guid id) + { + return $"api/v1/locations/user/{id}"; + } + } + + public static class Post + { + public static string AddNewLocation = "api/v1/locations/"; + } + } +} diff --git a/test/Marketing.FunctionalTests/Base/LocationsTestStartup.cs b/test/Marketing.FunctionalTests/Base/LocationsTestStartup.cs new file mode 100644 index 000000000..56b395ca7 --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/LocationsTestStartup.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.eShopOnContainers.Services.Marketing.API; +using Microsoft.Extensions.Configuration; + +namespace Marketing.FunctionalTests.Base +{ + public class LocationsTestsStartup : Startup + { + public LocationsTestsStartup(IConfiguration configuration) : base(configuration) + { + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) + { + app.UseMiddleware(); + } + else + { + base.ConfigureAuth(app); + } + } + + //class LocationAuthorizeMiddleware + //{ + // private readonly RequestDelegate _next; + + // public LocationAuthorizeMiddleware(RequestDelegate rd) + // { + // _next = rd; + // } + + // public async Task Invoke(HttpContext httpContext) + // { + // var identity = new ClaimsIdentity("cookies"); + // identity.AddClaim(new Claim("sub", "4611ce3f-380d-4db5-8d76-87a8689058ed")); + // httpContext.User.AddIdentity(identity); + + // await _next.Invoke(httpContext); + // } + //} + } +} diff --git a/test/Marketing.FunctionalTests/Base/MarketingScenarioBase.cs b/test/Marketing.FunctionalTests/Base/MarketingScenarioBase.cs new file mode 100644 index 000000000..470019693 --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/MarketingScenarioBase.cs @@ -0,0 +1,36 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System.IO; + +namespace Marketing.FunctionalTests.Base +{ + public class MarketingScenariosBase + { + public static string CampaignsUrlBase => "api/v1/campaigns"; + + public TestServer CreateServer() + { + var webHostBuilder = WebHost.CreateDefaultBuilder(); + webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Marketing"); + webHostBuilder.UseStartup(); + + var testServer = new TestServer(webHostBuilder); + + testServer.Host + .MigrateDbContext((context, services) => + { + var logger = services.GetService>(); + + new MarketingContextSeed() + .SeedAsync(context, logger) + .Wait(); + }); + + return testServer; + } + } +} diff --git a/test/Marketing.FunctionalTests/Base/MarketingTestStartup.cs b/test/Marketing.FunctionalTests/Base/MarketingTestStartup.cs new file mode 100644 index 000000000..4e1ee4493 --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/MarketingTestStartup.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.eShopOnContainers.Services.Marketing.API; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Marketing.FunctionalTests.Base +{ + public class MarketingTestsStartup : Startup + { + public MarketingTestsStartup(IConfiguration configuration) : base(configuration) + { + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) + { + app.UseMiddleware(); + } + else + { + base.ConfigureAuth(app); + } + } + } +} diff --git a/test/Marketing.FunctionalTests/Base/UserLocationRoleScenarioBase.cs b/test/Marketing.FunctionalTests/Base/UserLocationRoleScenarioBase.cs new file mode 100644 index 000000000..897c93e12 --- /dev/null +++ b/test/Marketing.FunctionalTests/Base/UserLocationRoleScenarioBase.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Marketing.FunctionalTests.Base +{ + public class UserLocationRoleScenariosBase : MarketingScenariosBase + { + private const string EndpointLocationName = "locations"; + + public static class Get + { + public static string UserLocationRulesByCampaignId(int campaignId) + => GetUserLocationRolesUrlBase(campaignId); + + public static string UserLocationRuleByCampaignAndUserLocationRuleId(int campaignId, + int userLocationRuleId) + => $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}"; + } + + public static class Post + { + public static string AddNewuserLocationRule(int campaignId) + => GetUserLocationRolesUrlBase(campaignId); + } + + public static class Put + { + public static string UserLocationRoleBy(int campaignId, + int userLocationRuleId) + => $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}"; + } + + public static class Delete + { + public static string UserLocationRoleBy(int campaignId, + int userLocationRuleId) + => $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}"; + } + + + private static string GetUserLocationRolesUrlBase(int campaignId) + => $"{CampaignsUrlBase}/{campaignId}/{EndpointLocationName}"; + } +} diff --git a/test/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj b/test/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj new file mode 100644 index 000000000..473dcb453 --- /dev/null +++ b/test/Marketing.FunctionalTests/Marketing.FunctionalTests.csproj @@ -0,0 +1,30 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Marketing.FunctionalTests/MarketingScenario.cs b/test/Marketing.FunctionalTests/MarketingScenario.cs new file mode 100644 index 000000000..253e325cf --- /dev/null +++ b/test/Marketing.FunctionalTests/MarketingScenario.cs @@ -0,0 +1,46 @@ +using Marketing.FunctionalTests.Base; +using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; +using Microsoft.eShopOnContainers.Services.Marketing.API.Dto; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Marketing.FunctionalTests +{ + public class MarketingScenarios : MarketingScenariosBase + { + [Fact] + public async Task Set_new_user_location_and_get_location_campaign_by_user_id() + { + using (var locationsServer = new LocationsScenariosBase().CreateServer()) + using (var marketingServer = new MarketingScenariosBase().CreateServer()) + { + var location = new LocationRequest + { + Longitude = -122.315752, + Latitude = 47.60461 + }; + var content = new StringContent(JsonConvert.SerializeObject(location), + Encoding.UTF8, "application/json"); + + // GIVEN a new location of user is created + await locationsServer.CreateClient() + .PostAsync(LocationsScenariosBase.Post.AddNewLocation, content); + + await Task.Delay(300); + + //Get campaing from Marketing.API + var campaignsResponse = await marketingServer.CreateClient() + .GetAsync(CampaignScenariosBase.Get.Campaigns); + + var responseBody = await campaignsResponse.Content.ReadAsStringAsync(); + var campaigns = JsonConvert.DeserializeObject>(responseBody); + + Assert.True(campaigns.Count > 0); + } + } + } +} diff --git a/test/Marketing.FunctionalTests/appsettings.json b/test/Marketing.FunctionalTests/appsettings.json new file mode 100644 index 000000000..2aa46abe6 --- /dev/null +++ b/test/Marketing.FunctionalTests/appsettings.json @@ -0,0 +1,12 @@ +{ + "ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word", + "MongoConnectionString": "mongodb://localhost:27017", + "MongoDatabase": "MarketingDb", + "IdentityUrl": "http://localhost:5105", + "isTest": "true", + "EventBusConnection": "localhost", + "AzureServiceBusEnabled": false, + "SubscriptionClientName": "Marketing", + "PicBaseUrl": "http://localhost:5110/api/v1/campaigns/[0]/pic/", + "SubscriptionClientName": "Marketing" +} diff --git a/test/Ordering.FunctionalTests/Base/AutoAuthorizedMiddleware.cs b/test/Ordering.FunctionalTests/Base/AutoAuthorizedMiddleware.cs new file mode 100644 index 000000000..8a104a5a2 --- /dev/null +++ b/test/Ordering.FunctionalTests/Base/AutoAuthorizedMiddleware.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Http; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Ordering.FunctionalTests.Base +{ + class AutoAuthorizeMiddleware + { + private readonly RequestDelegate _next; + + public AutoAuthorizeMiddleware(RequestDelegate rd) + { + _next = rd; + } + + public async Task Invoke(HttpContext httpContext) + { + var identity = new ClaimsIdentity("cookies"); + + identity.AddClaim(new Claim("sub", "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00")); + httpContext.User.AddIdentity(identity); + + await _next.Invoke(httpContext); + } + } +} diff --git a/test/Ordering.FunctionalTests/Base/BasketScenarioBase.cs b/test/Ordering.FunctionalTests/Base/BasketScenarioBase.cs new file mode 100644 index 000000000..602d401eb --- /dev/null +++ b/test/Ordering.FunctionalTests/Base/BasketScenarioBase.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using System.IO; + +namespace Ordering.FunctionalTests.Base +{ + class BasketScenariosBase + { + private const string ApiUrlBase = "api/v1/basket"; + + public TestServer CreateServer() + { + var webHostBuilder = WebHost.CreateDefaultBuilder(); + webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Basket"); + webHostBuilder.UseStartup(); + + return new TestServer(webHostBuilder); + } + + public static class Get + { + public static string GetBasketByCustomer(string customerId) + { + return $"{ApiUrlBase}/{customerId}"; + } + } + + public static class Post + { + public static string CreateBasket = $"{ApiUrlBase}/"; + public static string Checkout = $"{ApiUrlBase}/checkout"; + } + } +} diff --git a/test/Ordering.FunctionalTests/Base/BasketTestStartup.cs b/test/Ordering.FunctionalTests/Base/BasketTestStartup.cs new file mode 100644 index 000000000..a6221b5e8 --- /dev/null +++ b/test/Ordering.FunctionalTests/Base/BasketTestStartup.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.eShopOnContainers.Services.Basket.API; +using Microsoft.Extensions.Configuration; + +namespace Ordering.FunctionalTests.Base +{ + class BasketTestsStartup : Startup + { + public BasketTestsStartup(IConfiguration configuration) : base(configuration) + { + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) + { + app.UseMiddleware(); + } + else + { + base.ConfigureAuth(app); + } + } + } +} diff --git a/test/Ordering.FunctionalTests/Base/HttpClientExtensions.cs b/test/Ordering.FunctionalTests/Base/HttpClientExtensions.cs new file mode 100644 index 000000000..e5735ccb9 --- /dev/null +++ b/test/Ordering.FunctionalTests/Base/HttpClientExtensions.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.TestHost; +using System; +using System.Net.Http; + +namespace Ordering.FunctionalTests.Base +{ + static class HttpClientExtensions + { + public static HttpClient CreateIdempotentClient(this TestServer server) + { + var client = server.CreateClient(); + + client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); + + return client; + } + } +} diff --git a/test/Ordering.FunctionalTests/Base/OrderingScenarioBase.cs b/test/Ordering.FunctionalTests/Base/OrderingScenarioBase.cs new file mode 100644 index 000000000..4f49f27c3 --- /dev/null +++ b/test/Ordering.FunctionalTests/Base/OrderingScenarioBase.cs @@ -0,0 +1,75 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +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; + +namespace Ordering.FunctionalTests.Base +{ + public class OrderingScenariosBase + { + public TestServer CreateServer() + { + var webHostBuilder = WebHost.CreateDefaultBuilder(); + webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Ordering"); + webHostBuilder.UseStartup(); + webHostBuilder.ConfigureAppConfiguration((builderContext, config) => + { + config.AddJsonFile("settings.json"); + }); + + var testServer = new TestServer(webHostBuilder); + + testServer.Host + .MigrateDbContext((context, services) => + { + var env = services.GetService(); + var settings = services.GetService>(); + var logger = services.GetService>(); + + new OrderingContextSeed() + .SeedAsync(context, env, settings, logger) + .Wait(); + }) + .MigrateDbContext((_, __) => { }); + + 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 string ShipOrder = "api/v1/orders/ship"; + } + + public static class Delete + { + public static string OrderBy(int id) + { + return $"api/v1/orders/{id}"; + } + } + } +} diff --git a/test/Ordering.FunctionalTests/Base/OrderingTestStartup.cs b/test/Ordering.FunctionalTests/Base/OrderingTestStartup.cs new file mode 100644 index 000000000..5837c9bb0 --- /dev/null +++ b/test/Ordering.FunctionalTests/Base/OrderingTestStartup.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.eShopOnContainers.Services.Ordering.API; +using Microsoft.Extensions.Configuration; + +namespace Ordering.FunctionalTests.Base +{ + public class OrderingTestsStartup : Startup + { + public OrderingTestsStartup(IConfiguration env) : base(env) + { + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) + { + app.UseMiddleware(); + } + else + { + base.ConfigureAuth(app); + } + } + } +} diff --git a/test/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj b/test/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj new file mode 100644 index 000000000..2ba050b22 --- /dev/null +++ b/test/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj @@ -0,0 +1,29 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/test/Ordering.FunctionalTests/OrderingScenario.cs b/test/Ordering.FunctionalTests/OrderingScenario.cs new file mode 100644 index 000000000..0446dca5a --- /dev/null +++ b/test/Ordering.FunctionalTests/OrderingScenario.cs @@ -0,0 +1,185 @@ +using Microsoft.eShopOnContainers.Services.Basket.API.Model; +//using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; +using Microsoft.eShopOnContainers.WebMVC.ViewModels; +using Newtonsoft.Json; +using Ordering.FunctionalTests.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using WebMVC.Models; +using Xunit; + +namespace Ordering.FunctionalTests +{ + public class OrderingScenarios : OrderingScenariosBase + { + [Fact] + public async Task Cancel_basket_and_check_order_status_cancelled() + { + using (var orderServer = new OrderingScenariosBase().CreateServer()) + using (var basketServer = new BasketScenariosBase().CreateServer()) + { + // Expected data + var cityExpected = $"city-{Guid.NewGuid()}"; + var orderStatusExpected = "cancelled"; + + var basketClient = basketServer.CreateIdempotentClient(); + var orderClient = orderServer.CreateIdempotentClient(); + + // GIVEN a basket is created + var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket); + + // AND basket checkout is sent + await basketClient.PostAsync(BasketScenariosBase.Post.Checkout, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json")); + + // WHEN Order is created in Ordering.api + var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient); + + // AND Order is cancelled in Ordering.api + await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json")); + + // AND the requested order is retrieved + var order = await TryGetNewOrderCreated(cityExpected, orderClient); + + // THEN check status + Assert.Equal(orderStatusExpected, order.Status); + } + } + + [Fact] + public async Task Get_get_all_stored_orders_and_response_ok_status_code() + { + using (var server = CreateServer()) + { + var response = await server.CreateClient() + .GetAsync(Get.Orders); + + response.EnsureSuccessStatusCode(); + } + } + + [Fact] + public async Task Cancel_order_no_order_created_bad_request_response() + { + using (var server = CreateServer()) + { + var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateIdempotentClient() + .PutAsync(Put.CancelOrder, content); + + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + } + + [Fact] + public async Task Ship_order_no_order_created_bad_request_response() + { + using (var server = CreateServer()) + { + var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateIdempotentClient() + .PutAsync(Put.ShipOrder, content); + + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + } + + string BuildOrder() + { + var order = new OrderDTO() + { + OrderNumber = "-1" + }; + return JsonConvert.SerializeObject(order); + } + + private async Task 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 orders = JsonConvert.DeserializeObject>(ordersGetResponse); + + 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 = JsonConvert.DeserializeObject(orderDetails); + + if (IsOrderCreated(order, city)) + { + break; + } + } + + 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() + { + new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem() + { + Id = "1", + ProductName = "ProductName", + ProductId = "1", + UnitPrice = 10, + Quantity = 1 + } + }; + return JsonConvert.SerializeObject(order); + } + + string BuildCancelOrder(string orderId) + { + var order = new OrderDTO() + { + OrderNumber = orderId + }; + return JsonConvert.SerializeObject(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 JsonConvert.SerializeObject(checkoutBasket); + } + } +} diff --git a/test/Ordering.FunctionalTests/settings.json b/test/Ordering.FunctionalTests/settings.json new file mode 100644 index 000000000..70f1af3c0 --- /dev/null +++ b/test/Ordering.FunctionalTests/settings.json @@ -0,0 +1,10 @@ +{ + "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;", + "ExternalCatalogBaseUrl": "http://localhost:5101", + "IdentityUrl": "http://localhost:5105", + "isTest": "true", + "EventBusConnection": "localhost", + "CheckUpdateTime": "30000", + "GracePeriodTime": "1", + "SubscriptionClientName": "Ordering" +} diff --git a/test/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs b/test/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs new file mode 100644 index 000000000..e0f861017 --- /dev/null +++ b/test/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace UnitTest.Ordering.Application +{ + using global::Ordering.API.Application.Models; + using MediatR; + using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; + using Moq; + using System.Collections; + using System.Collections.Generic; + using System.Threading.Tasks; + using Xunit; + public class IdentifiedCommandHandlerTest + { + private readonly Mock _requestManager; + private readonly Mock _mediator; + + public IdentifiedCommandHandlerTest() + { + _requestManager = new Mock(); + _mediator = new Mock(); + } + + [Fact] + public async Task Handler_sends_command_when_order_no_exists() + { + // Arrange + var fakeGuid = Guid.NewGuid(); + var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); + + _requestManager.Setup(x => x.ExistAsync(It.IsAny())) + .Returns(Task.FromResult(false)); + + _mediator.Setup(x => x.Send(It.IsAny>(),default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object); + var cltToken = new System.Threading.CancellationToken(); + var result = await handler.Handle(fakeOrderCmd, cltToken); + + //Assert + Assert.True(result); + _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Once()); + } + + [Fact] + public async Task Handler_sends_no_command_when_order_already_exists() + { + // Arrange + var fakeGuid = Guid.NewGuid(); + var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); + + _requestManager.Setup(x => x.ExistAsync(It.IsAny())) + .Returns(Task.FromResult(true)); + + _mediator.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object); + var cltToken = new System.Threading.CancellationToken(); + var result = await handler.Handle(fakeOrderCmd, cltToken); + + //Assert + Assert.False(result); + _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Never()); + } + + private CreateOrderCommand FakeOrderRequest(Dictionary args = null) + { + return new CreateOrderCommand( + new List(), + userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, + userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, + city: args != null && args.ContainsKey("city") ? (string)args["city"] : null, + street: args != null && args.ContainsKey("street") ? (string)args["street"] : null, + state: args != null && args.ContainsKey("state") ? (string)args["state"] : null, + country: args != null && args.ContainsKey("country") ? (string)args["country"] : null, + zipcode: args != null && args.ContainsKey("zipcode") ? (string)args["zipcode"] : null, + cardNumber: args != null && args.ContainsKey("cardNumber") ? (string)args["cardNumber"] : "1234", + cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue, + cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123", + cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX", + cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0); + } + } +} diff --git a/test/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs b/test/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs new file mode 100644 index 000000000..7fe02017b --- /dev/null +++ b/test/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs @@ -0,0 +1,94 @@ +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Moq; +using System; +using System.Threading; +using System.Threading.Tasks; + + +namespace UnitTest.Ordering.Application +{ + using global::Ordering.API.Application.Models; + using MediatR; + using System.Collections; + using System.Collections.Generic; + using Xunit; + using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; + + public class NewOrderRequestHandlerTest + { + private readonly Mock _orderRepositoryMock; + private readonly Mock _identityServiceMock; + private readonly Mock _mediator; + + public NewOrderRequestHandlerTest() + { + + _orderRepositoryMock = new Mock(); + _identityServiceMock = new Mock(); + _mediator = new Mock(); + } + + [Fact] + public async Task Handle_return_false_if_order_is_not_persisted() + { + var buyerId = "1234"; + + var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary + { ["cardExpiration"] = DateTime.Now.AddYears(1) }); + + _orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny())) + .Returns(Task.FromResult(FakeOrder())); + + _orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken))) + .Returns(Task.FromResult(1)); + + _identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId); + + //Act + var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.Object); + var cltToken = new System.Threading.CancellationToken(); + var result = await handler.Handle(fakeOrderCmd, cltToken); + + //Assert + Assert.False(result); + } + + [Fact] + public void Handle_throws_exception_when_no_buyerId() + { + //Assert + Assert.Throws(() => new Buyer(string.Empty, string.Empty)); + } + + private Buyer FakeBuyer() + { + return new Buyer(Guid.NewGuid().ToString(), "1"); + } + + private Order FakeOrder() + { + return new Order("1", "fakeName", new Address("street", "city", "state", "country", "zipcode"), 1, "12", "111", "fakeName", DateTime.Now.AddYears(1)); + } + + private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary args = null) + { + return new CreateOrderCommand( + new List(), + userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, + userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, + city: args != null && args.ContainsKey("city") ? (string)args["city"] : null, + street: args != null && args.ContainsKey("street") ? (string)args["street"] : null, + state: args != null && args.ContainsKey("state") ? (string)args["state"] : null, + country: args != null && args.ContainsKey("country") ? (string)args["country"] : null, + zipcode: args != null && args.ContainsKey("zipcode") ? (string)args["zipcode"] : null, + cardNumber: args != null && args.ContainsKey("cardNumber") ? (string)args["cardNumber"] : "1234", + cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue, + cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123", + cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX", + cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0); + } + } +} diff --git a/test/Ordering.UnitTests/Application/OrderControllerTest.cs b/test/Ordering.UnitTests/Application/OrderControllerTest.cs new file mode 100644 index 000000000..a60ce3bb3 --- /dev/null +++ b/test/Ordering.UnitTests/Application/OrderControllerTest.cs @@ -0,0 +1,86 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.WebMVC.Controllers; +using Microsoft.eShopOnContainers.WebMVC.Services; +using Microsoft.eShopOnContainers.WebMVC.ViewModels; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using BasketModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Basket; + +namespace UnitTest.Ordering.Application +{ + public class OrderControllerTest + { + private readonly Mock _orderServiceMock; + private readonly Mock _basketServiceMock; + private readonly Mock> _identityParserMock; + private readonly Mock _contextMock; + + public OrderControllerTest() + { + _orderServiceMock = new Mock(); + _basketServiceMock = new Mock(); + _identityParserMock = new Mock>(); + _contextMock = new Mock(); + } + + [Fact] + public async Task Get_order_list_success() + { + //Arrange + var expectedTotalResults = 1; + var fakeOrder = GetFakeOrder(); + + _orderServiceMock.Setup(x => x.GetMyOrders(It.IsAny())) + .Returns(Task.FromResult(new List() { fakeOrder })); + + //Act + var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object); + orderController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await orderController.Index(fakeOrder); + + //Assert + var viewResult = Assert.IsType(actionResult); + var model = Assert.IsAssignableFrom>(viewResult.ViewData.Model); + Assert.Equal(model.Count, expectedTotalResults); + } + + [Fact] + public async Task Get_order_detail_success() + { + //Arrange + var fakeOrderId = "12"; + var fakeOrder = GetFakeOrder(); + + _orderServiceMock.Setup(x => x.GetOrder(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(fakeOrder)); + + //Act + var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object); + orderController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await orderController.Detail(fakeOrderId); + + //Assert + var viewResult = Assert.IsType(actionResult); + Assert.IsAssignableFrom(viewResult.ViewData.Model); + } + + + + private Order GetFakeOrder() + { + return new Order() + { + OrderNumber = "1", + CardNumber = "12", + CardSecurityNumber = "1212", + Status = "Pending", + RequestId = Guid.NewGuid(), + CardExpiration = DateTime.Now.AddYears(1), + }; + } + } +} diff --git a/test/Ordering.UnitTests/Application/OrdersWebApiTest.cs b/test/Ordering.UnitTests/Application/OrdersWebApiTest.cs new file mode 100644 index 000000000..516f9ba54 --- /dev/null +++ b/test/Ordering.UnitTests/Application/OrdersWebApiTest.cs @@ -0,0 +1,141 @@ +using MediatR; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; +using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; +using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; +using Moq; +using Ordering.API.Application.Commands; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace UnitTest.Ordering.Application +{ + public class OrdersWebApiTest + { + private readonly Mock _mediatorMock; + private readonly Mock _orderQueriesMock; + private readonly Mock _identityServiceMock; + + public OrdersWebApiTest() + { + _mediatorMock = new Mock(); + _orderQueriesMock = new Mock(); + _identityServiceMock = new Mock(); + } + + [Fact] + public async Task Create_order_with_requestId_success() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); + var actionResult = await orderController.CancelOrder(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + + } + + [Fact] + public async Task Cancel_order_bad_request() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); + var actionResult = await orderController.CancelOrder(new CancelOrderCommand(1), String.Empty) as BadRequestResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); + } + + [Fact] + public async Task Ship_order_with_requestId_success() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); + var actionResult = await orderController.ShipOrder(new ShipOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + + } + + [Fact] + public async Task Ship_order_bad_request() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); + var actionResult = await orderController.ShipOrder(new ShipOrderCommand(1), String.Empty) as BadRequestResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); + } + + [Fact] + public async Task Get_orders_success() + { + //Arrange + var fakeDynamicResult = Enumerable.Empty(); + _orderQueriesMock.Setup(x => x.GetOrdersFromUserAsync(Guid.NewGuid())) + .Returns(Task.FromResult(fakeDynamicResult)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); + var actionResult = await orderController.GetOrders() as OkObjectResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + } + + [Fact] + public async Task Get_order_success() + { + //Arrange + var fakeOrderId = 123; + var fakeDynamicResult = new Order(); + _orderQueriesMock.Setup(x => x.GetOrderAsync(It.IsAny())) + .Returns(Task.FromResult(fakeDynamicResult)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); + var actionResult = await orderController.GetOrder(fakeOrderId) as OkObjectResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + } + + [Fact] + public async Task Get_cardTypes_success() + { + //Arrange + var fakeDynamicResult = Enumerable.Empty(); + _orderQueriesMock.Setup(x => x.GetCardTypesAsync()) + .Returns(Task.FromResult(fakeDynamicResult)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); + var actionResult = await orderController.GetCardTypes() as OkObjectResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + } + } +} diff --git a/test/Ordering.UnitTests/Builders.cs b/test/Ordering.UnitTests/Builders.cs new file mode 100644 index 000000000..3103aee19 --- /dev/null +++ b/test/Ordering.UnitTests/Builders.cs @@ -0,0 +1,48 @@ +using System; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + +namespace UnitTest.Ordering +{ + public class AddressBuilder + { + public Address Build() + { + return new Address("street", "city", "state", "country", "zipcode"); + } + } + + public class OrderBuilder + { + private readonly Order order; + + public OrderBuilder(Address address) + { + order = new Order( + "userId", + "fakeName", + address, + cardTypeId:5, + cardNumber:"12", + cardSecurityNumber:"123", + cardHolderName:"name", + cardExpiration:DateTime.UtcNow); + } + + public OrderBuilder AddOne( + int productId, + string productName, + decimal unitPrice, + decimal discount, + string pictureUrl, + int units = 1) + { + order.AddOrderItem(productId, productName, unitPrice, discount, pictureUrl, units); + return this; + } + + public Order Build() + { + return order; + } + } +} diff --git a/test/Ordering.UnitTests/Domain/BuyerAggregateTest.cs b/test/Ordering.UnitTests/Domain/BuyerAggregateTest.cs new file mode 100644 index 000000000..588b929fd --- /dev/null +++ b/test/Ordering.UnitTests/Domain/BuyerAggregateTest.cs @@ -0,0 +1,132 @@ +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; +using Ordering.Domain.Exceptions; +using System; +using Xunit; + +public class BuyerAggregateTest +{ + public BuyerAggregateTest() + { } + + [Fact] + public void Create_buyer_item_success() + { + //Arrange + var identity = new Guid().ToString(); + var name = "fakeUser"; + + //Act + var fakeBuyerItem = new Buyer(identity, name); + + //Assert + Assert.NotNull(fakeBuyerItem); + } + + [Fact] + public void Create_buyer_item_fail() + { + //Arrange + var identity = string.Empty; + var name = "fakeUser"; + + //Act - Assert + Assert.Throws(() => new Buyer(identity, name)); + } + + [Fact] + public void add_payment_success() + { + //Arrange + var cardTypeId = 1; + var alias = "fakeAlias"; + var cardNumber = "124"; + var securityNumber = "1234"; + var cardHolderName = "FakeHolderNAme"; + var expiration = DateTime.Now.AddYears(1); + var orderId = 1; + var name = "fakeUser"; + var identity = new Guid().ToString(); + var fakeBuyerItem = new Buyer(identity, name); + + //Act + var result = fakeBuyerItem.VerifyOrAddPaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration, orderId); + + //Assert + Assert.NotNull(result); + } + + [Fact] + public void create_payment_method_success() + { + //Arrange + var cardTypeId = 1; + var alias = "fakeAlias"; + var cardNumber = "124"; + var securityNumber = "1234"; + var cardHolderName = "FakeHolderNAme"; + var expiration = DateTime.Now.AddYears(1); + var fakePaymentMethod = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); + + //Act + var result = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); + + //Assert + Assert.NotNull(result); + } + + [Fact] + public void create_payment_method_expiration_fail() + { + //Arrange + var cardTypeId = 1; + var alias = "fakeAlias"; + var cardNumber = "124"; + var securityNumber = "1234"; + var cardHolderName = "FakeHolderNAme"; + var expiration = DateTime.Now.AddYears(-1); + + //Act - Assert + Assert.Throws(() => new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration)); + } + + [Fact] + public void payment_method_isEqualTo() + { + //Arrange + var cardTypeId = 1; + var alias = "fakeAlias"; + var cardNumber = "124"; + var securityNumber = "1234"; + var cardHolderName = "FakeHolderNAme"; + var expiration = DateTime.Now.AddYears(1); + + //Act + var fakePaymentMethod = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); + var result = fakePaymentMethod.IsEqualTo(cardTypeId, cardNumber, expiration); + + //Assert + Assert.True(result); + } + + [Fact] + public void Add_new_PaymentMethod_raises_new_event() + { + //Arrange + var alias = "fakeAlias"; + var orderId = 1; + var cardTypeId = 5; + var cardNumber = "12"; + var cardSecurityNumber = "123"; + var cardHolderName = "FakeName"; + var cardExpiration = DateTime.Now.AddYears(1); + var expectedResult = 1; + var name = "fakeUser"; + + //Act + var fakeBuyer = new Buyer(Guid.NewGuid().ToString(), name); + fakeBuyer.VerifyOrAddPaymentMethod(cardTypeId, alias, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration, orderId); + + //Assert + Assert.Equal(fakeBuyer.DomainEvents.Count, expectedResult); + } +} \ No newline at end of file diff --git a/test/Ordering.UnitTests/Domain/OrderAggregateTest.cs b/test/Ordering.UnitTests/Domain/OrderAggregateTest.cs new file mode 100644 index 000000000..bf0678f5f --- /dev/null +++ b/test/Ordering.UnitTests/Domain/OrderAggregateTest.cs @@ -0,0 +1,180 @@ +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Ordering.Domain.Events; +using Ordering.Domain.Exceptions; +using System; +using System.Linq; +using UnitTest.Ordering; +using Xunit; + +public class OrderAggregateTest +{ + public OrderAggregateTest() + { } + + [Fact] + public void Create_order_item_success() + { + //Arrange + var productId = 1; + var productName = "FakeProductName"; + var unitPrice = 12; + var discount = 15; + var pictureUrl = "FakeUrl"; + var units = 5; + + //Act + var fakeOrderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); + + //Assert + Assert.NotNull(fakeOrderItem); + } + + [Fact] + public void Invalid_number_of_units() + { + //Arrange + var productId = 1; + var productName = "FakeProductName"; + var unitPrice = 12; + var discount = 15; + var pictureUrl = "FakeUrl"; + var units = -1; + + //Act - Assert + Assert.Throws(() => new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units)); + } + + [Fact] + public void Invalid_total_of_order_item_lower_than_discount_applied() + { + //Arrange + var productId = 1; + var productName = "FakeProductName"; + var unitPrice = 12; + var discount = 15; + var pictureUrl = "FakeUrl"; + var units = 1; + + //Act - Assert + Assert.Throws(() => new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units)); + } + + [Fact] + public void Invalid_discount_setting() + { + //Arrange + var productId = 1; + var productName = "FakeProductName"; + var unitPrice = 12; + var discount = 15; + var pictureUrl = "FakeUrl"; + var units = 5; + + //Act + var fakeOrderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); + + //Assert + Assert.Throws(() => fakeOrderItem.SetNewDiscount(-1)); + } + + [Fact] + public void Invalid_units_setting() + { + //Arrange + var productId = 1; + var productName = "FakeProductName"; + var unitPrice = 12; + var discount = 15; + var pictureUrl = "FakeUrl"; + var units = 5; + + //Act + var fakeOrderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); + + //Assert + Assert.Throws(() => fakeOrderItem.AddUnits(-1)); + } + + [Fact] + public void when_add_two_times_on_the_same_item_then_the_total_of_order_should_be_the_sum_of_the_two_items() + { + var address = new AddressBuilder().Build(); + var order = new OrderBuilder(address) + .AddOne(1,"cup",10.0m,0,string.Empty) + .AddOne(1,"cup",10.0m,0,string.Empty) + .Build(); + + Assert.Equal(20.0m, order.GetTotal()); + } + + [Fact] + public void Add_new_Order_raises_new_event() + { + //Arrange + var street = "fakeStreet"; + var city = "FakeCity"; + var state = "fakeState"; + var country = "fakeCountry"; + var zipcode = "FakeZipCode"; + var cardTypeId = 5; + var cardNumber = "12"; + var cardSecurityNumber = "123"; + var cardHolderName = "FakeName"; + var cardExpiration = DateTime.Now.AddYears(1); + var expectedResult = 1; + + //Act + var fakeOrder = new Order("1", "fakeName", new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); + + //Assert + Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult); + } + + [Fact] + public void Add_event_Order_explicitly_raises_new_event() + { + //Arrange + var street = "fakeStreet"; + var city = "FakeCity"; + var state = "fakeState"; + var country = "fakeCountry"; + var zipcode = "FakeZipCode"; + var cardTypeId = 5; + var cardNumber = "12"; + var cardSecurityNumber = "123"; + var cardHolderName = "FakeName"; + var cardExpiration = DateTime.Now.AddYears(1); + var expectedResult = 2; + + //Act + var fakeOrder = new Order("1", "fakeName", new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); + fakeOrder.AddDomainEvent(new OrderStartedDomainEvent(fakeOrder, "fakeName", "1", cardTypeId,cardNumber,cardSecurityNumber,cardHolderName,cardExpiration)); + //Assert + Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult); + } + + [Fact] + public void Remove_event_Order_explicitly() + { + //Arrange + var street = "fakeStreet"; + var city = "FakeCity"; + var state = "fakeState"; + var country = "fakeCountry"; + var zipcode = "FakeZipCode"; + var cardTypeId = 5; + var cardNumber = "12"; + var cardSecurityNumber = "123"; + var cardHolderName = "FakeName"; + var cardExpiration = DateTime.Now.AddYears(1); + var fakeOrder = new Order("1", "fakeName", new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); + var @fakeEvent = new OrderStartedDomainEvent(fakeOrder, "1", "fakeName", cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); + var expectedResult = 1; + + //Act + fakeOrder.AddDomainEvent(@fakeEvent); + fakeOrder.RemoveDomainEvent(@fakeEvent); + //Assert + Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult); + } +} \ No newline at end of file diff --git a/test/Ordering.UnitTests/Ordering.UnitTests.csproj b/test/Ordering.UnitTests/Ordering.UnitTests.csproj new file mode 100644 index 000000000..dff99f424 --- /dev/null +++ b/test/Ordering.UnitTests/Ordering.UnitTests.csproj @@ -0,0 +1,25 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + + + + + + From cc034183aa6c3f6153cbbf2a4adec99b91807845 Mon Sep 17 00:00:00 2001 From: Juan Antonio Cano Date: Mon, 25 Jun 2018 13:11:12 +0200 Subject: [PATCH 02/13] Urls for Identity, Gateway Shopping and Marketing added to setting view --- .../eShopOnContainers.Core/GlobalSettings.cs | 65 ++++++++++++++----- .../Services/Basket/BasketService.cs | 10 +-- .../Services/Catalog/CatalogService.cs | 10 +-- .../Services/FixUri/FixUriService.cs | 12 ++-- .../Services/Location/LocationService.cs | 6 +- .../Services/Marketing/CampaignService.cs | 6 +- .../Services/Order/OrderService.cs | 8 +-- .../Services/Settings/ISettingsService.cs | 4 +- .../Services/Settings/SettingsService.cs | 27 ++++++-- .../ViewModels/Base/ViewModelBase.cs | 7 +- .../ViewModels/SettingsViewModel.cs | 64 ++++++++++++++---- .../Views/SettingsView.xaml | 30 ++++++++- .../Mocks/MockSettingsService.cs | 26 ++++++-- 13 files changed, 209 insertions(+), 66 deletions(-) diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs index e1637d7be..41f18c98d 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/GlobalSettings.cs @@ -6,33 +6,54 @@ public const string MockTag = "Mock"; public const string DefaultEndpoint = "http://YOUR_IP_OR_DNS_NAME"; // i.e.: "http://YOUR_IP" or "http://YOUR_DNS_NAME" - private string _baseEndpoint; - private static readonly GlobalSetting _instance = new GlobalSetting(); + private string _baseIdentityEndpoint; + private string _baseGatewayShoppingEndpoint; + private string _baseGatewayMarketingEndpoint; public GlobalSetting() { AuthToken = "INSERT AUTHENTICATION TOKEN"; - BaseEndpoint = DefaultEndpoint; + + BaseIdentityEndpoint = DefaultEndpoint; + BaseGatewayShoppingEndpoint = DefaultEndpoint; + BaseGatewayMarketingEndpoint = DefaultEndpoint; + } + + public static GlobalSetting Instance { get; } = new GlobalSetting(); + + public string BaseIdentityEndpoint + { + get { return _baseIdentityEndpoint; } + set + { + _baseIdentityEndpoint = value; + UpdateEndpoint(_baseIdentityEndpoint); + } } - public static GlobalSetting Instance + public string BaseGatewayShoppingEndpoint { - get { return _instance; } + get { return _baseGatewayShoppingEndpoint; } + set + { + _baseGatewayShoppingEndpoint = value; + UpdateGatewayShoppingEndpoint(_baseGatewayShoppingEndpoint); + } } - public string BaseEndpoint + public string BaseGatewayMarketingEndpoint { - get { return _baseEndpoint; } + get { return _baseGatewayMarketingEndpoint; } set { - _baseEndpoint = value; - UpdateEndpoint(_baseEndpoint); + _baseGatewayMarketingEndpoint = value; + UpdateGatewayMarketingEndpoint(_baseGatewayMarketingEndpoint); } } - public string ClientId { get { return "xamarin"; }} + public string ClientId { get { return "xamarin"; } } - public string ClientSecret { get { return "secret"; }} + public string ClientSecret { get { return "secret"; } } public string AuthToken { get; set; } @@ -50,9 +71,13 @@ public string LogoutCallback { get; set; } - private void UpdateEndpoint(string baseEndpoint) + public string GatewayShoppingEndpoint { get; set; } + + public string GatewayMarketingEndpoint { get; set; } + + private void UpdateEndpoint(string endpoint) { - var identityBaseEndpoint = $"{baseEndpoint}/identity"; + var identityBaseEndpoint = $"{endpoint}/identity"; RegisterWebsite = $"{identityBaseEndpoint}/Account/Register"; LogoutCallback = $"{identityBaseEndpoint}/Account/Redirecting"; @@ -61,8 +86,18 @@ UserInfoEndpoint = $"{connectBaseEndpoint}/userinfo"; TokenEndpoint = $"{connectBaseEndpoint}/token"; LogoutEndpoint = $"{connectBaseEndpoint}/endsession"; - - IdentityCallback = $"{baseEndpoint}/xamarincallback"; + + IdentityCallback = $"{endpoint}/xamarincallback"; + } + + private void UpdateGatewayShoppingEndpoint(string endpoint) + { + GatewayShoppingEndpoint = $"{endpoint}/mobileshoppingapigw"; + } + + private void UpdateGatewayMarketingEndpoint(string endpoint) + { + GatewayMarketingEndpoint = $"{endpoint}/mobilemarketingapigw"; } } } \ No newline at end of file diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs index b36488f24..a53967e56 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Basket/BasketService.cs @@ -11,7 +11,7 @@ namespace eShopOnContainers.Core.Services.Basket private readonly IRequestProvider _requestProvider; private readonly IFixUriService _fixUriService; - private const string ApiUrlBase = "mobileshoppingapigw/api/v1/b/basket"; + private const string ApiUrlBase = "api/v1/b/basket"; public BasketService(IRequestProvider requestProvider, IFixUriService fixUriService) { @@ -21,7 +21,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task GetBasketAsync(string guidUser, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint) { Path = $"{ApiUrlBase}/{guidUser}" }; @@ -45,7 +45,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task UpdateBasketAsync(CustomerBasket customerBasket, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint) { Path = ApiUrlBase }; @@ -57,7 +57,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task CheckoutAsync(BasketCheckout basketCheckout, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint) { Path = $"{ApiUrlBase}/checkout" }; @@ -68,7 +68,7 @@ namespace eShopOnContainers.Core.Services.Basket public async Task ClearBasketAsync(string guidUser, string token) { - var builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint) + var builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint) { Path = $"{ApiUrlBase}/{guidUser}" }; diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs index 2811416ad..c9d3ef708 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Catalog/CatalogService.cs @@ -14,7 +14,7 @@ namespace eShopOnContainers.Core.Services.Catalog private readonly IRequestProvider _requestProvider; private readonly IFixUriService _fixUriService; - private const string ApiUrlBase = "mobileshoppingapigw/api/v1/c/catalog"; + private const string ApiUrlBase = "api/v1/c/catalog"; public CatalogService(IRequestProvider requestProvider, IFixUriService fixUriService) { @@ -24,7 +24,7 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> FilterAsync(int catalogBrandId, int catalogTypeId) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint); builder.Path = $"{ApiUrlBase}/items/type/{catalogTypeId}/brand/{catalogBrandId}"; string uri = builder.ToString(); @@ -38,7 +38,7 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> GetCatalogAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint); builder.Path = $"{ApiUrlBase}/items"; string uri = builder.ToString(); @@ -55,7 +55,7 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> GetCatalogBrandAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint); builder.Path = $"{ApiUrlBase}/catalogbrands"; string uri = builder.ToString(); @@ -69,7 +69,7 @@ namespace eShopOnContainers.Core.Services.Catalog public async Task> GetCatalogTypeAsync() { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint); builder.Path = $"{ApiUrlBase}/catalogtypes"; string uri = builder.ToString(); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/FixUri/FixUriService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/FixUri/FixUriService.cs index 06cfaeae3..c774cec55 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/FixUri/FixUriService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/FixUri/FixUriService.cs @@ -31,12 +31,12 @@ namespace eShopOnContainers.Core.Services.FixUri try { if (!ViewModelLocator.UseMockService - && _settingsService.UrlBase != GlobalSetting.DefaultEndpoint) + && _settingsService.IdentityEndpointBase != GlobalSetting.DefaultEndpoint) { foreach (var catalogItem in catalogItems) { MatchCollection serverResult = IpRegex.Matches(catalogItem.PictureUri); - MatchCollection localResult = IpRegex.Matches(_settingsService.UrlBase); + MatchCollection localResult = IpRegex.Matches(_settingsService.IdentityEndpointBase); if (serverResult.Count != -1 && localResult.Count != -1) { @@ -64,12 +64,12 @@ namespace eShopOnContainers.Core.Services.FixUri try { if (!ViewModelLocator.UseMockService - && _settingsService.UrlBase != GlobalSetting.DefaultEndpoint) + && _settingsService.IdentityEndpointBase != GlobalSetting.DefaultEndpoint) { foreach (var basketItem in basketItems) { MatchCollection serverResult = IpRegex.Matches(basketItem.PictureUrl); - MatchCollection localResult = IpRegex.Matches(_settingsService.UrlBase); + MatchCollection localResult = IpRegex.Matches(_settingsService.IdentityEndpointBase); if (serverResult.Count != -1 && localResult.Count != -1) { @@ -96,12 +96,12 @@ namespace eShopOnContainers.Core.Services.FixUri try { if (!ViewModelLocator.UseMockService - && _settingsService.UrlBase != GlobalSetting.DefaultEndpoint) + && _settingsService.IdentityEndpointBase != GlobalSetting.DefaultEndpoint) { foreach (var campaignItem in campaignItems) { MatchCollection serverResult = IpRegex.Matches(campaignItem.PictureUri); - MatchCollection localResult = IpRegex.Matches(_settingsService.UrlBase); + MatchCollection localResult = IpRegex.Matches(_settingsService.IdentityEndpointBase); if (serverResult.Count != -1 && localResult.Count != -1) { diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs index e18d335c0..3a35a303c 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Location/LocationService.cs @@ -8,6 +8,8 @@ namespace eShopOnContainers.Core.Services.Location { private readonly IRequestProvider _requestProvider; + private const string ApiUrlBase = "api/v1/l/locations"; + public LocationService(IRequestProvider requestProvider) { _requestProvider = requestProvider; @@ -15,8 +17,8 @@ namespace eShopOnContainers.Core.Services.Location public async Task UpdateUserLocation(eShopOnContainers.Core.Models.Location.Location newLocReq, string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); - builder.Path = "/mobilemarketingapigw/api/v1/l/locations"; + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayMarketingEndpoint); + builder.Path = ApiUrlBase; string uri = builder.ToString(); await _requestProvider.PostAsync(uri, newLocReq, token); } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs index 2fa5eaa9e..926a03d1e 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Marketing/CampaignService.cs @@ -13,7 +13,7 @@ namespace eShopOnContainers.Core.Services.Marketing private readonly IRequestProvider _requestProvider; private readonly IFixUriService _fixUriService; - private const string ApiUrlBase = "mobilemarketingapigw/api/v1/m/campaigns"; + private const string ApiUrlBase = "api/v1/m/campaigns"; public CampaignService(IRequestProvider requestProvider, IFixUriService fixUriService) { @@ -23,7 +23,7 @@ namespace eShopOnContainers.Core.Services.Marketing public async Task> GetAllCampaignsAsync(string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayMarketingEndpoint); builder.Path = $"{ApiUrlBase}/user"; string uri = builder.ToString(); @@ -40,7 +40,7 @@ namespace eShopOnContainers.Core.Services.Marketing public async Task GetCampaignByIdAsync(int campaignId, string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayMarketingEndpoint); builder.Path = $"{ApiUrlBase}/{campaignId}"; string uri = builder.ToString(); return await _requestProvider.GetAsync(uri, token); diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs index fb9a0c627..7595a7212 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Order/OrderService.cs @@ -11,7 +11,7 @@ namespace eShopOnContainers.Core.Services.Order { private readonly IRequestProvider _requestProvider; - private const string ApiUrlBase = "mobileshoppingapigw/api/v1/o/orders"; + private const string ApiUrlBase = "api/v1/o/orders"; public OrderService(IRequestProvider requestProvider) { @@ -25,7 +25,7 @@ namespace eShopOnContainers.Core.Services.Order public async Task> GetOrdersAsync(string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint); builder.Path = ApiUrlBase; @@ -42,7 +42,7 @@ namespace eShopOnContainers.Core.Services.Order { try { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint); builder.Path = $"{ApiUrlBase}/{orderId}"; @@ -78,7 +78,7 @@ namespace eShopOnContainers.Core.Services.Order public async Task CancelOrderAsync(int orderId, string token) { - UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BaseEndpoint); + UriBuilder builder = new UriBuilder(GlobalSetting.Instance.GatewayShoppingEndpoint); builder.Path = $"{ApiUrlBase}/cancel"; diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs index 69ede7b72..c110f98e3 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/ISettingsService.cs @@ -7,7 +7,9 @@ namespace eShopOnContainers.Core.Services.Settings string AuthAccessToken { get; set; } string AuthIdToken { get; set; } bool UseMocks { get; set; } - string UrlBase { get; set; } + string IdentityEndpointBase { get; set; } + string GatewayShoppingEndpointBase { get; set; } + string GatewayMarketingEndpointBase { get; set; } bool UseFakeLocation { get; set; } string Latitude { get; set; } string Longitude { get; set; } diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs index ca3e03c04..76dee8ddd 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Services/Settings/SettingsService.cs @@ -11,7 +11,9 @@ namespace eShopOnContainers.Core.Services.Settings private const string AccessToken = "access_token"; private const string IdToken = "id_token"; private const string IdUseMocks = "use_mocks"; - private const string IdUrlBase = "url_base"; + private const string IdIdentityBase = "url_base"; + private const string IdGatewayMarketingBase = "url_marketing"; + private const string IdGatewayShoppingBase = "url_shopping"; private const string IdUseFakeLocation = "use_fake_location"; private const string IdLatitude = "latitude"; private const string IdLongitude = "longitude"; @@ -23,8 +25,9 @@ namespace eShopOnContainers.Core.Services.Settings private readonly bool AllowGpsLocationDefault = false; private readonly double FakeLatitudeDefault = 47.604610d; private readonly double FakeLongitudeDefault = -122.315752d; - private readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint; - + private readonly string UrlIdentityDefault = GlobalSetting.Instance.BaseIdentityEndpoint; + private readonly string UrlGatewayMarketingDefault = GlobalSetting.Instance.BaseGatewayMarketingEndpoint; + private readonly string UrlGatewayShoppingDefault = GlobalSetting.Instance.BaseGatewayShoppingEndpoint; #endregion #region Settings Properties @@ -47,10 +50,22 @@ namespace eShopOnContainers.Core.Services.Settings set => AddOrUpdateValue(IdUseMocks, value); } - public string UrlBase + public string IdentityEndpointBase + { + get => GetValueOrDefault(IdIdentityBase, UrlIdentityDefault); + set => AddOrUpdateValue(IdIdentityBase, value); + } + + public string GatewayShoppingEndpointBase + { + get => GetValueOrDefault(IdGatewayShoppingBase, UrlGatewayShoppingDefault); + set => AddOrUpdateValue(IdGatewayShoppingBase, value); + } + + public string GatewayMarketingEndpointBase { - get => GetValueOrDefault(IdUrlBase, UrlBaseDefault); - set => AddOrUpdateValue(IdUrlBase, value); + get => GetValueOrDefault(IdGatewayMarketingBase, UrlGatewayMarketingDefault); + set => AddOrUpdateValue(IdGatewayMarketingBase, value); } public bool UseFakeLocation diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelBase.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelBase.cs index acb5e6636..30efc544d 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelBase.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/Base/ViewModelBase.cs @@ -29,7 +29,12 @@ namespace eShopOnContainers.Core.ViewModels.Base { DialogService = ViewModelLocator.Resolve(); NavigationService = ViewModelLocator.Resolve(); - GlobalSetting.Instance.BaseEndpoint = ViewModelLocator.Resolve().UrlBase; + + var settingsService = ViewModelLocator.Resolve(); + + GlobalSetting.Instance.BaseIdentityEndpoint = settingsService.IdentityEndpointBase; + GlobalSetting.Instance.BaseGatewayShoppingEndpoint = settingsService.GatewayShoppingEndpointBase; + GlobalSetting.Instance.BaseGatewayMarketingEndpoint = settingsService.GatewayMarketingEndpointBase; } public virtual Task InitializeAsync(object navigationData) diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs index 9ee3d5103..9f8b42b2c 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs @@ -16,7 +16,9 @@ namespace eShopOnContainers.Core.ViewModels private bool _useAzureServices; private bool _allowGpsLocation; private bool _useFakeLocation; - private string _endpoint; + private string _identityEndpoint; + private string _gatewayShoppingEndpoint; + private string _gatewayMarketingEndpoint; private double _latitude; private double _longitude; private string _gpsWarningMessage; @@ -32,7 +34,9 @@ namespace eShopOnContainers.Core.ViewModels _dependencyService = dependencyService; _useAzureServices = !_settingsService.UseMocks; - _endpoint = _settingsService.UrlBase; + _identityEndpoint = _settingsService.IdentityEndpointBase; + _gatewayShoppingEndpoint = _settingsService.GatewayShoppingEndpointBase; + _gatewayMarketingEndpoint = _settingsService.GatewayMarketingEndpointBase; _latitude = double.Parse(_settingsService.Latitude, CultureInfo.CurrentCulture); _longitude = double.Parse(_settingsService.Longitude, CultureInfo.CurrentCulture); _useFakeLocation = _settingsService.UseFakeLocation; @@ -51,7 +55,7 @@ namespace eShopOnContainers.Core.ViewModels { return !UseAzureServices ? "Mock Services are simulated objects that mimic the behavior of real services using a controlled approach." - : "When enabling the use of microservices/containers, the app will attempt to use real services deployed as Docker containers at the specified base endpoint, which will must be reachable through the network."; + : "When enabling the use of microservices/containers, the app will attempt to use real services deployed as Docker/Kubernetes containers at the specified base endpoint, which will must be reachable through the network."; } } @@ -117,17 +121,45 @@ namespace eShopOnContainers.Core.ViewModels } } - public string Endpoint + public string IdentityEndpoint { - get => _endpoint; + get => _identityEndpoint; set { - _endpoint = value; - if (!string.IsNullOrEmpty(_endpoint)) + _identityEndpoint = value; + if (!string.IsNullOrEmpty(_identityEndpoint)) { - UpdateEndpoint(); + UpdateIdentityEndpoint(); } - RaisePropertyChanged(() => Endpoint); + RaisePropertyChanged(() => IdentityEndpoint); + } + } + + public string GatewayShoppingEndpoint + { + get => _gatewayShoppingEndpoint; + set + { + _gatewayShoppingEndpoint = value; + if (!string.IsNullOrEmpty(_gatewayShoppingEndpoint)) + { + UpdateGatewayShoppingEndpoint(); + } + RaisePropertyChanged(() => GatewayShoppingEndpoint); + } + } + + public string GatewayMarketingEndpoint + { + get => _gatewayMarketingEndpoint; + set + { + _gatewayMarketingEndpoint = value; + if (!string.IsNullOrEmpty(_gatewayMarketingEndpoint)) + { + UpdateGatewayMarketingEndpoint(); + } + RaisePropertyChanged(() => GatewayMarketingEndpoint); } } @@ -233,10 +265,20 @@ namespace eShopOnContainers.Core.ViewModels _settingsService.UseMocks = !_useAzureServices; } - private void UpdateEndpoint() + private void UpdateIdentityEndpoint() { // Update remote endpoint (save to local storage) - GlobalSetting.Instance.BaseEndpoint = _settingsService.UrlBase = _endpoint; + GlobalSetting.Instance.BaseIdentityEndpoint = _settingsService.IdentityEndpointBase = _identityEndpoint; + } + + private void UpdateGatewayShoppingEndpoint() + { + GlobalSetting.Instance.BaseGatewayShoppingEndpoint = _settingsService.GatewayShoppingEndpointBase = _gatewayShoppingEndpoint; + } + + private void UpdateGatewayMarketingEndpoint() + { + GlobalSetting.Instance.BaseGatewayMarketingEndpoint = _settingsService.GatewayMarketingEndpointBase = _gatewayMarketingEndpoint; } private void UpdateFakeLocation() diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml index 7d200bbc8..465f6d0ba 100644 --- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml +++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/Views/SettingsView.xaml @@ -168,10 +168,36 @@ Style="{StaticResource SettingsStackLayoutStyle}" IsVisible="{Binding UseAzureServices}">