diff --git a/docs/EmulatorPolicyChecklist.md b/docs/EmulatorPolicyChecklist.md index b7ee1251..6d59a627 100644 --- a/docs/EmulatorPolicyChecklist.md +++ b/docs/EmulatorPolicyChecklist.md @@ -50,7 +50,7 @@ Track progress of emulator policy handler implementation. Each policy needs a ha | ⬜ | CacheStore | CacheStoreHandler.cs | Store interaction | `emulator/cache-store` | | ⬜ | Cors | CorsHandler.cs | Context mutation | `emulator/cors` | | ⬜ | EmitMetric | EmitMetricHandler.cs | No-op + callbacks | `emulator/emit-metric` | -| ⬜ | ForwardRequest | ForwardRequestHandler.cs | External service mock | `emulator/forward-request` | +| ✅ | ForwardRequest | ForwardRequestHandler.cs | External service mock | `emulator/forward-request` | | ⬜ | JsonP | JsonPHandler.cs | Context mutation | `emulator/jsonp` | | ⬜ | JsonToXml | JsonToXmlHandle.cs | No-op + callbacks | `emulator/json-to-xml` | | ⬜ | LlmEmitTokenMetric | LlmEmitTokenMetricHandler.cs | No-op + callbacks | `emulator/llm-emit-token-metric` | diff --git a/src/Testing/Document/TestDocumentExtensions.cs b/src/Testing/Document/TestDocumentExtensions.cs index a6217d9e..d55067b0 100644 --- a/src/Testing/Document/TestDocumentExtensions.cs +++ b/src/Testing/Document/TestDocumentExtensions.cs @@ -32,6 +32,9 @@ public static ResponseExampleStore SetupResponseExampleStore(this TestDocument d public static LoggerStore SetupLoggerStore(this TestDocument document) => document.Context.LoggerStore; + public static ForwardRequestStore SetupForwardRequest(this TestDocument document) => + document.Context.ForwardRequestStore; + public static RateLimitStore SetupRateLimitStore(this TestDocument document) => document.Context.RateLimitStore; } \ No newline at end of file diff --git a/src/Testing/Emulator/Data/ForwardRequestStore.cs b/src/Testing/Emulator/Data/ForwardRequestStore.cs new file mode 100644 index 00000000..1523ae3b --- /dev/null +++ b/src/Testing/Emulator/Data/ForwardRequestStore.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Data; + +public class ForwardRequestStore +{ + private readonly Queue _responses = new(); + private MockBackendResponse? _default; + + public ForwardRequestStore Returns(MockBackendResponse response) + { + _responses.Enqueue(response); + return this; + } + + public ForwardRequestStore ReturnsDefault(MockBackendResponse response) + { + _default = response; + return this; + } + + internal MockBackendResponse? GetNext() => + _responses.Count > 0 ? _responses.Dequeue() : _default; +} diff --git a/src/Testing/Emulator/Data/MockBackendResponse.cs b/src/Testing/Emulator/Data/MockBackendResponse.cs new file mode 100644 index 00000000..6734939b --- /dev/null +++ b/src/Testing/Emulator/Data/MockBackendResponse.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Data; + +public record MockBackendResponse +{ + public int StatusCode { get; init; } = 200; + public string StatusReason { get; init; } = "OK"; + public Dictionary Headers { get; init; } = new(); + public string? Body { get; init; } +} diff --git a/src/Testing/Emulator/Policies/ForwardRequestHandler.cs b/src/Testing/Emulator/Policies/ForwardRequestHandler.cs index dbb0a455..71cbdc33 100644 --- a/src/Testing/Emulator/Policies/ForwardRequestHandler.cs +++ b/src/Testing/Emulator/Policies/ForwardRequestHandler.cs @@ -1,7 +1,8 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.Azure.ApiManagement.PolicyToolkit.Authoring; +using Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Expressions; namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Policies; @@ -12,6 +13,27 @@ internal class ForwardRequestHandler : PolicyHandlerOptionalParam + var callbackExecuted = false; + test.SetupBackend().ForwardRequest().WithCallback((context, _) => { - executedCallback = true; + callbackExecuted = true; + context.Response.StatusCode = 418; }); test.RunBackend(); - executedCallback.Should().BeTrue(); + callbackExecuted.Should().BeTrue(); + test.Context.Response.StatusCode.Should().Be(418); } } \ No newline at end of file