Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSOE-770: Add support for structured html-validate output #354

Closed
wants to merge 12 commits into from
43 changes: 43 additions & 0 deletions Lombiq.Tests.UI/Extensions/HtmlValidationResultExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using Atata.HtmlValidation;
using Lombiq.Tests.UI.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace Lombiq.Tests.UI.Extensions;
Expand All @@ -22,4 +25,44 @@ public static async Task<IEnumerable<string>> GetErrorsAsync(this HtmlValidation
.Select(error =>
(error.StartsWith("error:", StringComparison.OrdinalIgnoreCase) ? string.Empty : "error:") + error);
}

/// <summary>
/// Gets the parsed errors from the HTML validation result.
/// Can only be used if the output formatter is set to JSON.
/// </summary>
public static async Task<IEnumerable<HtmlValidationError>> GetParsedErrorsAsync(this HtmlValidationResult result)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good idea to rename it to something more specific like GetJsonParsedErrorsAsync, if we would add more formatters.

{
if (string.IsNullOrEmpty(result.ResultFilePath) || !File.Exists(result.ResultFilePath))
{
return Enumerable.Empty<HtmlValidationError>();
}

return ParseOutput(await File.ReadAllTextAsync(result.ResultFilePath));
}

private static IEnumerable<HtmlValidationError> ParseOutput(string output)
{
output = output.Trim();
if ((!output.StartsWith('{') || !output.EndsWith('}')) &&
(!output.StartsWith('[') || !output.EndsWith(']')))
{
throw new JsonException("Invalid JSON, make sure to set the OutputFormatter to JSON.");
}

try
{
var document = JsonDocument.Parse(output);
return document.RootElement.EnumerateArray()
.SelectMany(element => element.GetProperty("messages").EnumerateArray())
.Select(message =>
{
var rawMessageText = message.GetRawText();
return JsonSerializer.Deserialize<HtmlValidationError>(rawMessageText);
});
}
catch (JsonException)
{
throw new JsonException("Unable to parse output, did you set the OutputFormatter to JSON?");
}
}
}
29 changes: 29 additions & 0 deletions Lombiq.Tests.UI/Models/HtmlValidationError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Azure.Core.Serialization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Lombiq.Tests.UI.Models;

public class HtmlValidationError
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be more specific too (like JsonHtmlValidationError or something like that.

{
[JsonPropertyName("ruleId")]
public string RuleId { get; set; }
[JsonPropertyName("severity")]
public int Severity { get; set; }
[JsonPropertyName("message")]
public string Message { get; set; }
[JsonPropertyName("offset")]
public int Offset { get; set; }
[JsonPropertyName("line")]
public int Line { get; set; }
[JsonPropertyName("column")]
public int Column { get; set; }
[JsonPropertyName("size")]
public int Size { get; set; }
[JsonPropertyName("selector")]
public string Selector { get; set; }
[JsonPropertyName("ruleUrl")]
public string RuleUrl { get; set; }
[JsonPropertyName("context")]
public JsonElement Context { get; set; }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason this is JsonElement instead of something else is because this doesn't seem to have the same properties every time see sample output below:
image

}