Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.
This commit is contained in:
@@ -20,6 +20,7 @@ using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Xunit;
|
||||
using Xunit.v3;
|
||||
|
||||
namespace StellaOps.Notify.WebService.Tests.W1;
|
||||
|
||||
@@ -61,8 +62,8 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
_adminToken = CreateToken("notify.viewer", "notify.operator", "notify.admin");
|
||||
}
|
||||
|
||||
public Task InitializeAsync() => Task.CompletedTask;
|
||||
public Task DisposeAsync() => Task.CompletedTask;
|
||||
public ValueTask InitializeAsync() => ValueTask.CompletedTask;
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
|
||||
#region Health Endpoints Contract
|
||||
|
||||
@@ -73,11 +74,11 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("/healthz");
|
||||
var response = await client.GetAsync("/healthz", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
json?["status"]?.GetValue<string>().Should().Be("ok");
|
||||
}
|
||||
@@ -89,7 +90,7 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
var client = _factory.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("/readyz");
|
||||
var response = await client.GetAsync("/readyz", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().BeOneOf(HttpStatusCode.OK, HttpStatusCode.ServiceUnavailable);
|
||||
@@ -107,13 +108,13 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("/api/v1/notify/rules");
|
||||
var response = await client.GetAsync("/api/v1/notify/rules", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
response.Content.Headers.ContentType?.MediaType.Should().Be("application/json");
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
json.Should().NotBeNull();
|
||||
json!.AsArray().Should().NotBeNull();
|
||||
@@ -132,7 +133,8 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
// Act
|
||||
var response = await client.PostAsync(
|
||||
"/api/v1/notify/rules",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||
@@ -166,7 +168,7 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("/api/v1/notify/rules/nonexistent-rule-id");
|
||||
var response = await client.GetAsync("/api/v1/notify/rules/nonexistent-rule-id", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||
@@ -184,10 +186,11 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
var payload = CreateRulePayload(ruleId);
|
||||
await client.PostAsync(
|
||||
"/api/v1/notify/rules",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Act
|
||||
var response = await client.DeleteAsync($"/api/v1/notify/rules/{ruleId}");
|
||||
var response = await client.DeleteAsync($"/api/v1/notify/rules/{ruleId}", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
|
||||
@@ -205,13 +208,13 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("/api/v1/notify/channels");
|
||||
var response = await client.GetAsync("/api/v1/notify/channels", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
response.Content.Headers.ContentType?.MediaType.Should().Be("application/json");
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
json.Should().NotBeNull();
|
||||
json!.AsArray().Should().NotBeNull();
|
||||
@@ -230,7 +233,8 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
// Act
|
||||
var response = await client.PostAsync(
|
||||
"/api/v1/notify/channels",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||
@@ -248,11 +252,11 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("/api/v1/notify/templates");
|
||||
var response = await client.GetAsync("/api/v1/notify/templates", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
json.Should().NotBeNull();
|
||||
json!.AsArray().Should().NotBeNull();
|
||||
@@ -271,7 +275,8 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
// Act
|
||||
var response = await client.PostAsync(
|
||||
"/api/v1/notify/templates",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||
@@ -294,7 +299,8 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
// Act
|
||||
var response = await client.PostAsync(
|
||||
"/api/v1/notify/deliveries",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Assert - can be 201 Created or 202 Accepted depending on processing
|
||||
response.StatusCode.Should().BeOneOf(HttpStatusCode.Created, HttpStatusCode.Accepted);
|
||||
@@ -308,11 +314,11 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("/api/v1/notify/deliveries?limit=10");
|
||||
var response = await client.GetAsync("/api/v1/notify/deliveries?limit=10", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
json.Should().NotBeNull();
|
||||
json!.AsArray().Should().NotBeNull();
|
||||
@@ -326,7 +332,7 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync($"/api/v1/notify/deliveries/{Guid.NewGuid()}");
|
||||
var response = await client.GetAsync($"/api/v1/notify/deliveries/{Guid.NewGuid()}", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||
@@ -348,11 +354,12 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
// Act
|
||||
var response = await client.PostAsync(
|
||||
"/api/v1/notify/_internal/rules/normalize",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
json?["schemaVersion"]?.GetValue<string>().Should().NotBeNullOrEmpty();
|
||||
}
|
||||
@@ -372,15 +379,16 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
var payload = CreateRulePayload(ruleId);
|
||||
await client.PostAsync(
|
||||
"/api/v1/notify/rules",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Act
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
var response = await client.GetAsync($"/api/v1/notify/rules/{ruleId}");
|
||||
var response = await client.GetAsync($"/api/v1/notify/rules/{ruleId}", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
|
||||
// Verify required fields exist
|
||||
@@ -403,15 +411,16 @@ public class NotifyWebServiceContractTests : IClassFixture<WebApplicationFactory
|
||||
var payload = CreateChannelPayload(channelId);
|
||||
await client.PostAsync(
|
||||
"/api/v1/notify/channels",
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
|
||||
new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"),
|
||||
CancellationToken.None);
|
||||
|
||||
// Act
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _viewerToken);
|
||||
var response = await client.GetAsync($"/api/v1/notify/channels/{channelId}");
|
||||
var response = await client.GetAsync($"/api/v1/notify/channels/{channelId}", CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var content = await response.Content.ReadAsStringAsync(CancellationToken.None);
|
||||
var json = JsonNode.Parse(content);
|
||||
|
||||
json?["channelId"].Should().NotBeNull();
|
||||
|
||||
Reference in New Issue
Block a user