mirror of
https://github.com/meysamhadeli/booking-microservices.git
synced 2026-04-29 17:25:49 +08:00
Merge pull request #349 from AyobKafrashian/Complete-modular-monolith-tests
feat: compleate modular monolith tests
This commit is contained in:
commit
b0da80bfff
@ -18,7 +18,7 @@ using MediatR;
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Passenger;
|
using BookingPassenger;
|
||||||
using ValueObjects;
|
using ValueObjects;
|
||||||
|
|
||||||
public record CreateBooking(Guid PassengerId, Guid FlightId, string Description) : ICommand<CreateBookingResult>
|
public record CreateBooking(Guid PassengerId, Guid FlightId, string Description) : ICommand<CreateBookingResult>
|
||||||
@ -107,7 +107,7 @@ internal class CreateBookingCommandHandler : ICommandHandler<CreateBooking, Crea
|
|||||||
}
|
}
|
||||||
|
|
||||||
var passenger =
|
var passenger =
|
||||||
await _passengerGrpcServiceClient.GetByIdAsync(new Passenger.GetByIdRequest { Id = command.PassengerId.ToString() }, cancellationToken: cancellationToken);
|
await _passengerGrpcServiceClient.GetByIdAsync(new BookingPassenger.GetByIdRequest { Id = command.PassengerId.ToString() }, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
var emptySeat = (await _flightGrpcServiceClient
|
var emptySeat = (await _flightGrpcServiceClient
|
||||||
.GetAvailableSeatsAsync(new GetAvailableSeatsRequest { FlightId = command.FlightId.ToString() }, cancellationToken: cancellationToken)
|
.GetAvailableSeatsAsync(new GetAvailableSeatsRequest { FlightId = command.FlightId.ToString() }, cancellationToken: cancellationToken)
|
||||||
|
|||||||
@ -2,7 +2,7 @@ using Booking.Configuration;
|
|||||||
using BookingFlight;
|
using BookingFlight;
|
||||||
using BuildingBlocks.Web;
|
using BuildingBlocks.Web;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Passenger;
|
using BookingPassenger;
|
||||||
|
|
||||||
namespace Booking.Extensions.Infrastructure;
|
namespace Booking.Extensions.Infrastructure;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package passenger;
|
package bookingPassenger;
|
||||||
|
|
||||||
service PassengerGrpcService {
|
service PassengerGrpcService {
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Api;
|
||||||
|
using Booking.Data;
|
||||||
|
using BuildingBlocks.Contracts.EventBus.Messages;
|
||||||
|
using BuildingBlocks.TestBase;
|
||||||
|
using BookingFlight;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Grpc.Core.Testing;
|
||||||
|
using Integration.Test.Fakes;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
using NSubstitute;
|
||||||
|
using BookingPassenger;
|
||||||
|
using Xunit;
|
||||||
|
using GetByIdRequest = BookingFlight.GetByIdRequest;
|
||||||
|
|
||||||
|
namespace Integration.Test.Booking.Features
|
||||||
|
{
|
||||||
|
public class CreateBookingTests : BookingIntegrationTestBase
|
||||||
|
{
|
||||||
|
public CreateBookingTests(TestReadFixture<Program, BookingReadDbContext> integrationTestFixture) : base(
|
||||||
|
integrationTestFixture)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RegisterTestsServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
MockFlightGrpcServices(services);
|
||||||
|
MockPassengerGrpcServices(services);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task should_create_booking_to_event_store_currectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var command = new FakeCreateBookingCommand().Generate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Fixture.SendAsync(command);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
response?.Id.Should().BeGreaterOrEqualTo(0);
|
||||||
|
|
||||||
|
(await Fixture.WaitForPublishing<BookingCreated>()).Should().Be(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void MockPassengerGrpcServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.Replace(ServiceDescriptor.Singleton(x =>
|
||||||
|
{
|
||||||
|
var mockPassenger = Substitute.For<PassengerGrpcService.PassengerGrpcServiceClient>();
|
||||||
|
|
||||||
|
mockPassenger.GetByIdAsync(Arg.Any<BookingPassenger.GetByIdRequest>())
|
||||||
|
.Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakePassengerResponse.Generate()),
|
||||||
|
Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }));
|
||||||
|
|
||||||
|
return mockPassenger;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MockFlightGrpcServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.Replace(ServiceDescriptor.Singleton(x =>
|
||||||
|
{
|
||||||
|
var mockFlight = Substitute.For<FlightGrpcService.FlightGrpcServiceClient>();
|
||||||
|
|
||||||
|
mockFlight.GetByIdAsync(Arg.Any<GetByIdRequest>())
|
||||||
|
.Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakeFlightResponse.Generate()),
|
||||||
|
Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }));
|
||||||
|
|
||||||
|
mockFlight.GetAvailableSeatsAsync(Arg.Any<GetAvailableSeatsRequest>())
|
||||||
|
.Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakeGetAvailableSeatsResponse.Generate()),
|
||||||
|
Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }));
|
||||||
|
|
||||||
|
mockFlight.ReserveSeatAsync(Arg.Any<ReserveSeatRequest>())
|
||||||
|
.Returns(TestCalls.AsyncUnaryCall(Task.FromResult(FakeReserveSeatResponse.Generate()),
|
||||||
|
Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }));
|
||||||
|
|
||||||
|
return mockFlight;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
using Api;
|
||||||
|
using Booking.Data;
|
||||||
|
using BuildingBlocks.TestBase;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Integration.Test;
|
||||||
|
|
||||||
|
[Collection(IntegrationTestCollection.Name)]
|
||||||
|
public class BookingIntegrationTestBase : TestReadBase<Program, BookingReadDbContext>
|
||||||
|
{
|
||||||
|
public BookingIntegrationTestBase(TestReadFixture<Program, BookingReadDbContext> integrationTestFixture) : base(integrationTestFixture)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CollectionDefinition(Name)]
|
||||||
|
public class IntegrationTestCollection : ICollectionFixture<TestReadFixture<Program, BookingReadDbContext>>
|
||||||
|
{
|
||||||
|
public const string Name = "Booking Integration Test";
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using AutoBogus;
|
||||||
|
|
||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using global::Booking.Booking.Features.CreatingBook.V1;
|
||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
public sealed class FakeCreateBookingCommand : AutoFaker<CreateBooking>
|
||||||
|
{
|
||||||
|
public FakeCreateBookingCommand()
|
||||||
|
{
|
||||||
|
RuleFor(r => r.Id, _ => NewId.NextGuid());
|
||||||
|
RuleFor(r => r.FlightId, _ => new Guid("3c5c0000-97c6-fc34-2eb9-08db322230c9"));
|
||||||
|
RuleFor(r => r.PassengerId, _ => new Guid("4c5c8888-97c6-fc34-2eb9-18db322230c1"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using AutoBogus;
|
||||||
|
using BookingFlight;
|
||||||
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
|
||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
public static class FakeFlightResponse
|
||||||
|
{
|
||||||
|
public static GetFlightByIdResult Generate()
|
||||||
|
{
|
||||||
|
var flightMock = new GetFlightByIdResult
|
||||||
|
{
|
||||||
|
FlightDto = new FlightResponse
|
||||||
|
{
|
||||||
|
Id = new Guid("3c5c0000-97c6-fc34-2eb9-08db322230c9").ToString(),
|
||||||
|
Price = 100,
|
||||||
|
Status = FlightStatus.Completed,
|
||||||
|
AircraftId = new Guid("3c5c0000-97c6-fc34-fcd3-08db322230c8").ToString(),
|
||||||
|
ArriveAirportId = new Guid("3c5c0000-97c6-fc34-a0cb-08db322230c8").ToString(),
|
||||||
|
ArriveDate = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc).ToTimestamp(),
|
||||||
|
DepartureDate = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc).ToTimestamp(),
|
||||||
|
FlightDate = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc).ToTimestamp(),
|
||||||
|
FlightNumber = "1500B",
|
||||||
|
DepartureAirportId = new Guid("3c5c0000-97c6-fc34-fc3c-08db322230c8").ToString()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return flightMock;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using BookingFlight;
|
||||||
|
|
||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
public static class FakeGetAvailableSeatsResponse
|
||||||
|
{
|
||||||
|
public static GetAvailableSeatsResult Generate()
|
||||||
|
{
|
||||||
|
var result = new GetAvailableSeatsResult();
|
||||||
|
result.SeatDtos.AddRange(new List<SeatDtoResponse>
|
||||||
|
{
|
||||||
|
new SeatDtoResponse()
|
||||||
|
{
|
||||||
|
FlightId = new Guid("3c5c0000-97c6-fc34-2eb9-08db322230c9").ToString(),
|
||||||
|
Class = SeatClass.Economy,
|
||||||
|
Type = SeatType.Aisle,
|
||||||
|
SeatNumber = "33F",
|
||||||
|
Id = NewId.NextGuid().ToString()
|
||||||
|
},
|
||||||
|
new SeatDtoResponse()
|
||||||
|
{
|
||||||
|
FlightId = new Guid("3c5c0000-97c6-fc34-2eb9-08db322230c9").ToString(),
|
||||||
|
Class = SeatClass.Economy,
|
||||||
|
Type = SeatType.Window,
|
||||||
|
SeatNumber = "22D",
|
||||||
|
Id = NewId.NextGuid().ToString()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
using MassTransit;
|
||||||
|
using BookingPassenger;
|
||||||
|
|
||||||
|
public static class FakePassengerResponse
|
||||||
|
{
|
||||||
|
public static GetPassengerByIdResult Generate()
|
||||||
|
{
|
||||||
|
var result = new GetPassengerByIdResult
|
||||||
|
{
|
||||||
|
PassengerDto = new PassengerResponse()
|
||||||
|
{
|
||||||
|
Id = NewId.NextGuid().ToString(),
|
||||||
|
Name = "Test",
|
||||||
|
PassportNumber = "121618"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
using BookingFlight;
|
||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
public static class FakeReserveSeatResponse
|
||||||
|
{
|
||||||
|
public static ReserveSeatResult Generate()
|
||||||
|
{
|
||||||
|
var result = new ReserveSeatResult();
|
||||||
|
result.Id = NewId.NextGuid().ToString();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="xunit.runner.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Api\src\Api.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"parallelizeAssembly": false,
|
||||||
|
"parallelizeTestCollections": false
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.35906.104 d17.14
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "Integration.Test\Integration.Test.csproj", "{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {BF30A2EF-A06D-4A7E-B99B-304221C5FC0C}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
using AutoBogus;
|
||||||
|
|
||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
using global::Identity.Identity.Features.RegisteringNewUser.V1;
|
||||||
|
|
||||||
|
public class FakeRegisterNewUserCommand : AutoFaker<RegisterNewUser>
|
||||||
|
{
|
||||||
|
public FakeRegisterNewUserCommand()
|
||||||
|
{
|
||||||
|
RuleFor(r => r.Username, x => "TestMyUser");
|
||||||
|
RuleFor(r => r.Password, _ => "Password@123");
|
||||||
|
RuleFor(r => r.ConfirmPassword, _ => "Password@123");
|
||||||
|
RuleFor(r => r.Email, _ => "test@test.com");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using BuildingBlocks.Contracts.EventBus.Messages;
|
||||||
|
using BuildingBlocks.TestBase;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Api;
|
||||||
|
using Identity.Data;
|
||||||
|
using Integration.Test.Fakes;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Integration.Test.Identity.Features;
|
||||||
|
|
||||||
|
public class RegisterNewUserTests : IdentityIntegrationTestBase
|
||||||
|
{
|
||||||
|
public RegisterNewUserTests(
|
||||||
|
TestWriteFixture<Program, IdentityContext> integrationTestFactory) : base(integrationTestFactory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task should_create_new_user_to_db_and_publish_message_to_broker()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var command = new FakeRegisterNewUserCommand().Generate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Fixture.SendAsync(command);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
response?.Should().NotBeNull();
|
||||||
|
response?.Username.Should().Be(command.Username);
|
||||||
|
|
||||||
|
(await Fixture.WaitForPublishing<UserCreated>()).Should().Be(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
using BuildingBlocks.TestBase;
|
||||||
|
using Api;
|
||||||
|
using Identity.Data;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Integration.Test;
|
||||||
|
|
||||||
|
[Collection(IntegrationTestCollection.Name)]
|
||||||
|
public class IdentityIntegrationTestBase : TestWriteBase<Program, IdentityContext>
|
||||||
|
{
|
||||||
|
public IdentityIntegrationTestBase(TestWriteFixture<Program, IdentityContext> integrationTestFactory)
|
||||||
|
: base(integrationTestFactory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CollectionDefinition(Name)]
|
||||||
|
public class IntegrationTestCollection : ICollectionFixture<TestWriteFixture<Program, IdentityContext>>
|
||||||
|
{
|
||||||
|
public const string Name = "Identity Integration Test";
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
using BuildingBlocks.Constants;
|
||||||
|
using BuildingBlocks.Contracts.EventBus.Messages;
|
||||||
|
using BuildingBlocks.Core;
|
||||||
|
using BuildingBlocks.EFCore;
|
||||||
|
using Identity.Data.Seed;
|
||||||
|
using Identity.Identity.Constants;
|
||||||
|
using Identity.Identity.Models;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|
||||||
|
namespace Integration.Test;
|
||||||
|
|
||||||
|
public class IdentityTestDataSeeder(
|
||||||
|
UserManager<User> userManager,
|
||||||
|
RoleManager<Role> roleManager,
|
||||||
|
IEventDispatcher eventDispatcher
|
||||||
|
)
|
||||||
|
: ITestDataSeeder
|
||||||
|
{
|
||||||
|
public async Task SeedAllAsync()
|
||||||
|
{
|
||||||
|
await SeedRoles();
|
||||||
|
await SeedUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SeedRoles()
|
||||||
|
{
|
||||||
|
if (await roleManager.RoleExistsAsync(IdentityConstant.Role.Admin) == false)
|
||||||
|
{
|
||||||
|
await roleManager.CreateAsync(new Role { Name = IdentityConstant.Role.Admin });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await roleManager.RoleExistsAsync(IdentityConstant.Role.User) == false)
|
||||||
|
{
|
||||||
|
await roleManager.CreateAsync(new Role { Name = IdentityConstant.Role.User });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SeedUsers()
|
||||||
|
{
|
||||||
|
if (await userManager.FindByNameAsync("samh") == null)
|
||||||
|
{
|
||||||
|
var result = await userManager.CreateAsync(InitialData.Users.First(), "Admin@123456");
|
||||||
|
|
||||||
|
if (result.Succeeded)
|
||||||
|
{
|
||||||
|
await userManager.AddToRoleAsync(InitialData.Users.First(), IdentityConstant.Role.Admin);
|
||||||
|
|
||||||
|
await eventDispatcher.SendAsync(new UserCreated(InitialData.Users.First().Id, InitialData.Users.First().FirstName + " " + InitialData.Users.First().LastName, InitialData.Users.First().PassPortNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await userManager.FindByNameAsync("meysamh2") == null)
|
||||||
|
{
|
||||||
|
var result = await userManager.CreateAsync(InitialData.Users.Last(), "User@123456");
|
||||||
|
|
||||||
|
if (result.Succeeded)
|
||||||
|
{
|
||||||
|
await userManager.AddToRoleAsync(InitialData.Users.Last(), IdentityConstant.Role.User);
|
||||||
|
|
||||||
|
await eventDispatcher.SendAsync(new UserCreated(InitialData.Users.Last().Id, InitialData.Users.Last().FirstName + " " + InitialData.Users.Last().LastName, InitialData.Users.Last().PassPortNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="xunit.runner.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Api\src\Api.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"parallelizeAssembly": false,
|
||||||
|
"parallelizeTestCollections": false
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.35906.104 d17.14
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "Integration.Test\Integration.Test.csproj", "{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {BF30A2EF-A06D-4A7E-B99B-304221C5FC0C}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
using AutoBogus;
|
||||||
|
using Passenger.Passengers.Enums;
|
||||||
|
|
||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
using global::Passenger.Passengers.Features.CompletingRegisterPassenger.V1;
|
||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
public sealed class FakeCompleteRegisterPassengerCommand : AutoFaker<CompleteRegisterPassenger>
|
||||||
|
{
|
||||||
|
public FakeCompleteRegisterPassengerCommand(string passportNumber)
|
||||||
|
{
|
||||||
|
RuleFor(r => r.Id, _ => NewId.NextGuid());
|
||||||
|
RuleFor(r => r.PassportNumber, _ => passportNumber);
|
||||||
|
RuleFor(r => r.PassengerType, _ => PassengerType.Male);
|
||||||
|
RuleFor(r => r.Age, _ => 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
using AutoBogus;
|
||||||
|
using global::Passenger.Passengers.Enums;
|
||||||
|
using global::Passenger.Passengers.Features.CompletingRegisterPassenger.V1;
|
||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
public class FakeCompleteRegisterPassengerMongoCommand : AutoFaker<CompleteRegisterPassengerMongoCommand>
|
||||||
|
{
|
||||||
|
public FakeCompleteRegisterPassengerMongoCommand()
|
||||||
|
{
|
||||||
|
RuleFor(r => r.Id, _ => NewId.NextGuid());
|
||||||
|
RuleFor(r => r.Name, _ => "Sam");
|
||||||
|
RuleFor(r => r.PassportNumber, _ => "123456789");
|
||||||
|
RuleFor(r => r.Age, _ => 30);
|
||||||
|
RuleFor(r => r.IsDeleted, _ => false);
|
||||||
|
RuleFor(r => r.PassengerType, _ => PassengerType.Male);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
using AutoBogus;
|
||||||
|
using BuildingBlocks.Contracts.EventBus.Messages;
|
||||||
|
|
||||||
|
namespace Integration.Test.Fakes;
|
||||||
|
|
||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
public class FakeUserCreated : AutoFaker<UserCreated>
|
||||||
|
{
|
||||||
|
public FakeUserCreated()
|
||||||
|
{
|
||||||
|
RuleFor(r => r.Id, _ => NewId.NextGuid());
|
||||||
|
RuleFor(r => r.Name, _ => "Sam");
|
||||||
|
RuleFor(r => r.PassportNumber, _ => "123456789");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="xunit.runner.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Api\src\Api.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using BuildingBlocks.Contracts.EventBus.Messages;
|
||||||
|
using BuildingBlocks.TestBase;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Integration.Test.Fakes;
|
||||||
|
using Api;
|
||||||
|
using Passenger.Data;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Integration.Test.Passenger.Features;
|
||||||
|
public class CompleteRegisterPassengerTests : PassengerIntegrationTestBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public CompleteRegisterPassengerTests(
|
||||||
|
TestFixture<Program, PassengerDbContext, PassengerReadDbContext> integrationTestFactory) : base(integrationTestFactory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task should_complete_register_passenger_and_update_to_db()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var userCreated = new FakeUserCreated().Generate();
|
||||||
|
|
||||||
|
await Fixture.Publish(userCreated);
|
||||||
|
(await Fixture.WaitForPublishing<UserCreated>()).Should().Be(true);
|
||||||
|
(await Fixture.WaitForConsuming<UserCreated>()).Should().Be(true);
|
||||||
|
|
||||||
|
var command = new FakeCompleteRegisterPassengerCommand(userCreated.PassportNumber).Generate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Fixture.SendAsync(command);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
response.Should().NotBeNull();
|
||||||
|
response?.PassengerDto?.Name.Should().Be(userCreated.Name);
|
||||||
|
response?.PassengerDto?.PassportNumber.Should().Be(command.PassportNumber);
|
||||||
|
response?.PassengerDto?.PassengerType.ToString().Should().Be(command.PassengerType.ToString());
|
||||||
|
response?.PassengerDto?.Age.Should().Be(command.Age);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using BuildingBlocks.TestBase;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Integration.Test.Fakes;
|
||||||
|
using Passenger;
|
||||||
|
using Api;
|
||||||
|
using Passenger.Data;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Integration.Test.Passenger.Features;
|
||||||
|
|
||||||
|
using global::Passenger.Passengers.Features.GettingPassengerById.V1;
|
||||||
|
|
||||||
|
public class GetPassengerByIdTests : PassengerIntegrationTestBase
|
||||||
|
{
|
||||||
|
public GetPassengerByIdTests(
|
||||||
|
TestFixture<Program, PassengerDbContext, PassengerReadDbContext> integrationTestFactory) : base(integrationTestFactory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task should_retrive_a_passenger_by_id_currectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var command = new FakeCompleteRegisterPassengerMongoCommand().Generate();
|
||||||
|
|
||||||
|
await Fixture.SendAsync(command);
|
||||||
|
|
||||||
|
var query = new GetPassengerById(command.Id);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Fixture.SendAsync(query);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
response.Should().NotBeNull();
|
||||||
|
response?.PassengerDto?.Id.Should().Be(command.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task should_retrive_a_passenger_by_id_from_grpc_service()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var command = new FakeCompleteRegisterPassengerMongoCommand().Generate();
|
||||||
|
|
||||||
|
await Fixture.SendAsync(command);
|
||||||
|
|
||||||
|
var passengerGrpcClient = new PassengerGrpcService.PassengerGrpcServiceClient(Fixture.Channel);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await passengerGrpcClient.GetByIdAsync(new GetByIdRequest { Id = command.Id.ToString() });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
response?.Should().NotBeNull();
|
||||||
|
response?.PassengerDto?.Id.Should().Be(command.Id.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
using BuildingBlocks.TestBase;
|
||||||
|
using Api;
|
||||||
|
using Passenger.Data;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Integration.Test;
|
||||||
|
|
||||||
|
[Collection(IntegrationTestCollection.Name)]
|
||||||
|
public class PassengerIntegrationTestBase : TestBase<Program, PassengerDbContext, PassengerReadDbContext>
|
||||||
|
{
|
||||||
|
public PassengerIntegrationTestBase(TestFixture<Program, PassengerDbContext, PassengerReadDbContext> integrationTestFactory)
|
||||||
|
: base(integrationTestFactory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CollectionDefinition(Name)]
|
||||||
|
public class IntegrationTestCollection : ICollectionFixture<TestFixture<Program, PassengerDbContext, PassengerReadDbContext>>
|
||||||
|
{
|
||||||
|
public const string Name = "Passenger Integration Test";
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"parallelizeAssembly": false,
|
||||||
|
"parallelizeTestCollections": false
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.35906.104 d17.14
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "Integration.Test\Integration.Test.csproj", "{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A0D4B2AE-53E4-454D-A1CB-E51168D016F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {BF30A2EF-A06D-4A7E-B99B-304221C5FC0C}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@ -111,6 +111,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "2-modul
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndToEnd.Test", "2-modular-monolith-architecture-style\src\Modules\Flight\tests\EndToEnd.Test\EndToEnd.Test.csproj", "{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndToEnd.Test", "2-modular-monolith-architecture-style\src\Modules\Flight\tests\EndToEnd.Test\EndToEnd.Test.csproj", "{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Booking", "Booking", "{5DE68C42-13B1-44D0-B966-7EE083B9B2B5}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "2-modular-monolith-architecture-style\src\Modules\Booking\tests\Integration.Test\Integration.Test.csproj", "{A23A47DB-7C4B-411C-9078-AE567407FEB1}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{F59A33C1-6197-4F76-82BF-D7F2CC9D6438}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "2-modular-monolith-architecture-style\src\Modules\Identity\tests\Integration.Test\Integration.Test.csproj", "{39DE2739-1426-2288-DF5D-B58D339E5CDE}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Passenger", "Passenger", "{687C40B6-F05C-4794-981D-5DA28C07E3D2}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "2-modular-monolith-architecture-style\src\Modules\Passenger\tests\Integration.Test\Integration.Test.csproj", "{87AE85AA-A092-2130-C912-97B9B252845A}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -221,6 +233,18 @@ Global
|
|||||||
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A23A47DB-7C4B-411C-9078-AE567407FEB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A23A47DB-7C4B-411C-9078-AE567407FEB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A23A47DB-7C4B-411C-9078-AE567407FEB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A23A47DB-7C4B-411C-9078-AE567407FEB1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{39DE2739-1426-2288-DF5D-B58D339E5CDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{39DE2739-1426-2288-DF5D-B58D339E5CDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{39DE2739-1426-2288-DF5D-B58D339E5CDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{39DE2739-1426-2288-DF5D-B58D339E5CDE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{87AE85AA-A092-2130-C912-97B9B252845A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{87AE85AA-A092-2130-C912-97B9B252845A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{87AE85AA-A092-2130-C912-97B9B252845A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{87AE85AA-A092-2130-C912-97B9B252845A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -276,6 +300,12 @@ Global
|
|||||||
{E7B7E65D-DB14-494C-A748-EF90666FB0B1} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
{E7B7E65D-DB14-494C-A748-EF90666FB0B1} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||||
{AE7E4AE8-4A5C-44AE-B1FC-2A04824EE29B} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
{AE7E4AE8-4A5C-44AE-B1FC-2A04824EE29B} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||||
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
{7CBA4E35-64EA-BFB3-0507-B7DE1E60CD54} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||||
|
{5DE68C42-13B1-44D0-B966-7EE083B9B2B5} = {AD2FB7C1-8641-47E9-B62D-B3A2D74147D8}
|
||||||
|
{A23A47DB-7C4B-411C-9078-AE567407FEB1} = {5DE68C42-13B1-44D0-B966-7EE083B9B2B5}
|
||||||
|
{F59A33C1-6197-4F76-82BF-D7F2CC9D6438} = {AD2FB7C1-8641-47E9-B62D-B3A2D74147D8}
|
||||||
|
{39DE2739-1426-2288-DF5D-B58D339E5CDE} = {F59A33C1-6197-4F76-82BF-D7F2CC9D6438}
|
||||||
|
{687C40B6-F05C-4794-981D-5DA28C07E3D2} = {AD2FB7C1-8641-47E9-B62D-B3A2D74147D8}
|
||||||
|
{87AE85AA-A092-2130-C912-97B9B252845A} = {687C40B6-F05C-4794-981D-5DA28C07E3D2}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {BF29DFD4-25EC-44C4-9DA6-E3AC4B292257}
|
SolutionGuid = {BF29DFD4-25EC-44C4-9DA6-E3AC4B292257}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user