Files
git.stella-ops.org/src/StellaOps.Concelier.Connector.Cccs.Tests/Internal/CccsHtmlParserTests.cs
master d97779eed6
Some checks failed
Build Test Deploy / build-test (push) Has been cancelled
Build Test Deploy / authority-container (push) Has been cancelled
Build Test Deploy / docs (push) Has been cancelled
Build Test Deploy / deploy (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Rename Concelier Source modules to Connector
2025-10-18 20:11:18 +03:00

93 lines
3.1 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using FluentAssertions;
using StellaOps.Concelier.Connector.Cccs.Internal;
using StellaOps.Concelier.Connector.Common.Html;
using Xunit;
using Xunit.Abstractions;
namespace StellaOps.Concelier.Connector.Cccs.Tests.Internal;
public sealed class CccsHtmlParserTests
{
private readonly ITestOutputHelper _output;
private static readonly HtmlContentSanitizer Sanitizer = new();
private static readonly CccsHtmlParser Parser = new(Sanitizer);
public CccsHtmlParserTests(ITestOutputHelper output)
{
_output = output ?? throw new ArgumentNullException(nameof(output));
}
public static IEnumerable<object[]> ParserCases()
{
yield return new object[]
{
"cccs-raw-advisory.json",
"TEST-001",
"en",
new[] { "Vendor Widget 1.0", "Vendor Widget 2.0" },
new[]
{
"https://example.com/details",
"https://www.cyber.gc.ca/en/contact-cyber-centre?lang=en"
},
new[] { "CVE-2020-1234", "CVE-2021-9999" }
};
yield return new object[]
{
"cccs-raw-advisory-fr.json",
"TEST-002-FR",
"fr",
new[] { "Produit Exemple 3.1", "Produit Exemple 3.2", "Variante 3.2.1" },
new[]
{
"https://exemple.ca/details",
"https://www.cyber.gc.ca/fr/contact-centre-cyber"
},
new[] { "CVE-2024-1111" }
};
}
[Theory]
[MemberData(nameof(ParserCases))]
public void Parse_ExtractsExpectedFields(
string fixtureName,
string expectedSerial,
string expectedLanguage,
string[] expectedProducts,
string[] expectedReferenceUrls,
string[] expectedCves)
{
var raw = LoadFixture<CccsRawAdvisoryDocument>(fixtureName);
var dto = Parser.Parse(raw);
_output.WriteLine("Products: {0}", string.Join("|", dto.Products));
_output.WriteLine("References: {0}", string.Join("|", dto.References.Select(r => $"{r.Url} ({r.Label})")));
_output.WriteLine("CVEs: {0}", string.Join("|", dto.CveIds));
dto.SerialNumber.Should().Be(expectedSerial);
dto.Language.Should().Be(expectedLanguage);
dto.Products.Should().BeEquivalentTo(expectedProducts);
foreach (var url in expectedReferenceUrls)
{
dto.References.Should().Contain(reference => reference.Url == url);
}
dto.CveIds.Should().BeEquivalentTo(expectedCves);
dto.ContentHtml.Should().Contain("<ul>").And.Contain("<li>");
dto.ContentHtml.Should().Contain("<h2", because: "heading structure must survive sanitisation for UI rendering");
}
internal static T LoadFixture<T>(string fileName)
{
var path = Path.Combine(AppContext.BaseDirectory, "Fixtures", fileName);
var json = File.ReadAllText(path);
return JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions(JsonSerializerDefaults.Web))!;
}
}