Skip to content

Commit

Permalink
Merge branch 'Richard87-issue-478-bugfix'
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydmiller committed Jul 21, 2023
2 parents 46d8331 + 128d965 commit ca99ea8
Show file tree
Hide file tree
Showing 18 changed files with 257 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<NoWarn>1570;1571;1572;1573;1574;1587;1591;1701;1702;1711;1735;0618</NoWarn>
<ImplicitUsings>true</ImplicitUsings>
<Version>1.2.0</Version>
<Version>1.2.1</Version>
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ public static WolverineOptions UseFluentValidation(this WolverineOptions options
options.Services.Policies.Add<ValidatorLifetimePolicy>();
options.Services.AddSingleton(typeof(IFailureAction<>), typeof(FailureAction<>));

if (behavior == RegistrationBehavior.DiscoverAndRegisterValidators)
options.ConfigureLazily(o =>
{
options.Services.Scan(x =>
if (behavior == RegistrationBehavior.DiscoverAndRegisterValidators)
{
foreach (var assembly in options.Assemblies) x.Assembly(assembly);

x.ConnectImplementationsToTypesClosing(typeof(IValidator<>));
});
}
options.Services.Scan(x =>
{
foreach (var assembly in options.Assemblies) x.Assembly(assembly);

x.ConnectImplementationsToTypesClosing(typeof(IValidator<>));
});
}
});

options.OnException<ValidationException>().Discard();
options.Policies.Add<FluentValidationPolicy>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using FluentValidation;

namespace Wolverine.Http.Tests.DifferentAssembly.Validation;

public class Validated2Endpoint
{
[WolverinePost("/validate2/customer")]
public static string Post(CreateCustomer2 customer)
{
return "Got a new customer";
}

[WolverinePost("/validate2/user")]
public static string Post(CreateUser2 user)
{
return "Got a new user";
}
}

public record CreateCustomer2
(
string FirstName,
string LastName,
string PostalCode
)
{
public class CreateCustomerValidator : AbstractValidator<CreateCustomer2>
{
public CreateCustomerValidator()
{
RuleFor(x => x.FirstName).NotNull();
RuleFor(x => x.LastName).NotNull();
RuleFor(x => x.PostalCode).NotNull();
}
}
}

public record CreateUser2
(
string FirstName,
string LastName,
string PostalCode,
string Password
)
{
public class CreateUserValidator : AbstractValidator<CreateUser2>
{
public CreateUserValidator()
{
RuleFor(x => x.FirstName).NotNull();
RuleFor(x => x.LastName).NotNull();
RuleFor(x => x.PostalCode).NotNull();
}
}

public class PasswordValidator : AbstractValidator<CreateUser2>
{
public PasswordValidator()
{
RuleFor(x => x.Password).Length(8);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Wolverine.Http\Wolverine.Http.csproj" />
<ProjectReference Include="..\Wolverine.Http.FluentValidation\Wolverine.Http.FluentValidation.csproj" />
</ItemGroup>

</Project>
15 changes: 14 additions & 1 deletion src/Http/Wolverine.Http.Tests/IntegrationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,20 @@ protected IntegrationContext(AppFixture fixture)
public HttpGraph HttpChains => Host.Services.GetRequiredService<WolverineHttpOptions>().Endpoints!;

public IAlbaHost Host => _fixture.Host;
public IDocumentStore Store => _fixture.Host.Services.GetRequiredService<IDocumentStore>();

public IDocumentStore Store
{
get
{
var store = _fixture.Host.Services.GetRequiredService<IDocumentStore>();
if (store == null)
{
_fixture.ResetHost().GetAwaiter().GetResult();
}

return _fixture.Host.Services.GetRequiredService<IDocumentStore>();
}
}

async Task IAsyncLifetime.InitializeAsync()
{
Expand Down
1 change: 1 addition & 0 deletions src/Http/Wolverine.Http.Tests/Wolverine.Http.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<ItemGroup>
<ProjectReference Include="..\..\Persistence\Wolverine.Marten\Wolverine.Marten.csproj" />
<ProjectReference Include="..\..\Testing\TestingSupport\TestingSupport.csproj" />
<ProjectReference Include="..\Wolverine.Http.Tests.DifferentAssembly\Wolverine.Http.Tests.DifferentAssembly.csproj" />
<ProjectReference Include="..\Wolverine.Http\Wolverine.Http.csproj" />
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<ProjectReference Include="..\WolverineWebApi\WolverineWebApi.csproj" />
Expand Down
17 changes: 17 additions & 0 deletions src/Http/Wolverine.Http.Tests/fluent_validation_middleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Alba;
using Microsoft.AspNetCore.Mvc;
using Shouldly;
using Wolverine.Http.Tests.DifferentAssembly.Validation;
using WolverineWebApi.Validation;

namespace Wolverine.Http.Tests;
Expand Down Expand Up @@ -41,6 +42,22 @@ public async Task one_validator_sad_path()
// in the request
var problems = results.ReadAsJson<ProblemDetails>();
}
[Fact]
public async Task one_validator_sad_path_in_different_assembly()
{
var createCustomer = new CreateCustomer2(null, "Humphrey", "11111");

var results = await Scenario(x =>
{
x.Post.Json(createCustomer).ToUrl("/validate2/customer");
x.ContentTypeShouldBe("application/problem+json");
x.StatusCodeShouldBe(400);
});

// Just proving that we have ProblemDetails content
// in the request
var problems = results.ReadAsJson<ProblemDetails>();
}

[Fact]
public async Task two_validator_happy_path()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// <auto-generated/>
#pragma warning disable
using FluentValidation;
using Microsoft.AspNetCore.Routing;
using System;
using System.Linq;
using Wolverine.Http;
using Wolverine.Http.FluentValidation;

namespace Internal.Generated.WolverineHandlers
{
// START: POST_validate2_customer
public class POST_validate2_customer : Wolverine.Http.HttpHandler
{
private readonly Wolverine.Http.WolverineHttpOptions _wolverineHttpOptions;
private readonly Wolverine.Http.FluentValidation.IProblemDetailSource<Wolverine.Http.Tests.DifferentAssembly.Validation.CreateCustomer2> _problemDetailSource;
private readonly FluentValidation.IValidator<Wolverine.Http.Tests.DifferentAssembly.Validation.CreateCustomer2> _validator;

public POST_validate2_customer(Wolverine.Http.WolverineHttpOptions wolverineHttpOptions, Wolverine.Http.FluentValidation.IProblemDetailSource<Wolverine.Http.Tests.DifferentAssembly.Validation.CreateCustomer2> problemDetailSource, FluentValidation.IValidator<Wolverine.Http.Tests.DifferentAssembly.Validation.CreateCustomer2> validator) : base(wolverineHttpOptions)
{
_wolverineHttpOptions = wolverineHttpOptions;
_problemDetailSource = problemDetailSource;
_validator = validator;
}



public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext)
{
var (customer, jsonContinue) = await ReadJsonAsync<Wolverine.Http.Tests.DifferentAssembly.Validation.CreateCustomer2>(httpContext);
if (jsonContinue == Wolverine.HandlerContinuation.Stop) return;
var result1 = await Wolverine.Http.FluentValidation.Internals.FluentValidationHttpExecutor.ExecuteOne<Wolverine.Http.Tests.DifferentAssembly.Validation.CreateCustomer2>(_validator, _problemDetailSource, customer).ConfigureAwait(false);
if (!(result1 is Wolverine.Http.WolverineContinue))
{
await result1.ExecuteAsync(httpContext).ConfigureAwait(false);
return;
}

var result_of_Post = Wolverine.Http.Tests.DifferentAssembly.Validation.Validated2Endpoint.Post(customer);
await WriteString(httpContext, result_of_Post);
}

}

// END: POST_validate2_customer


}

3 changes: 3 additions & 0 deletions src/Http/WolverineWebApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Wolverine.FluentValidation;
using Wolverine.Http;
using Wolverine.Http.FluentValidation;
using Wolverine.Http.Tests.DifferentAssembly.Validation;
using Wolverine.Marten;
using WolverineWebApi;
using WolverineWebApi.Marten;
Expand Down Expand Up @@ -55,10 +56,12 @@
opts.Policies.AutoApplyTransactions();

opts.UseFluentValidation();
opts.Discovery.IncludeAssembly(typeof(CreateCustomer2).Assembly);

opts.OptimizeArtifactWorkflow();

opts.Policies.Add<BroadcastClientMessages>();

});

var app = builder.Build();
Expand Down
1 change: 1 addition & 0 deletions src/Http/WolverineWebApi/WolverineWebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<ProjectReference Include="..\..\Persistence\Wolverine.EntityFrameworkCore\Wolverine.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\Persistence\Wolverine.Marten\Wolverine.Marten.csproj" />
<ProjectReference Include="..\Wolverine.Http.FluentValidation\Wolverine.Http.FluentValidation.csproj" />
<ProjectReference Include="..\Wolverine.Http.Tests.DifferentAssembly\Wolverine.Http.Tests.DifferentAssembly.csproj" />
<ProjectReference Include="..\Wolverine.Http\Wolverine.Http.csproj" />
</ItemGroup>

Expand Down
47 changes: 47 additions & 0 deletions src/Testing/CoreTests/Acceptance/middleware_usage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,21 @@ public async Task use_attributes_to_explicitly_opt_into_implied_middleware()
"Back on Defense"
);
}

[Fact]
public async Task use_implied_middleware_that_is_inner_type()
{
var list = await invokeMessage(new SnapBall("Go!"), x =>
{
x.AddMiddleware<MiddlewareWrapper.FootballMiddleware>();
});

list.ShouldHaveTheSameElementsAs(
"Line up",
"Snap Ball",
"Score touchdown"
);
}
}

public class MiddlewareActivity
Expand Down Expand Up @@ -633,6 +648,8 @@ public void Handle(StrikeoutsMessage message, Recorder recorder)

public record JumpBall(string Name);

public record SnapBall(string Name);

public class BasketballHandler
{
[WolverineBefore]
Expand All @@ -652,4 +669,34 @@ public static void BackOnDefense(Recorder recorder)
recorder.Actions.Add("Back on Defense");
}

}

public class FootballHandler
{

public static void Handle(SnapBall command, Recorder recorder)
{
recorder.Actions.Add("Snap Ball");
}


}

public class MiddlewareWrapper
{
public class FootballMiddleware
{
[WolverineBefore]
public static void LineUp(Recorder recorder)
{
recorder.Actions.Add("Line up");
}

[WolverineAfter]
public static void BackOnDefense(Recorder recorder)
{
recorder.Actions.Add("Score touchdown");
}

}
}
50 changes: 4 additions & 46 deletions src/Testing/CoreTests/Tracking/TrackedSessionTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,19 @@ public void Dispose()
_host?.Dispose();
}

[Fact]
public async Task throw_if_any_exceptions_happy_path()
{
theSession.Record(MessageEventType.Sent, theEnvelope, "", Guid.NewGuid());
await theSession.TrackAsync();
theSession.AssertNoExceptionsWereThrown();
}

[Fact]
public async Task throw_if_any_exceptions_sad_path()
{
var guid = Guid.NewGuid();
theSession.Record(MessageEventType.ExecutionStarted, theEnvelope, "", guid);
theSession.Record(MessageEventType.ExecutionFinished, theEnvelope, "", guid, new DivideByZeroException());
await theSession.TrackAsync();

Should.Throw<AggregateException>(() => theSession.AssertNoExceptionsWereThrown());
}

[Fact]
public async Task throw_if_any_exceptions_and_completed_happy_path()
{
var guid = Guid.NewGuid();
theSession.Record(MessageEventType.ExecutionStarted, theEnvelope, "", guid);
theSession.Record(MessageEventType.ExecutionFinished, theEnvelope, "", guid);
await theSession.TrackAsync();
theSession.AssertNoExceptionsWereThrown();
theSession.AssertNotTimedOut();
}

[Fact]
public async Task throw_if_any_exceptions_and_completed_sad_path_with_exceptions()
{
var guid = Guid.NewGuid();
theSession.Record(MessageEventType.ExecutionStarted, theEnvelope, "", guid);
theSession.Record(MessageEventType.ExecutionFinished, theEnvelope, "", guid, new DivideByZeroException());
await theSession.TrackAsync();


Should.Throw<AggregateException>(() =>
await Should.ThrowAsync<AggregateException>(async () =>
{
theSession.AssertNoExceptionsWereThrown();
theSession.AssertNotTimedOut();
});
}

[Fact]
public async Task throw_if_any_exceptions_and_completed_sad_path_with_never_completed()
{
theSession.Record(MessageEventType.ExecutionStarted, theEnvelope, "", Guid.NewGuid());
await theSession.TrackAsync();
await theSession.TrackAsync();

Should.Throw<TimeoutException>(() =>
{
theSession.AssertNoExceptionsWereThrown();
theSession.AssertNotTimedOut();
});
}

}
Loading

0 comments on commit ca99ea8

Please sign in to comment.