Skip to content
This repository was archived by the owner on Nov 14, 2024. It is now read-only.

Commit f4f624b

Browse files
Feature - redesign library with first cycle of refactoring (#27)
* Feature - redesign library with first cycle of refactoring * pr-fix: finish renaming * pr-fix: use string as output result * pr-sug: test temp enabling logic app * pr-sug: split 'GetLogicAppTriggerUrlAsync' to better alternative * pr-sug: use Arcus guidelines for test's names * pr-sug: use date time offset * pr-sug: use single or default * pr-sug: remove magic number of runs * pr-sug: increase timeout to 40s * pr-sug: add explicit test cases for logic apps provider * pr-sug: add extra information to the trigger exception * pr-sug: use '...Async' suffix on all asynchronous methods * pr-sug: update without booleans in result type * pr-sug: add arg checks * pr-sug: add test for temp success static result * pr-sug: update with any derived exception assertion * pr-sug: using datetime offset * pr-sug: rename to 'LogicAppConverter' * pr-sug: use private disabling func. * pr-sug: move tenant ID before subscription ID in logic app auth. * pr-sug: rename to include 'minimum...' in number of logic app runs to poll * pr-sug: add tests for creating/assigning info in custom exceptions * pr-sug: add tests for logic app converter * pr-fix: update with correct double assertion of possible 'null' * pr-sug: update exception signature with message as least specific * pr-sug: update exception signature with message as least specific * pr-sug: use diff setup for timeout/number of items * pr-sug: testing reconfigure * pr-sug: update simpler assertion * Update src/Invictus.Testing/LogicAppClient.cs Co-authored-by: Maxim Braekman <[email protected]> * Update src/Invictus.Testing/LogicAppClient.cs Co-authored-by: Maxim Braekman <[email protected]> Co-authored-by: Maxim Braekman <[email protected]>
1 parent 4ed3539 commit f4f624b

25 files changed

+2432
-1417
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using Arcus.Testing.Logging;
2+
using Microsoft.Extensions.Logging;
3+
using Xunit.Abstractions;
4+
5+
namespace Invictus.Testing.Tests.Integration
6+
{
7+
/// <summary>
8+
/// Provides set of reusable information required for the logic app integration tests.
9+
/// </summary>
10+
public abstract class IntegrationTest
11+
{
12+
/// <summary>
13+
/// Initializes a new instance of the <see cref="IntegrationTest"/> class.
14+
/// </summary>
15+
protected IntegrationTest(ITestOutputHelper outputWriter)
16+
{
17+
Logger = new XunitTestLogger(outputWriter);
18+
ResourceGroup = Configuration.GetAzureResourceGroup();
19+
LogicAppName = Configuration.GetTestLogicAppName();
20+
LogicAppMockingName = Configuration.GetTestMockingLogicAppName();
21+
22+
string subscriptionId = Configuration.GetAzureSubscriptionId();
23+
string tenantId = Configuration.GetAzureTenantId();
24+
string clientId = Configuration.GetAzureClientId();
25+
string clientSecret = Configuration.GetAzureClientSecret();
26+
Authentication = LogicAuthentication.UsingServicePrincipal(tenantId, subscriptionId, clientId, clientSecret);
27+
}
28+
29+
/// <summary>
30+
/// Gets the logger to write diagnostic messages during tests.
31+
/// </summary>
32+
protected ILogger Logger { get; }
33+
34+
/// <summary>
35+
/// Gets the configuration available in the current integration test suite.
36+
/// </summary>
37+
protected TestConfig Configuration { get; } = TestConfig.Create();
38+
39+
/// <summary>
40+
/// Gets the resource group where the logic app resources on Azure are located.
41+
/// </summary>
42+
protected string ResourceGroup { get; }
43+
44+
/// <summary>
45+
/// Gets the name of the logic app resource running on Azure to test stateless operations against.
46+
/// </summary>
47+
protected string LogicAppName { get; }
48+
49+
/// <summary>
50+
/// Gets the name of the logic app resource running on Azure to test stateful operations against.
51+
/// </summary>
52+
protected string LogicAppMockingName { get; }
53+
54+
/// <summary>
55+
/// Gets the authentication mechanism to authenticate with Azure.
56+
/// </summary>
57+
protected LogicAuthentication Authentication { get; }
58+
}
59+
}

src/Invictus.Testing.Tests.Integration/Invictus.Testing.Tests.Integration.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8+
<PackageReference Include="Bogus" Version="29.0.2" />
89
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.4" />
910
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
1011
<PackageReference Include="xunit" Version="2.4.1" />
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Invictus.Testing.Model;
6+
using Invictus.Testing.Serialization;
7+
using Newtonsoft.Json.Linq;
8+
using Xunit;
9+
using Xunit.Abstractions;
10+
11+
namespace Invictus.Testing.Tests.Integration
12+
{
13+
public class LogicAppClientTests : IntegrationTest
14+
{
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="LogicAppClientTests"/> class.
17+
/// </summary>
18+
public LogicAppClientTests(ITestOutputHelper outputWriter) : base(outputWriter)
19+
{
20+
}
21+
22+
[Fact]
23+
public async Task GetLogicAppTriggerUrl_NoTriggerNameSpecified_Success()
24+
{
25+
// Arrange
26+
using (var logicApp = await LogicAppClient.CreateAsync(ResourceGroup, LogicAppName, Authentication))
27+
{
28+
// Act
29+
LogicAppTriggerUrl logicAppTriggerUrl = await logicApp.GetTriggerUrlAsync();
30+
31+
// Assert
32+
Assert.NotNull(logicAppTriggerUrl.Value);
33+
Assert.Equal("POST", logicAppTriggerUrl.Method);
34+
}
35+
}
36+
37+
[Fact]
38+
public async Task GetLogicAppTriggerUrl_ByName_Success()
39+
{
40+
using (var logicApp = await LogicAppClient.CreateAsync(ResourceGroup, LogicAppName, Authentication))
41+
{
42+
// Act
43+
LogicAppTriggerUrl logicAppTriggerUrl = await logicApp.GetTriggerUrlByNameAsync(triggerName: "manual");
44+
45+
// Assert
46+
Assert.NotNull(logicAppTriggerUrl.Value);
47+
Assert.Equal("POST", logicAppTriggerUrl.Method);
48+
}
49+
}
50+
51+
[Fact]
52+
public async Task TemporaryEnableSuccessStaticResultForAction_WithoutConsumerStaticResult_Success()
53+
{
54+
// Arrange
55+
const string actionName = "HTTP";
56+
string correlationId = $"correlationId-{Guid.NewGuid()}";
57+
var headers = new Dictionary<string, string>
58+
{
59+
{ "correlationId", correlationId },
60+
};
61+
62+
// Act
63+
using (var logicApp = await LogicAppClient.CreateAsync(ResourceGroup, LogicAppMockingName, Authentication, Logger))
64+
{
65+
await using (await logicApp.TemporaryEnableAsync())
66+
{
67+
await using (await logicApp.TemporaryEnableSuccessStaticResultAsync(actionName))
68+
{
69+
// Act
70+
await logicApp.TriggerAsync(headers);
71+
LogicAppAction enabledAction = await PollForLogicAppActionAsync(correlationId, actionName);
72+
73+
Assert.Equal(actionName, enabledAction.Name);
74+
Assert.Equal("200", enabledAction.Outputs.statusCode.ToString());
75+
Assert.Equal("Succeeded", enabledAction.Status);
76+
}
77+
78+
await logicApp.TriggerAsync(headers);
79+
LogicAppAction disabledAction = await PollForLogicAppActionAsync(correlationId, actionName);
80+
81+
Assert.NotEmpty(disabledAction.Outputs.headers);
82+
}
83+
}
84+
}
85+
86+
[Fact]
87+
public async Task TemporaryEnableStaticResultsForAction_WithSuccessStaticResult_Success()
88+
{
89+
// Arrange
90+
const string actionName = "HTTP";
91+
string correlationId = $"correlationId-{Guid.NewGuid()}";
92+
var headers = new Dictionary<string, string>
93+
{
94+
{ "correlationId", correlationId },
95+
};
96+
97+
var definition = new StaticResultDefinition
98+
{
99+
Outputs = new Outputs
100+
{
101+
Headers = new Dictionary<string, string> { { "testheader", "testvalue" } },
102+
StatusCode = "200",
103+
Body = JToken.Parse("{id : 12345, name : 'test body'}")
104+
},
105+
Status = "Succeeded"
106+
};
107+
108+
// Act
109+
using (var logicApp = await LogicAppClient.CreateAsync(ResourceGroup, LogicAppMockingName, Authentication, Logger))
110+
{
111+
await using (await logicApp.TemporaryEnableAsync())
112+
{
113+
var definitions = new Dictionary<string, StaticResultDefinition> { [actionName] = definition };
114+
await using (await logicApp.TemporaryEnableStaticResultsAsync(definitions))
115+
{
116+
// Act
117+
await logicApp.TriggerAsync(headers);
118+
LogicAppAction enabledAction = await PollForLogicAppActionAsync(correlationId, actionName);
119+
120+
Assert.Equal("200", enabledAction.Outputs.statusCode.ToString());
121+
Assert.Equal("testvalue", enabledAction.Outputs.headers["testheader"].ToString());
122+
Assert.Contains("test body", enabledAction.Outputs.body.ToString());
123+
}
124+
125+
await logicApp.TriggerAsync(headers);
126+
LogicAppAction disabledAction = await PollForLogicAppActionAsync(correlationId, actionName);
127+
128+
Assert.DoesNotContain("test body", disabledAction.Outputs.body.ToString());
129+
}
130+
}
131+
}
132+
133+
[Fact]
134+
public async Task TemporaryEnableStaticResultForAction_WithSuccessStaticResult_Success()
135+
{
136+
// Arrange
137+
const string actionName = "HTTP";
138+
string correlationId = $"correlationId-{Guid.NewGuid()}";
139+
var headers = new Dictionary<string, string>
140+
{
141+
{ "correlationId", correlationId },
142+
};
143+
144+
var definition = new StaticResultDefinition
145+
{
146+
Outputs = new Outputs
147+
{
148+
Headers = new Dictionary<string, string> { { "testheader", "testvalue" } },
149+
StatusCode = "200",
150+
Body = JToken.Parse("{id : 12345, name : 'test body'}")
151+
},
152+
Status = "Succeeded"
153+
};
154+
155+
// Act
156+
using (var logicApp = await LogicAppClient.CreateAsync(ResourceGroup, LogicAppMockingName, Authentication))
157+
{
158+
await using (await logicApp.TemporaryEnableAsync())
159+
{
160+
await using (await logicApp.TemporaryEnableStaticResultAsync(actionName, definition))
161+
{
162+
// Act
163+
await logicApp.TriggerAsync(headers);
164+
LogicAppAction enabledAction = await PollForLogicAppActionAsync(correlationId, actionName);
165+
166+
Assert.Equal("200", enabledAction.Outputs.statusCode.ToString());
167+
Assert.Equal("testvalue", enabledAction.Outputs.headers["testheader"].ToString());
168+
Assert.Contains("test body", enabledAction.Outputs.body.ToString());
169+
}
170+
171+
await logicApp.TriggerAsync(headers);
172+
LogicAppAction disabledAction = await PollForLogicAppActionAsync(correlationId, actionName);
173+
174+
Assert.DoesNotContain("test body", disabledAction.Outputs.body.ToString());
175+
}
176+
}
177+
}
178+
179+
[Fact]
180+
public async Task TemporaryEnableLogicApp_Success()
181+
{
182+
// Act
183+
using (var logicApp = await LogicAppClient.CreateAsync(ResourceGroup, LogicAppMockingName, Authentication, Logger))
184+
{
185+
await using (await logicApp.TemporaryEnableAsync())
186+
{
187+
// Assert
188+
LogicApp metadata = await logicApp.GetMetadataAsync();
189+
Assert.Equal("Enabled", metadata.State);
190+
}
191+
{
192+
LogicApp metadata = await logicApp.GetMetadataAsync();
193+
Assert.Equal("Disabled", metadata.State);
194+
}
195+
}
196+
}
197+
198+
[Theory]
199+
[InlineData(null)]
200+
[InlineData("")]
201+
public async Task Constructor_WithBlankResourceGroup_Fails(string resourceGroup)
202+
{
203+
await Assert.ThrowsAsync<ArgumentException>(
204+
() => LogicAppClient.CreateAsync(resourceGroup, LogicAppName, Authentication));
205+
}
206+
207+
[Theory]
208+
[InlineData(null)]
209+
[InlineData("")]
210+
public async Task Constructor_WithBlankLogicApp_Fails(string logicApp)
211+
{
212+
await Assert.ThrowsAsync<ArgumentException>(
213+
() => LogicAppClient.CreateAsync(ResourceGroup, logicApp, Authentication));
214+
}
215+
216+
[Theory]
217+
[InlineData(null)]
218+
[InlineData("")]
219+
public async Task ConstructorWithLogger_WithBlankResourceGroup_Fails(string resourceGroup)
220+
{
221+
await Assert.ThrowsAsync<ArgumentException>(
222+
() => LogicAppClient.CreateAsync(resourceGroup, LogicAppName, Authentication, Logger));
223+
}
224+
225+
[Theory]
226+
[InlineData(null)]
227+
[InlineData("")]
228+
public async Task ConstructorWithLogger_WithBlankLogicApp_Fails(string logicApp)
229+
{
230+
await Assert.ThrowsAsync<ArgumentException>(
231+
() => LogicAppClient.CreateAsync(ResourceGroup, logicApp, Authentication, Logger));
232+
}
233+
234+
[Fact]
235+
public async Task Constructor_WithNullAuthentication_Fails()
236+
{
237+
await Assert.ThrowsAnyAsync<ArgumentException>(
238+
() => LogicAppClient.CreateAsync(ResourceGroup, LogicAppName, authentication: null));
239+
}
240+
241+
[Fact]
242+
public async Task ConstructorWithLogger_WithNullAuthentication_Fails()
243+
{
244+
await Assert.ThrowsAnyAsync<ArgumentException>(
245+
() => LogicAppClient.CreateAsync(ResourceGroup, LogicAppName, authentication: null, logger: Logger));
246+
}
247+
248+
private async Task<LogicAppAction> PollForLogicAppActionAsync(string correlationId, string actionName)
249+
{
250+
LogicAppRun logicAppRun = await LogicAppsProvider
251+
.LocatedAt(ResourceGroup, LogicAppMockingName, Authentication, Logger)
252+
.WithStartTime(DateTimeOffset.UtcNow.AddMinutes(-1))
253+
.WithCorrelationId(correlationId)
254+
.PollForSingleLogicAppRunAsync();
255+
256+
Assert.True(logicAppRun.Actions.Count() != 0);
257+
LogicAppAction logicAppAction = logicAppRun.Actions.First(action => action.Name.Equals(actionName));
258+
Assert.NotNull(logicAppAction);
259+
260+
return logicAppAction;
261+
}
262+
}
263+
}

0 commit comments

Comments
 (0)