diff --git a/Directory.Packages.props b/Directory.Packages.props index 8a045ab2c4..b96e82e0ff 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -78,7 +78,7 @@ - + diff --git a/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.Api/SFA.DAS.ApprenticeCommitments.Api.csproj b/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.Api/SFA.DAS.ApprenticeCommitments.Api.csproj index 960a7f5364..c51aa64f43 100644 --- a/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.Api/SFA.DAS.ApprenticeCommitments.Api.csproj +++ b/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.Api/SFA.DAS.ApprenticeCommitments.Api.csproj @@ -55,8 +55,10 @@ - + + + diff --git a/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.sln b/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.sln index c7120d0e4d..8c977fed3e 100644 --- a/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.sln +++ b/src/ApprenticeCommitments/SFA.DAS.ApprenticeCommitments.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.32126.315 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SFA.DAS.ApprenticeCommitments", "SFA.DAS.ApprenticeCommitments\SFA.DAS.ApprenticeCommitments.csproj", "{4EF11FD1-20DE-446A-B5DF-02CF9B289059}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SFA.DAS.ApprenticeCommitments.Api", "SFA.DAS.ApprenticeCommitments.Api\SFA.DAS.ApprenticeCommitments.Api.csproj", "{8097F35C-39A4-4A20-A443-48C2BD32070E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SFA.DAS.ApprenticeCommitments.Api", "SFA.DAS.ApprenticeCommitments.Api\SFA.DAS.ApprenticeCommitments.Api.csproj", "{8097F35C-39A4-4A20-A443-48C2BD32070E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SFA.DAS.ApprenticeCommitments.Api.AcceptanceTests", "SFA.DAS.ApprenticeCommitments.Api.AcceptanceTests\SFA.DAS.ApprenticeCommitments.Api.AcceptanceTests.csproj", "{EA634DDE-8FD7-482F-9B2E-1AA061825B7C}" EndProject @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SFA.DAS.SharedOuterApi.Unit EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{DA12142C-C24A-4E3F-9C8C-7536F3915FDE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SFA.DAS.SharedOuterApi.Apprentice.GovUK.Auth", "..\Shared\SFA.DAS.SharedOuterApi.Apprentice.GovUK.Auth\SFA.DAS.SharedOuterApi.Apprentice.GovUK.Auth.csproj", "{9A8DA95E-D09D-4CFD-8061-313564A75617}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -52,6 +54,10 @@ Global {41D340D7-A7E7-4430-B7F3-C5C1A90DD113}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {41D340D7-A7E7-4430-B7F3-C5C1A90DD113}.Release|Any CPU.ActiveCfg = Release|Any CPU {41D340D7-A7E7-4430-B7F3-C5C1A90DD113}.Release|Any CPU.Build.0 = Release|Any CPU + {9A8DA95E-D09D-4CFD-8061-313564A75617}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A8DA95E-D09D-4CFD-8061-313564A75617}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A8DA95E-D09D-4CFD-8061-313564A75617}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A8DA95E-D09D-4CFD-8061-313564A75617}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Apprenticeships/SFA.DAS.Apprenticeships.Api/Properties/launchSettings.json b/src/Apprenticeships/SFA.DAS.Apprenticeships.Api/Properties/launchSettings.json index 5d63a6be01..39157000af 100644 --- a/src/Apprenticeships/SFA.DAS.Apprenticeships.Api/Properties/launchSettings.json +++ b/src/Apprenticeships/SFA.DAS.Apprenticeships.Api/Properties/launchSettings.json @@ -1,13 +1,4 @@ { - "$schema": "https://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:22894", - "sslPort": 44333 - } - }, "profiles": { "SFA.DAS.Apprenticeships.Api": { "commandName": "Project", @@ -25,6 +16,45 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "With All Stubs": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "CoursesApiConfiguration__Url": "http://localhost:6011", + "ApprenticeshipsApiConfiguration__Url": "http://localhost:6012", + "CommitmentsV2ApiConfiguration__Url": "http://localhost:6013", + "AccountsInnerApi__Url": "http://localhost:6014", + "EmployerProfilesApiConfiguration__Url": "http://localhost:6015", + "CollectionCalendarApiConfiguration__Url": "http://localhost:6016" + }, + "applicationUrl": "https://localhost:7101;http://localhost:5101", + "dotnetRunMessages": true + }, + "With Real Inner": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "CoursesApiConfiguration__Url": "http://localhost:6011", + "ApprenticeshipsApiConfiguration__Url": "http://localhost:6012", + "CommitmentsV2ApiConfiguration__Url": "http://localhost:6013", + "AccountsInnerApi__Url": "http://localhost:6014", + "EmployerProfilesApiConfiguration__Url": "http://localhost:6015", + "CollectionCalendarApiConfiguration__Url": "http://localhost:6016" + }, + "applicationUrl": "https://localhost:7101;http://localhost:5101", + "dotnetRunMessages": true + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:22894", + "sslPort": 44333 } } } \ No newline at end of file diff --git a/src/Apprenticeships/SFA.DAS.Apprenticeships.Stubs/Program.cs b/src/Apprenticeships/SFA.DAS.Apprenticeships.Stubs/Program.cs new file mode 100644 index 0000000000..4be779ac5b --- /dev/null +++ b/src/Apprenticeships/SFA.DAS.Apprenticeships.Stubs/Program.cs @@ -0,0 +1,308 @@ +using System.Net; +using System.Text.Json; +using AutoFixture; +using SFA.DAS.Apprenticeships.InnerApi; +using SFA.DAS.Apprenticeships.Responses; +using SFA.DAS.SharedOuterApi.InnerApi.Responses; +using SFA.DAS.SharedOuterApi.InnerApi.Responses.Apprenticeships; +using SFA.DAS.SharedOuterApi.InnerApi.Responses.CollectionCalendar; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using WireMock.Settings; + +namespace SFA.DAS.Apprenticeships.Stubs +{ + public class Program + { + private static WireMockServer _fakeCoursesApi; + private static WireMockServer _fakeApprenticeshipsApi; + private static WireMockServer _fakeCommitmentsApi; + private static WireMockServer _fakeAccountsApi; + private static WireMockServer _fakeEmployerProfilesApi; + private static WireMockServer _fakeCollectionCalendarApi; + + static void Main(string[] args) + { + try + { + _fakeCoursesApi = WireMockServer.Start(new WireMockServerSettings + { + Urls = new[] { "http://*:6011" }, + StartAdminInterface = true, + }); + SetUpCoursesResponses(); + + _fakeApprenticeshipsApi = WireMockServer.Start(new WireMockServerSettings + { + Urls = new[] { "http://*:6012" }, + StartAdminInterface = true, + }); + SetUpApprenticeshipResponses(); + + _fakeCommitmentsApi = WireMockServer.Start(new WireMockServerSettings + { + Urls = new[] { "http://*:6013" }, + StartAdminInterface = true, + }); + SetUpCommitmentsResponses(); + + _fakeAccountsApi = WireMockServer.Start(new WireMockServerSettings + { + Urls = new[] { "http://*:6014" }, + StartAdminInterface = true, + }); + SetUpAccountsResponses(); + + _fakeEmployerProfilesApi = WireMockServer.Start(new WireMockServerSettings + { + Urls = new[] { "http://*:6015" }, + StartAdminInterface = true, + }); + SetUpEmployerProfilesResponses(); + + _fakeCollectionCalendarApi = WireMockServer.Start(new WireMockServerSettings + { + Urls = new[] { "http://*:6016" }, + StartAdminInterface = true, + }); + SetupCollectionCalendarResponses(); + + Console.WriteLine(("Please RETURN to stop server")); + Console.ReadLine(); + } + finally + { + _fakeCoursesApi.Stop(); + _fakeCoursesApi.Dispose(); + _fakeApprenticeshipsApi.Stop(); + _fakeApprenticeshipsApi.Dispose(); + _fakeCommitmentsApi.Stop(); + _fakeCommitmentsApi.Dispose(); + _fakeAccountsApi.Stop(); + _fakeAccountsApi.Dispose(); + _fakeEmployerProfilesApi.Stop(); + _fakeEmployerProfilesApi.Dispose(); + _fakeCollectionCalendarApi.Stop(); + _fakeCollectionCalendarApi.Dispose(); + } + } + + private static void SetUpCoursesResponses() + { + _fakeCoursesApi.Given( + Request.Create().WithPath($"/api/courses/standards/*") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + } + + private static void SetupCollectionCalendarResponses() + { + _fakeCollectionCalendarApi.Given( + Request.Create().WithPath($"/academicyears") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + } + + private static void SetUpCommitmentsResponses() + { + _fakeCommitmentsApi.Given( + Request.Create().WithPath($"/api/AccountLegalEntity/*") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeCommitmentsApi.Given( + Request.Create().WithPath($"/api/providers/*") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeCommitmentsApi.Given( + Request.Create().WithPath($"/api/trainingprogramme/*/versions") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + } + + private static void SetUpApprenticeshipResponses() + { + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/key") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/price") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/startDate") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/priceHistory").UsingPost() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/startDateChange").UsingPost() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/priceHistory/pending").UsingGet() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/startDateChange/pending").UsingGet() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Create()))); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/priceHistory/pending").UsingDelete() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/priceHistory/pending/reject").UsingPatch() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/priceHistory/pending").UsingPatch() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/startDateChange/pending").UsingDelete() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/startDateChange/reject").UsingPatch() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/startDateChange/pending").UsingPatch() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/freeze").UsingPost() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + + _fakeApprenticeshipsApi.Given( + Request.Create().WithPath($"/*/unfreeze").UsingPost() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody("{}")); + } + + private static void SetUpAccountsResponses() + { + _fakeAccountsApi.Given( + Request.Create().WithPath($"/api/user/*/accounts") + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().CreateMany()))); + } + + private static void SetUpEmployerProfilesResponses() + { + _fakeEmployerProfilesApi.Given( + Request.Create().WithPath($"/api/users/*") + .UsingGet() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(new Fixture().Build().With(x => x.Id, Guid.NewGuid().ToString).Create()))); + } + } +} \ No newline at end of file diff --git a/src/Apprenticeships/SFA.DAS.Apprenticeships.Stubs/SFA.DAS.Apprenticeships.Stubs.csproj b/src/Apprenticeships/SFA.DAS.Apprenticeships.Stubs/SFA.DAS.Apprenticeships.Stubs.csproj new file mode 100644 index 0000000000..02bcc5ce9b --- /dev/null +++ b/src/Apprenticeships/SFA.DAS.Apprenticeships.Stubs/SFA.DAS.Apprenticeships.Stubs.csproj @@ -0,0 +1,20 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + diff --git a/src/Apprenticeships/SFA.DAS.Apprenticeships.sln b/src/Apprenticeships/SFA.DAS.Apprenticeships.sln index 02fedcb279..b7495be835 100644 --- a/src/Apprenticeships/SFA.DAS.Apprenticeships.sln +++ b/src/Apprenticeships/SFA.DAS.Apprenticeships.sln @@ -17,6 +17,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SFA.DAS.SharedOuterApi", ". EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SFA.DAS.SharedOuterApi.UnitTests", "..\Shared\SFA.DAS.SharedOuterApi.UnitTests\SFA.DAS.SharedOuterApi.UnitTests.csproj", "{C6ECCA19-D25A-4749-AEEF-9BF003C921F5}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stubs", "Stubs", "{5A06408D-D406-4285-958D-F2618BC987FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SFA.DAS.Apprenticeships.Stubs", "SFA.DAS.Apprenticeships.Stubs\SFA.DAS.Apprenticeships.Stubs.csproj", "{8D741612-C398-4164-95DE-3AAEB0CD39F6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -47,6 +51,10 @@ Global {C6ECCA19-D25A-4749-AEEF-9BF003C921F5}.Debug|Any CPU.Build.0 = Debug|Any CPU {C6ECCA19-D25A-4749-AEEF-9BF003C921F5}.Release|Any CPU.ActiveCfg = Release|Any CPU {C6ECCA19-D25A-4749-AEEF-9BF003C921F5}.Release|Any CPU.Build.0 = Release|Any CPU + {8D741612-C398-4164-95DE-3AAEB0CD39F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D741612-C398-4164-95DE-3AAEB0CD39F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D741612-C398-4164-95DE-3AAEB0CD39F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D741612-C398-4164-95DE-3AAEB0CD39F6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -54,6 +62,7 @@ Global GlobalSection(NestedProjects) = preSolution {322E17EC-CEA4-4C01-86B1-C13D09F10B86} = {3FE9AA84-D0A7-42FA-96A7-31136C2C236D} {C6ECCA19-D25A-4749-AEEF-9BF003C921F5} = {3FE9AA84-D0A7-42FA-96A7-31136C2C236D} + {8D741612-C398-4164-95DE-3AAEB0CD39F6} = {5A06408D-D406-4285-958D-F2618BC987FB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E20541EE-1A11-4048-9593-FA357F0ED2FC} diff --git a/src/Apprenticeships/SFA.DAS.Apprenticeships.slnLaunch b/src/Apprenticeships/SFA.DAS.Apprenticeships.slnLaunch new file mode 100644 index 0000000000..70d43f2f4b --- /dev/null +++ b/src/Apprenticeships/SFA.DAS.Apprenticeships.slnLaunch @@ -0,0 +1,30 @@ +[ + { + "Name": "With All Stubs", + "Projects": [ + { + "Path": "SFA.DAS.Apprenticeships.Api\\SFA.DAS.Apprenticeships.Api.csproj", + "Action": "Start", + "DebugTarget": "With All Stubs" + }, + { + "Path": "SFA.DAS.Apprenticeships.Stubs\\SFA.DAS.Apprenticeships.Stubs.csproj", + "Action": "Start" + } + ] + }, + { + "Name": "With Real Inner", + "Projects": [ + { + "Path": "SFA.DAS.Apprenticeships.Api\\SFA.DAS.Apprenticeships.Api.csproj", + "Action": "Start", + "DebugTarget": "With Real Inner" + }, + { + "Path": "SFA.DAS.Apprenticeships.Stubs\\SFA.DAS.Apprenticeships.Stubs.csproj", + "Action": "Start" + } + ] + } +] \ No newline at end of file diff --git a/src/Payments/README.md b/src/Payments/README.md index 3bf8b624c3..ff738b479d 100644 --- a/src/Payments/README.md +++ b/src/Payments/README.md @@ -30,7 +30,7 @@ Most of the application configuration is taken from the [das-employer-config rep | Name | Description | Stub Value | | ------------------------------------------------------------- | ------------------------------------------------- |-------------------------------------------| | LearnerDataApiConfiguration:Url | Url of the data endpoint | https://localhost:4000/learner-data-api | -| LearnerDataApiConfiguration:TokenSettings:Url | Url of the token endpoint | | +| LearnerDataApiConfiguration:TokenSettings:Url | Url of the token endpoint | http://localhost (if using stub api) | | LearnerDataApiConfiguration:TokenSettings:Scope | Token settings | | | LearnerDataApiConfiguration:TokenSettings:ClientId | Token settings | | | LearnerDataApiConfiguration:TokenSettings:Tenant | Token settings | | @@ -38,17 +38,22 @@ Most of the application configuration is taken from the [das-employer-config rep | LearnerDataApiConfiguration:TokenSettings:GrantType | Token settings | | | LearnerDataApiConfiguration:TokenSettings:ShouldSkipForLocal | For local use only, skips calling token endpoint | true | +### Local Running +* Ensure you have the following appsettings.development.json in the API project root: +``` +{ + "Environment": "LOCAL", + "ConfigurationStorageConnectionString": "UseDevelopmentStorage=true" +} +``` -## 🔗 External Dependencies +* Make sure Azure Storage Emulator is running +* Make sure the config above is in Azure Storage +* If you want to use a stub Learner Data api, select the "API with Stubs" Launch Profile (it'll manage config and start the stubs automatically), otherwise just run SFA.DAS.Payments.API with the https launch profile -The Outer API has many external dependancies which can all be configured to use stubs by following the config above. -## Running Locally +## 🔗 External Dependencies -* Make sure Azure Storage Emulator (Azureite) is running -* Make sure the config has been updated to call any Stub APIs required -* Run the [Commitments Stubs](https://github.com/SkillsFundingAgency/das-commitments-stubs) -* Run the Apprenticeships Inner API -* Run the application \ No newline at end of file +The Outer API has many external dependancies which can all be configured to use stubs by following the config above. \ No newline at end of file diff --git a/src/Payments/SFA.DAS.Payments.Api/Properties/launchSettings.json b/src/Payments/SFA.DAS.Payments.Api/Properties/launchSettings.json index 7850330879..2f14b08f3f 100644 --- a/src/Payments/SFA.DAS.Payments.Api/Properties/launchSettings.json +++ b/src/Payments/SFA.DAS.Payments.Api/Properties/launchSettings.json @@ -1,32 +1,23 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:53085", - "sslPort": 44373 - } - }, +{ "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "http://localhost:5157", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5157" }, "https": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7157;http://localhost:5157", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7157;http://localhost:5157" }, "IIS Express": { "commandName": "IISExpress", @@ -35,6 +26,27 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "WithStubs": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "LearnerDataApiConfiguration__Url": "http://localhost:6011", + "LearnerDataApiConfiguration__TokenSettings__ShouldSkipForLocal": "true", + "LearnerDataApiConfiguration__TokenSettings__Url": "http://localhost" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7157;http://localhost:5157" + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:53085", + "sslPort": 44373 } } -} +} \ No newline at end of file diff --git a/src/Payments/SFA.DAS.Payments.Api/Startup.cs b/src/Payments/SFA.DAS.Payments.Api/Startup.cs index 866c231a17..c8bc97b960 100644 --- a/src/Payments/SFA.DAS.Payments.Api/Startup.cs +++ b/src/Payments/SFA.DAS.Payments.Api/Startup.cs @@ -5,6 +5,7 @@ using SFA.DAS.Payments.Api.AppStart; using SFA.DAS.Payments.Application.Learners; using SFA.DAS.SharedOuterApi.AppStart; +using SFA.DAS.SharedOuterApi.Configuration; using SFA.DAS.SharedOuterApi.Infrastructure.HealthCheck; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; diff --git a/src/Payments/SFA.DAS.Payments.Stubs/Program.cs b/src/Payments/SFA.DAS.Payments.Stubs/Program.cs new file mode 100644 index 0000000000..5eb7893485 --- /dev/null +++ b/src/Payments/SFA.DAS.Payments.Stubs/Program.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Text.Json; +using AutoFixture; +using SFA.DAS.Payments.Models.Responses; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using WireMock.Settings; + +namespace SFA.DAS.Payments.Stubs +{ + public class Program + { + private static WireMockServer _fakeLearnerDataApi; + + static void Main(string[] args) + { + try + { + _fakeLearnerDataApi = WireMockServer.Start(new WireMockServerSettings + { + Urls = new[] { "http://*:6011" }, + StartAdminInterface = true, + }); + + SetupGetLearnersResponse(); + + Console.WriteLine(("Please RETURN to stop server")); + Console.ReadLine(); + } + finally + { + _fakeLearnerDataApi.Stop(); + _fakeLearnerDataApi.Dispose(); + } + } + + private static void SetupGetLearnersResponse() + { + _fakeLearnerDataApi.Given( + Request.Create().WithPath($"/learners/*") + .UsingGet() + ) + .RespondWith( + Response.Create() + .WithStatusCode((int)HttpStatusCode.OK) + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(GetLearnerResponseObject()))); + } + + private static List GetLearnerResponseObject() + { + return new Fixture().CreateMany().ToList(); + } + } +} diff --git a/src/Payments/SFA.DAS.Payments.Stubs/SFA.DAS.Payments.Stubs.csproj b/src/Payments/SFA.DAS.Payments.Stubs/SFA.DAS.Payments.Stubs.csproj new file mode 100644 index 0000000000..2783baadd2 --- /dev/null +++ b/src/Payments/SFA.DAS.Payments.Stubs/SFA.DAS.Payments.Stubs.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/src/Payments/SFA.DAS.Payments.sln b/src/Payments/SFA.DAS.Payments.sln index 0845940dd9..15ca8c5499 100644 --- a/src/Payments/SFA.DAS.Payments.sln +++ b/src/Payments/SFA.DAS.Payments.sln @@ -20,6 +20,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{268E0F EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SFA.DAS.SharedOuterApi", "..\Shared\SFA.DAS.SharedOuterApi\SFA.DAS.SharedOuterApi.csproj", "{FBFA8D08-A342-4106-8805-5E4F424C3AB7}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stubs", "Stubs", "{6B356F86-6F04-48A3-A6FF-0B7B8084862E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SFA.DAS.Payments.Stubs", "SFA.DAS.Payments.Stubs\SFA.DAS.Payments.Stubs.csproj", "{DDE95B5D-161B-41DD-A22A-055173988331}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -46,12 +50,17 @@ Global {FBFA8D08-A342-4106-8805-5E4F424C3AB7}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBFA8D08-A342-4106-8805-5E4F424C3AB7}.Release|Any CPU.ActiveCfg = Release|Any CPU {FBFA8D08-A342-4106-8805-5E4F424C3AB7}.Release|Any CPU.Build.0 = Release|Any CPU + {DDE95B5D-161B-41DD-A22A-055173988331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DDE95B5D-161B-41DD-A22A-055173988331}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDE95B5D-161B-41DD-A22A-055173988331}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DDE95B5D-161B-41DD-A22A-055173988331}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {FBFA8D08-A342-4106-8805-5E4F424C3AB7} = {268E0FE2-9159-48C2-A3BF-EDB6502E0011} + {DDE95B5D-161B-41DD-A22A-055173988331} = {6B356F86-6F04-48A3-A6FF-0B7B8084862E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1FBA9471-0084-450A-961B-4B248AA9922B} diff --git a/src/Payments/SFA.DAS.Payments.slnLaunch b/src/Payments/SFA.DAS.Payments.slnLaunch new file mode 100644 index 0000000000..52719261b9 --- /dev/null +++ b/src/Payments/SFA.DAS.Payments.slnLaunch @@ -0,0 +1,16 @@ +[ + { + "Name": "API with Stubs", + "Projects": [ + { + "Path": "SFA.DAS.Payments.Api\\SFA.DAS.Payments.Api.csproj", + "Action": "Start", + "DebugTarget": "WithStubs" + }, + { + "Path": "SFA.DAS.Payments.Stubs\\SFA.DAS.Payments.Stubs.csproj", + "Action": "Start" + } + ] + } +] \ No newline at end of file diff --git a/src/Shared/SFA.DAS.SharedOuterApi/AppStart/ConfigurationBuilder.cs b/src/Shared/SFA.DAS.SharedOuterApi/AppStart/ConfigurationBuilder.cs index f0ff4260ce..c2064782bb 100644 --- a/src/Shared/SFA.DAS.SharedOuterApi/AppStart/ConfigurationBuilder.cs +++ b/src/Shared/SFA.DAS.SharedOuterApi/AppStart/ConfigurationBuilder.cs @@ -11,8 +11,7 @@ public static IConfigurationRoot BuildSharedConfiguration(this IConfiguration co { var config = new ConfigurationBuilder() .AddConfiguration(configuration) - .SetBasePath(Directory.GetCurrentDirectory()) - .AddEnvironmentVariables(); + .SetBasePath(Directory.GetCurrentDirectory()); #if DEBUG config.AddJsonFile("appsettings.json", true); if (!configuration.IsLocalAcceptanceTests()) @@ -32,6 +31,8 @@ public static IConfigurationRoot BuildSharedConfiguration(this IConfiguration co ); } + config.AddEnvironmentVariables(); + return config.Build(); }