Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions Internal/Xcepto.Internal.Http/Builders/HttpStateBuilder.T.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
Expand All @@ -18,10 +19,10 @@ public abstract class HttpStateBuilderIdentity<TBuilder> : AbstractStateBuilderI
{

protected Func<HttpClient> ClientProducer = () => new();
protected Uri BaseUrl = new("http://localhost:8080");
protected Func<Uri> BaseUrl = () => new("http://localhost:8080");
protected HttpMethodVerb MethodVerb = HttpMethodVerb.Get;
protected PathString PathString = "/";
protected readonly List<KeyValuePair<string, string>> QueryArgs = new();
protected Func<PathString> PathString = () => "/";
protected readonly List<Func<KeyValuePair<string, string>>> QueryArgs = new();
protected readonly List<HttpResponseAssertion> ResponseAssertions = new();

protected HttpStateBuilderIdentity(IStateMachineBuilder stateMachineBuilder, IStateBuilderIdentity stateBuilderIdentity) : base(stateMachineBuilder, stateBuilderIdentity) { }
Expand All @@ -47,15 +48,18 @@ protected override bool DefaultRetry
}


protected Uri Url
protected Func<Uri> Url
{
get
{
if (BaseUrl is null)
throw new BuilderException("no Url defined");
if (!Uri.TryCreate(BaseUrl, PathString + QueryString.Create(QueryArgs), out var uri))
throw new ArgumentException("Url creation failed");
return uri;
return () =>
{
if (!Uri.TryCreate(BaseUrl(), PathString() + QueryString.Create(QueryArgs.Select(x=> x())), out var uri))
throw new ArgumentException("Url creation failed");
return uri;
};
}
}

Expand All @@ -72,14 +76,26 @@ public TBuilder WithCustomClient(Func<HttpClient> clientProducer)
}

public TBuilder WithCustomBaseUrl(Uri uri)
{
BaseUrl = () => uri;
return (TBuilder)this;
}

public TBuilder WithCustomBaseUrl(Func<Uri> uri)
{
BaseUrl = uri;
return (TBuilder)this;
}

public TBuilder AddQueryArgument(string key, string value)
{
QueryArgs.Add(new KeyValuePair<string, string>(key, value));
QueryArgs.Add(() => new KeyValuePair<string, string>(key, value));
return (TBuilder)this;
}

public TBuilder AddQueryArgument(Func<KeyValuePair<string, string>> argument)
{
QueryArgs.Add(argument);
return (TBuilder)this;
}

Expand All @@ -91,7 +107,13 @@ public TBuilder WithHttpVerb(HttpMethodVerb verb)

public TBuilder WithPathString(PathString pathString)
{
PathString = pathString;
PathString = () => pathString;
return (TBuilder)this;
}

public TBuilder WithPathString(Func<PathString> pathStringPromise)
{
PathString = pathStringPromise;
return (TBuilder)this;
}

Expand Down
2 changes: 1 addition & 1 deletion Samples/RestAuth/Samples.Rest.API.Tests/BaseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Samples.Rest.API.Tests;

public class BaseTest
{
protected (string encoded, byte[] hashed) CreateToken()
protected static (string encoded, byte[] hashed) CreateToken()
{
byte[] bytes = new byte[32];
var randomNumberGenerator = RandomNumberGenerator.Create();
Expand Down
123 changes: 123 additions & 0 deletions Samples/RestAuth/Samples.Rest.API.Tests/PromisedPathTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System.Net;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using Samples.Rest.API.Requests;
using Samples.Rest.API.Responses;
using Samples.Rest.API.Tests.Scenarios;
using Xcepto;
using Xcepto.Config;
using Xcepto.NewtonsoftJson;
using Xcepto.Rest.Extensions;
using Xcepto.Scenarios;

namespace Samples.Rest.API.Tests;

[TestFixture]
public class PromisedPathTests: BaseTest
{
readonly TimeoutConfig _timeoutConfig = new TimeoutConfig(
TimeSpan.FromSeconds(60),
TimeSpan.FromSeconds(10)
);
private readonly MockedTokenScenario _scenario = new MockedTokenScenario(CreateToken().hashed);

[Test]
public async Task PromisedPathFromResponse_Get_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

var promiseResponse = rest.Get("/api/GetPath")
.WithResponseType<PathResponse>()
.AssertSuccess()
.PromiseResponse();

rest.Get(() => promiseResponse.Resolve().Path)
.AssertSuccess();
});
}

[Test]
public async Task PromisedPathFromResponse_Post_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

var promiseResponse = rest.Get("/api/PostPath")
.WithResponseType<PathResponse>()
.AssertSuccess()
.PromiseResponse();

rest.Post(() => promiseResponse.Resolve().Path)
.AssertSuccess();
});
}

[Test]
public async Task PromisedPathFromResponse_Patch_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

var promiseResponse = rest.Get("/api/PatchPath")
.WithResponseType<DynamicPathRequest>()
.AssertSuccess()
.PromiseResponse();

rest.Patch(() => promiseResponse.Resolve().Path)
.AssertSuccess();
});
}

[Test]
public async Task PromisedPathFromResponse_Put_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

var promiseResponse = rest.Get("/api/PutPath")
.WithResponseType<DynamicPathRequest>()
.AssertSuccess()
.PromiseResponse();

rest.Put(() => promiseResponse.Resolve().Path)
.AssertSuccess();
});
}

[Test]
public async Task PromisedPathFromResponse_Delete_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

var promiseResponse = rest.Get("/api/DeletePath")
.WithResponseType<DynamicPathRequest>()
.AssertSuccess()
.PromiseResponse();

rest.Delete(() => promiseResponse.Resolve().Path)
.AssertSuccess();
});
}
}
98 changes: 98 additions & 0 deletions Samples/RestAuth/Samples.Rest.API.Tests/StaticPathTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System.Net;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using Samples.Rest.API.Requests;
using Samples.Rest.API.Responses;
using Samples.Rest.API.Tests.Scenarios;
using Xcepto;
using Xcepto.Config;
using Xcepto.NewtonsoftJson;
using Xcepto.Rest.Extensions;
using Xcepto.Scenarios;

namespace Samples.Rest.API.Tests;

[TestFixture]
public class StaticPathTests: BaseTest
{
readonly TimeoutConfig _timeoutConfig = new TimeoutConfig(
TimeSpan.FromSeconds(60),
TimeSpan.FromSeconds(10)
);
private readonly MockedTokenScenario _scenario = new MockedTokenScenario(CreateToken().hashed);

[Test]
public async Task StaticPath_Get_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

rest.Get("/api/GetPath/validate")
.AssertSuccess();
});
}

[Test]
public async Task StaticPath_Post_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

rest.Post("/api/PostPath/validate")
.AssertSuccess();
});
}

[Test]
public async Task StaticPath_Patch_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

rest.Patch("/api/PatchPath/validate")
.AssertSuccess();
});
}

[Test]
public async Task StaticPath_Put_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

rest.Put("/api/PutPath/validate")
.AssertSuccess();
});
}

[Test]
public async Task StaticPath_Delete_Works()
{
await XceptoTest.Given(_scenario, _timeoutConfig, builder =>
{
var rest = builder.RestAdapterBuilder()
.WithBaseUrl(new Uri($"http://localhost:{_scenario.ApiPort}"))
.WithSerializer(new NewtonsoftSerializer())
.Build();

rest.Delete("/api/DeletePath/validate")
.AssertSuccess();
});
}
}
16 changes: 16 additions & 0 deletions Samples/RestAuth/Samples.Rest.API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@
return Results.Json(new AuthenticatedTestResponse());
});

app.MapGet("/api/GetPath", () => Results.Json(new PathResponse("/api/GetPath/validate")));
app.MapGet("/api/GetPath/validate", () => Results.StatusCode(204));

app.MapGet("/api/PostPath", () => Results.Json(new PathResponse("/api/PostPath/validate")));
app.MapPost("/api/PostPath/validate", () => Results.StatusCode(204));

app.MapGet("/api/PatchPath", () => Results.Json(new PathResponse("/api/PatchPath/validate")));
app.MapPatch("/api/PatchPath/validate", () => Results.StatusCode(204));

app.MapGet("/api/DeletePath", () => Results.Json(new PathResponse("/api/DeletePath/validate")));
app.MapDelete("/api/DeletePath/validate", () => Results.StatusCode(204));

app.MapGet("/api/PutPath", () => Results.Json(new PathResponse("/api/PutPath/validate")));
app.MapPut("/api/PutPath/validate", () => Results.StatusCode(204));


static byte[] UrlDecode(string s)
{
s = s.Replace("-", "+").Replace("_", "/");
Expand Down
3 changes: 3 additions & 0 deletions Samples/RestAuth/Samples.Rest.API/Requests/APathRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Samples.Rest.API.Requests;

public class APathRequest();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Samples.Rest.API.Requests;

public record DynamicPathRequest(PathString Path);
3 changes: 3 additions & 0 deletions Samples/RestAuth/Samples.Rest.API/Responses/PathResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Samples.Rest.API.Responses;

public record PathResponse(string Path);
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ private async Task StartEnvironment(IServiceProvider serviceProvider)
.WithPassword("test")
.WithPortBinding(5432, true)
.WithWaitStrategy(Wait.ForUnixContainer().UntilCommandIsCompleted("pg_isready -U test -d test"))
.WithLogger(testContainerSupport.CreateLogger("postres"))
.WithNetwork(network)
.WithOutputConsumer(testContainerSupport.CreateOutputConsumer("postgres", false))
.WithNetworkAliases("postgres")
Expand Down
Loading
Loading