From 19b105b0e86aa3c9f4bc454bdf8f7f9a6b056cd1 Mon Sep 17 00:00:00 2001 From: ThompsonNye Date: Sat, 17 Aug 2024 16:38:40 +0200 Subject: [PATCH] Add integration tests --- src/WebApi/Cars/GetCars.cs | 2 +- tests/WebApi.Tests.Integration/CarFaker.cs | 19 ++++ .../Cars/CreateCarTests.cs | 70 +++++++++++++ .../Cars/DeleteCarTests.cs | 64 ++++++++++++ .../Cars/GetCarTests.cs | 57 +++++++++++ .../Cars/GetCarsTests.cs | 66 +++++++++++++ .../Cars/UpdateCarTests.cs | 99 +++++++++++++++++++ .../PostgresRespawner.cs | 40 ++++++++ .../SharedTestCollection.cs | 7 ++ ...TestUserAlwaysAuthorizedPolicyEvaluator.cs | 38 +++++++ .../WebApi.Tests.Integration.csproj | 32 ++++++ .../WebApi.Tests.Integration/WebAppFactory.cs | 79 +++++++++++++++ vegasco-server.sln | 9 +- vegasco-server.sln.DotSettings | 3 + 14 files changed, 583 insertions(+), 2 deletions(-) create mode 100644 tests/WebApi.Tests.Integration/CarFaker.cs create mode 100644 tests/WebApi.Tests.Integration/Cars/CreateCarTests.cs create mode 100644 tests/WebApi.Tests.Integration/Cars/DeleteCarTests.cs create mode 100644 tests/WebApi.Tests.Integration/Cars/GetCarTests.cs create mode 100644 tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs create mode 100644 tests/WebApi.Tests.Integration/Cars/UpdateCarTests.cs create mode 100644 tests/WebApi.Tests.Integration/PostgresRespawner.cs create mode 100644 tests/WebApi.Tests.Integration/SharedTestCollection.cs create mode 100644 tests/WebApi.Tests.Integration/TestUserAlwaysAuthorizedPolicyEvaluator.cs create mode 100644 tests/WebApi.Tests.Integration/WebApi.Tests.Integration.csproj create mode 100644 tests/WebApi.Tests.Integration/WebAppFactory.cs create mode 100644 vegasco-server.sln.DotSettings diff --git a/src/WebApi/Cars/GetCars.cs b/src/WebApi/Cars/GetCars.cs index 9a8ec8b..027b026 100644 --- a/src/WebApi/Cars/GetCars.cs +++ b/src/WebApi/Cars/GetCars.cs @@ -14,7 +14,7 @@ public static class GetCars .WithTags("Cars"); } - public static async Task Endpoint( + private static async Task Endpoint( ApplicationDbContext dbContext, CancellationToken cancellationToken) { diff --git a/tests/WebApi.Tests.Integration/CarFaker.cs b/tests/WebApi.Tests.Integration/CarFaker.cs new file mode 100644 index 0000000..2d5bb5e --- /dev/null +++ b/tests/WebApi.Tests.Integration/CarFaker.cs @@ -0,0 +1,19 @@ +using Bogus; +using Vegasco.WebApi.Cars; + +namespace WebApi.Tests.Integration; + +internal class CarFaker +{ + private readonly Faker _faker = new(); + + internal CreateCar.Request CreateCarRequest() + { + return new CreateCar.Request(_faker.Vehicle.Model()); + } + + internal UpdateCar.Request UpdateCarRequest() + { + return new UpdateCar.Request(_faker.Vehicle.Model()); + } +} diff --git a/tests/WebApi.Tests.Integration/Cars/CreateCarTests.cs b/tests/WebApi.Tests.Integration/Cars/CreateCarTests.cs new file mode 100644 index 0000000..4376218 --- /dev/null +++ b/tests/WebApi.Tests.Integration/Cars/CreateCarTests.cs @@ -0,0 +1,70 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using System.Net; +using System.Net.Http.Json; +using Vegasco.WebApi.Cars; +using Vegasco.WebApi.Persistence; + +namespace WebApi.Tests.Integration.Cars; + +[Collection(SharedTestCollection.Name)] +public class CreateCarTests : IAsyncLifetime +{ + private readonly WebAppFactory _factory; + private readonly IServiceScope _scope; + private readonly ApplicationDbContext _dbContext; + + private readonly CarFaker _carFaker = new(); + + public CreateCarTests(WebAppFactory factory) + { + _factory = factory; + _scope = _factory.Services.CreateScope(); + _dbContext = _scope.ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task CreateCar_ShouldCreateCar_WhenRequestIsValid() + { + // Arrange + var createCarRequest = _carFaker.CreateCarRequest(); + + // Act + var response = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.Created); + var createdCar = await response.Content.ReadFromJsonAsync(); + createdCar.Should().BeEquivalentTo(createCarRequest, o => o.ExcludingMissingMembers()); + + _dbContext.Cars.Should().ContainEquivalentOf(createdCar); + } + + [Fact] + public async Task CreateCar_ShouldReturnValidationProblems_WhenRequestIsNotValid() + { + // Arrange + var createCarRequest = new CreateCar.Request(""); + + // Act + var response = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.BadRequest); + var validationProblemDetails = await response.Content.ReadFromJsonAsync(); + validationProblemDetails!.Errors.Keys.Should().Contain(x => + x.Equals(nameof(CreateCar.Request.Name), StringComparison.OrdinalIgnoreCase)); + + _dbContext.Cars.Should().NotContainEquivalentOf(createCarRequest, o => o.ExcludingMissingMembers()); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _scope.Dispose(); + await _dbContext.DisposeAsync(); + await _factory.ResetDatabaseAsync(); + } +} diff --git a/tests/WebApi.Tests.Integration/Cars/DeleteCarTests.cs b/tests/WebApi.Tests.Integration/Cars/DeleteCarTests.cs new file mode 100644 index 0000000..e672d0f --- /dev/null +++ b/tests/WebApi.Tests.Integration/Cars/DeleteCarTests.cs @@ -0,0 +1,64 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using System.Net; +using System.Net.Http.Json; +using Vegasco.WebApi.Cars; +using Vegasco.WebApi.Persistence; + +namespace WebApi.Tests.Integration.Cars; + +[Collection(SharedTestCollection.Name)] +public class DeleteCarTests : IAsyncLifetime +{ + private readonly WebAppFactory _factory; + private readonly IServiceScope _scope; + private readonly ApplicationDbContext _dbContext; + + private readonly CarFaker _carFaker = new(); + + public DeleteCarTests(WebAppFactory factory) + { + _factory = factory; + _scope = _factory.Services.CreateScope(); + _dbContext = _scope.ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task DeleteCar_ShouldReturnNotFound_WhenCarDoesNotExist() + { + // Arrange + var randomCarId = Guid.NewGuid(); + + // Act + var response = await _factory.HttpClient.DeleteAsync($"v1/cars/{randomCarId}"); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task DeleteCar_ShouldDeleteCar_WhenCarExists() + { + // Arrange + var createCarRequest = _carFaker.CreateCarRequest(); + var createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + createCarResponse.EnsureSuccessStatusCode(); + var createdCar = await createCarResponse.Content.ReadFromJsonAsync(); + + // Act + var response = await _factory.HttpClient.DeleteAsync($"v1/cars/{createdCar!.Id}"); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.NoContent); + _dbContext.Cars.Should().BeEmpty(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _scope.Dispose(); + await _dbContext.DisposeAsync(); + await _factory.ResetDatabaseAsync(); + } +} diff --git a/tests/WebApi.Tests.Integration/Cars/GetCarTests.cs b/tests/WebApi.Tests.Integration/Cars/GetCarTests.cs new file mode 100644 index 0000000..af2dcfa --- /dev/null +++ b/tests/WebApi.Tests.Integration/Cars/GetCarTests.cs @@ -0,0 +1,57 @@ +using FluentAssertions; +using System.Net; +using System.Net.Http.Json; +using Vegasco.WebApi.Cars; + +namespace WebApi.Tests.Integration.Cars; + +[Collection(SharedTestCollection.Name)] +public class GetCarTests : IAsyncLifetime +{ + private readonly WebAppFactory _factory; + + private readonly CarFaker _carFaker = new(); + + public GetCarTests(WebAppFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task GetCar_ShouldReturnNotFound_WhenCarDoesNotExist() + { + // Arrange + var randomCarId = Guid.NewGuid(); + + // Act + var response = await _factory.HttpClient.GetAsync($"v1/cars/{randomCarId}"); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task GetCar_ShouldReturnCar_WhenCarExists() + { + // Arrange + var createCarRequest = _carFaker.CreateCarRequest(); + var createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + createCarResponse.EnsureSuccessStatusCode(); + var createdCar = await createCarResponse.Content.ReadFromJsonAsync(); + + // Act + var response = await _factory.HttpClient.GetAsync($"v1/cars/{createdCar!.Id}"); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.OK); + var car = await response.Content.ReadFromJsonAsync(); + car.Should().BeEquivalentTo(createdCar); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _factory.ResetDatabaseAsync(); + } +} diff --git a/tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs b/tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs new file mode 100644 index 0000000..b94c864 --- /dev/null +++ b/tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs @@ -0,0 +1,66 @@ +using FluentAssertions; +using System.Net; +using System.Net.Http.Json; +using Vegasco.WebApi.Cars; + +namespace WebApi.Tests.Integration.Cars; + +[Collection(SharedTestCollection.Name)] +public class GetCarsTests : IAsyncLifetime +{ + private readonly WebAppFactory _factory; + + private readonly CarFaker _carFaker = new(); + + public GetCarsTests(WebAppFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task GetCars_ShouldReturnEmptyList_WhenNoEntriesExist() + { + // Arrange + + // Act + var response = await _factory.HttpClient.GetAsync("v1/cars"); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.OK); + var cars = await response.Content.ReadFromJsonAsync>(); + cars.Should().BeEmpty(); + } + + [Fact] + public async Task GetCars_ShouldReturnEntries_WhenEntriesExist() + { + // Arrange + List createdCars = []; + + const int numberOfCars = 5; + for (var i = 0; i < numberOfCars; i++) + { + var createCarRequest = _carFaker.CreateCarRequest(); + var createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + createCarResponse.EnsureSuccessStatusCode(); + + var createdCar = await createCarResponse.Content.ReadFromJsonAsync(); + createdCars.Add(createdCar!); + } + + // Act + var response = await _factory.HttpClient.GetAsync("v1/cars"); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.OK); + var cars = await response.Content.ReadFromJsonAsync>(); + cars.Should().BeEquivalentTo(createdCars); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _factory.ResetDatabaseAsync(); + } +} diff --git a/tests/WebApi.Tests.Integration/Cars/UpdateCarTests.cs b/tests/WebApi.Tests.Integration/Cars/UpdateCarTests.cs new file mode 100644 index 0000000..bc0ca8b --- /dev/null +++ b/tests/WebApi.Tests.Integration/Cars/UpdateCarTests.cs @@ -0,0 +1,99 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using System.Net; +using System.Net.Http.Json; +using Vegasco.WebApi.Cars; +using Vegasco.WebApi.Persistence; + +namespace WebApi.Tests.Integration.Cars; + +[Collection(SharedTestCollection.Name)] +public class UpdateCarTests : IAsyncLifetime +{ + private readonly WebAppFactory _factory; + private readonly IServiceScope _scope; + private readonly ApplicationDbContext _dbContext; + + private readonly CarFaker _carFaker = new(); + + public UpdateCarTests(WebAppFactory factory) + { + _factory = factory; + _scope = _factory.Services.CreateScope(); + _dbContext = _scope.ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task UpdateCar_ShouldUpdateCar_WhenCarExistsAndRequestIsValid() + { + // Arrange + var createCarRequest = _carFaker.CreateCarRequest(); + var createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + createCarResponse.EnsureSuccessStatusCode(); + var createdCar = await createCarResponse.Content.ReadFromJsonAsync(); + + var updateCarRequest = _carFaker.UpdateCarRequest(); + + // Act + var response = await _factory.HttpClient.PutAsJsonAsync($"v1/cars/{createdCar!.Id}", updateCarRequest); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.OK); + var updatedCar = await response.Content.ReadFromJsonAsync(); + updatedCar!.Id.Should().Be(createdCar.Id); + updatedCar.Should().BeEquivalentTo(updateCarRequest, o => o.ExcludingMissingMembers()); + + _dbContext.Cars.Should().ContainEquivalentOf(updatedCar, o => o.ExcludingMissingMembers()); + } + + [Fact] + public async Task UpdateCar_ShouldReturnValidationProblems_WhenRequestIsNotValid() + { + // Arrange + var createCarRequest = _carFaker.CreateCarRequest(); + var createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + createCarResponse.EnsureSuccessStatusCode(); + var createdCar = await createCarResponse.Content.ReadFromJsonAsync(); + + var updateCarRequest = new UpdateCar.Request(""); + + // Act + var response = await _factory.HttpClient.PutAsJsonAsync($"v1/cars/{createdCar!.Id}", updateCarRequest); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.BadRequest); + var validationProblemDetails = await response.Content.ReadFromJsonAsync(); + validationProblemDetails!.Errors.Keys.Should().Contain(x => + x.Equals(nameof(CreateCar.Request.Name), StringComparison.OrdinalIgnoreCase)); + + _dbContext.Cars.Should().ContainSingle(x => x.Id == createdCar.Id) + .Which + .Should().NotBeEquivalentTo(updateCarRequest, o => o.ExcludingMissingMembers()); + } + + [Fact] + public async Task UpdateCar_ShouldReturnNotFound_WhenNoCarWithIdExists() + { + // Arrange + var updateCarRequest = _carFaker.UpdateCarRequest(); + var randomCarId = Guid.NewGuid(); + + // Act + var response = await _factory.HttpClient.PutAsJsonAsync($"v1/cars/{randomCarId}", updateCarRequest); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + + _dbContext.Cars.Should().BeEmpty(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _scope.Dispose(); + await _dbContext.DisposeAsync(); + await _factory.ResetDatabaseAsync(); + } +} diff --git a/tests/WebApi.Tests.Integration/PostgresRespawner.cs b/tests/WebApi.Tests.Integration/PostgresRespawner.cs new file mode 100644 index 0000000..d969aac --- /dev/null +++ b/tests/WebApi.Tests.Integration/PostgresRespawner.cs @@ -0,0 +1,40 @@ +using Npgsql; +using Respawn; +using System.Data.Common; + +namespace WebApi.Tests.Integration; +internal sealed class PostgresRespawner : IDisposable +{ + private readonly DbConnection _connection; + private readonly Respawner _respawner; + + private PostgresRespawner(Respawner respawner, DbConnection connection) + { + _respawner = respawner; + _connection = connection; + } + + public static async Task CreateAsync(string connectionString) + { + DbConnection connection = new NpgsqlConnection(connectionString); + await connection.OpenAsync(); + + var respawner = await Respawner.CreateAsync(connection, + new RespawnerOptions + { + SchemasToInclude = ["public"], + DbAdapter = DbAdapter.Postgres + }); + return new PostgresRespawner(respawner, connection); + } + + public async Task ResetDatabaseAsync() + { + await _respawner.ResetAsync(_connection); + } + + public void Dispose() + { + _connection.Dispose(); + } +} diff --git a/tests/WebApi.Tests.Integration/SharedTestCollection.cs b/tests/WebApi.Tests.Integration/SharedTestCollection.cs new file mode 100644 index 0000000..bb824b2 --- /dev/null +++ b/tests/WebApi.Tests.Integration/SharedTestCollection.cs @@ -0,0 +1,7 @@ +namespace WebApi.Tests.Integration; + +[CollectionDefinition(Name)] +public class SharedTestCollection : ICollectionFixture +{ + public const string Name = nameof(SharedTestCollection); +} diff --git a/tests/WebApi.Tests.Integration/TestUserAlwaysAuthorizedPolicyEvaluator.cs b/tests/WebApi.Tests.Integration/TestUserAlwaysAuthorizedPolicyEvaluator.cs new file mode 100644 index 0000000..ce19bdf --- /dev/null +++ b/tests/WebApi.Tests.Integration/TestUserAlwaysAuthorizedPolicyEvaluator.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization.Policy; +using Microsoft.AspNetCore.Http; +using System.Security.Claims; + +namespace WebApi.Tests.Integration; + +public sealed class TestUserAlwaysAuthorizedPolicyEvaluator : IPolicyEvaluator +{ + public const string Username = "Test user"; + public static readonly string UserId = Guid.NewGuid().ToString(); + + public Task AuthenticateAsync(AuthorizationPolicy policy, HttpContext context) + { + Claim[] claims = + [ + + new Claim(ClaimTypes.Name, Username), + new Claim("name", Username), + new Claim(ClaimTypes.NameIdentifier, UserId), + new Claim("aud", "https://localhost") + ]; + + ClaimsIdentity identity = new(claims, JwtBearerDefaults.AuthenticationScheme); + ClaimsPrincipal principal = new(identity); + AuthenticationTicket ticket = new(principal, JwtBearerDefaults.AuthenticationScheme); + var result = AuthenticateResult.Success(ticket); + return Task.FromResult(result); ; + } + + public Task AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, + object? resource) + { + return Task.FromResult(PolicyAuthorizationResult.Success()); + } +} \ No newline at end of file diff --git a/tests/WebApi.Tests.Integration/WebApi.Tests.Integration.csproj b/tests/WebApi.Tests.Integration/WebApi.Tests.Integration.csproj new file mode 100644 index 0000000..9f191f4 --- /dev/null +++ b/tests/WebApi.Tests.Integration/WebApi.Tests.Integration.csproj @@ -0,0 +1,32 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/WebApi.Tests.Integration/WebAppFactory.cs b/tests/WebApi.Tests.Integration/WebAppFactory.cs new file mode 100644 index 0000000..3fb871d --- /dev/null +++ b/tests/WebApi.Tests.Integration/WebAppFactory.cs @@ -0,0 +1,79 @@ +using DotNet.Testcontainers.Images; +using Microsoft.AspNetCore.Authorization.Policy; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Testcontainers.PostgreSql; +using Vegasco.WebApi.Common; +using Vegasco.WebApi.Persistence; + +namespace WebApi.Tests.Integration; + +public sealed class WebAppFactory : WebApplicationFactory, IAsyncLifetime +{ + private readonly PostgreSqlContainer _database = new PostgreSqlBuilder() + .WithImage(DockerImage) + .WithImagePullPolicy(PullPolicy.Always) + .Build(); + + private const string DockerImage = "postgres:16.3-alpine"; + + public HttpClient HttpClient => CreateClient(); + + private PostgresRespawner? _postgresRespawner; + + public async Task InitializeAsync() + { + await _database.StartAsync(); + + // Force application startup (i.e. initialization and validation) + _ = CreateClient(); + + using var scope = Services.CreateScope(); + await using var dbContext = scope.ServiceProvider.GetRequiredService(); + await dbContext.Database.MigrateAsync(); + + _postgresRespawner = await PostgresRespawner.CreateAsync(_database.GetConnectionString()); + } + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + IEnumerable> customConfig = + [ + new KeyValuePair("ConnectionStrings:Database", _database.GetConnectionString()), + new KeyValuePair("JWT:Authority", "https://localhost"), + new KeyValuePair("JWT:Audience", "https://localhost"), + new KeyValuePair("JWT:Issuer", "https://localhost"), + new KeyValuePair("JWT:NameClaimType", null), + ]; + + builder.UseConfiguration(new ConfigurationBuilder() + .AddInMemoryCollection(customConfig) + .Build()); + + builder.ConfigureServices(services => + { + }); + + builder.ConfigureTestServices(services => + { + services.RemoveAll(); + services.AddSingleton(); + }); + } + + public async Task ResetDatabaseAsync() + { + await _postgresRespawner!.ResetDatabaseAsync(); + } + + async Task IAsyncLifetime.DisposeAsync() + { + _postgresRespawner!.Dispose(); + await _database.DisposeAsync(); + } +} \ No newline at end of file diff --git a/vegasco-server.sln b/vegasco-server.sln index 4ea8158..7c09892 100644 --- a/vegasco-server.sln +++ b/vegasco-server.sln @@ -14,7 +14,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{437DE053-1DAB-4EEF-BEA6-E3B5179692F8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi.Tests.Unit", "tests\WebApi.Tests.Unit\WebApi.Tests.Unit.csproj", "{5BA94D65-1D04-49EA-B7CC-F3719DE2D97E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi.Tests.Unit", "tests\WebApi.Tests.Unit\WebApi.Tests.Unit.csproj", "{5BA94D65-1D04-49EA-B7CC-F3719DE2D97E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi.Tests.Integration", "tests\WebApi.Tests.Integration\WebApi.Tests.Integration.csproj", "{0B1F3D81-95E8-4CFC-8A90-8A3CB2549326}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -30,6 +32,10 @@ Global {5BA94D65-1D04-49EA-B7CC-F3719DE2D97E}.Debug|Any CPU.Build.0 = Debug|Any CPU {5BA94D65-1D04-49EA-B7CC-F3719DE2D97E}.Release|Any CPU.ActiveCfg = Release|Any CPU {5BA94D65-1D04-49EA-B7CC-F3719DE2D97E}.Release|Any CPU.Build.0 = Release|Any CPU + {0B1F3D81-95E8-4CFC-8A90-8A3CB2549326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0B1F3D81-95E8-4CFC-8A90-8A3CB2549326}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0B1F3D81-95E8-4CFC-8A90-8A3CB2549326}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0B1F3D81-95E8-4CFC-8A90-8A3CB2549326}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -37,6 +43,7 @@ Global GlobalSection(NestedProjects) = preSolution {9FF3C98A-5085-4EBE-A980-DB2148B0C00A} = {C051A684-BD6A-43F2-B0CC-F3C2315D99E3} {5BA94D65-1D04-49EA-B7CC-F3719DE2D97E} = {437DE053-1DAB-4EEF-BEA6-E3B5179692F8} + {0B1F3D81-95E8-4CFC-8A90-8A3CB2549326} = {437DE053-1DAB-4EEF-BEA6-E3B5179692F8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7813E32D-AE19-479C-853B-063882D2D05A} diff --git a/vegasco-server.sln.DotSettings b/vegasco-server.sln.DotSettings new file mode 100644 index 0000000..d8d7c4c --- /dev/null +++ b/vegasco-server.sln.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file