Skip to content

Commit ed7b4c5

Browse files
authored
Fix logic to find start index for H3 headers in issue forms (#58)
1 parent 927ad66 commit ed7b4c5

File tree

5 files changed

+83
-6
lines changed

5 files changed

+83
-6
lines changed

GitHubIssueFormsParser/src/GitHubIssuesParserCli/IssueFormBody/Parsing/IssueFormBodyParser.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ public static IssueFormBody Parse(IssueFormBodyText issueFormBodyText, IssueForm
1313
{
1414
var currentTemplateItem = templateItems[i];
1515
var nextTemplateItem = templateItems.GetNextTemplateElement(i);
16-
var (startIdx, valueLength) = GetLevel3HeaderValueIndexes(currentTemplateItem.Label, nextTemplateItem?.Label, issueFormBodyText);
16+
var (startIdx, valueLength) = GetLevel3HeaderValueIndexes(
17+
currentTemplateItem.Label,
18+
nextTemplateItem?.Label,
19+
issueFormBodyText);
1720
var bodyAsString = (string)issueFormBodyText;
1821
var value = bodyAsString.Substring(startIdx, valueLength);
1922
var issueFormItem = IssueFormItemFactory.CreateFormItem(currentTemplateItem.Id, currentTemplateItem.Type, value);
@@ -50,9 +53,26 @@ private static (int startIdx, int valueLength) GetLevel3HeaderValueIndexes(
5053
private static int GetStartIndex(this IssueFormBodyText issueFormBodyText, string h3HeaderValue)
5154
{
5255
var bodyAsString = (string)issueFormBodyText;
53-
var startIdx = bodyAsString.IndexOf(h3HeaderValue, StringComparison.Ordinal);
54-
return startIdx is -1
55-
? throw IssueFormBodyParserException.H3HeaderNotFound(h3HeaderValue)
56-
: startIdx;
56+
var h3HeaderValueWindowsLineEnding = h3HeaderValue + NewLines.CR + NewLines.LF;
57+
var startIdx = bodyAsString.IndexOf(h3HeaderValueWindowsLineEnding, StringComparison.Ordinal);
58+
if (startIdx is not -1)
59+
{
60+
return startIdx;
61+
}
62+
63+
var h3HeaderValueUnixLineEnding = h3HeaderValue + NewLines.LF;
64+
startIdx = bodyAsString.IndexOf(h3HeaderValueUnixLineEnding, StringComparison.Ordinal);
65+
if (startIdx is not -1)
66+
{
67+
return startIdx;
68+
}
69+
70+
throw IssueFormBodyParserException.H3HeaderNotFound(h3HeaderValue);
71+
}
72+
73+
internal static class NewLines
74+
{
75+
public const string CR = "\r";
76+
public const string LF = "\n";
5777
}
5878
}

GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/CliCommands/ParseIssueFormCommandTests.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public async Task ParseIssueFormCommandTest1()
4444
/// regardless of the line endings on the issue form body.
4545
/// </summary>
4646
[Theory]
47-
[InlineData(CR)]
4847
[InlineData(LF)]
4948
[InlineData(CR + LF)]
5049
public async Task ParseIssueFormCommandTest2(string newLine)
@@ -76,4 +75,27 @@ public async Task ParseIssueFormCommandTest2(string newLine)
7675
issueFormJson.OperatingSystems.Unknown.ShouldNotBeNull();
7776
issueFormJson.OperatingSystems.Unknown.ShouldBe(false);
7877
}
78+
79+
/// <summary>
80+
/// Tests that the <see cref="ParseIssueFormCommand"/> produces the expected JSON output.
81+
/// This tests an edge case scenario for matching on the H3 header values. The matching is done
82+
/// with an string.IndexOf method and if two H3 headers start with the same value then the matching
83+
/// would always return the first occurence.
84+
///
85+
/// This has been fixed by changing the matching so that it only matches if the H3 header value
86+
/// matches for an entire line, not just the first string occurence.
87+
/// </summary>
88+
[Fact]
89+
public async Task ParseIssueFormCommandTest3()
90+
{
91+
using var console = new FakeInMemoryConsole();
92+
var command = new ParseIssueFormCommand
93+
{
94+
IssueFormBody = File.ReadAllText("./TestFiles/IssueBody2.md").NormalizeLineEndings(),
95+
TemplateFilepath = "./TestFiles/Template2.yml",
96+
};
97+
await command.ExecuteAsync(console);
98+
var output = console.ReadOutputString();
99+
output.ShouldNotBeNull();
100+
}
79101
}

GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/GitHubIssuesParserCli.Tests.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
<None Update="TestFiles\InvalidTemplate2.yml">
4949
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
5050
</None>
51+
<None Update="TestFiles\IssueBody2.md">
52+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
53+
</None>
5154
<None Update="TestFiles\IssueBodyWithMangledCheckbox.md">
5255
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
5356
</None>
@@ -60,6 +63,9 @@
6063
<None Update="TestFiles\InvalidTemplate.yml">
6164
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
6265
</None>
66+
<None Update="TestFiles\Template2.yml">
67+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
68+
</None>
6369
<None Update="TestFiles\Template.yml">
6470
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
6571
</None>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### What NuGet package do you want to release?
2+
3+
dotnet-sdk-extensions
4+
5+
### What
6+
7+
dotnet-sdk-extensions-testing
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Release NuGet package
2+
description: Release a NuGet package.
3+
title: Release NuGet package
4+
body:
5+
- type: dropdown
6+
id: nuget-id
7+
attributes:
8+
label: What NuGet package do you want to release?
9+
options:
10+
- dotnet-sdk-extensions
11+
- dotnet-sdk-extensions-testing
12+
validations:
13+
required: true
14+
- type: dropdown
15+
id: nuget-id-2
16+
attributes:
17+
label: What
18+
options:
19+
- dotnet-sdk-extensions
20+
- dotnet-sdk-extensions-testing
21+
validations:
22+
required: true

0 commit comments

Comments
 (0)