diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..9cc496505
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.cs diff=csharp
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index da37e81da..44482aa47 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,3 +1,3 @@
# These owners will be the default owners for everything in the repo and
# will be requested for review when someone opens a pull request.
-* @pascalberger @christianbumann @x-jokay @silanosa @georgesgoetz
\ No newline at end of file
+* @cake-contrib/team-bbt @x-jokay
\ No newline at end of file
diff --git a/nuspec/nuget/Cake.Issues.Testing.nuspec b/nuspec/nuget/Cake.Issues.Testing.nuspec
index 519258325..aaf4fcd4e 100644
--- a/nuspec/nuget/Cake.Issues.Testing.nuspec
+++ b/nuspec/nuget/Cake.Issues.Testing.nuspec
@@ -17,7 +17,7 @@ Common helpers for testing add-ins based on Cake.Issues
Copyright © BBT Software AG and contributors
Cake Script Cake-Issues Issues Testing
- https://github.com/cake-contrib/Cake.Issues/releases/tag/0.8.1
+ https://github.com/cake-contrib/Cake.Issues/releases/tag/0.9.0
diff --git a/nuspec/nuget/Cake.Issues.nuspec b/nuspec/nuget/Cake.Issues.nuspec
index 8287bab58..bafece048 100644
--- a/nuspec/nuget/Cake.Issues.nuspec
+++ b/nuspec/nuget/Cake.Issues.nuspec
@@ -24,7 +24,7 @@ See the Project Site for an overview of the whole ecosystem of addins for workin
Copyright © BBT Software AG and contributors
Cake Script Cake-Issues CodeAnalysis Linting Issues
- https://github.com/cake-contrib/Cake.Issues/releases/tag/0.8.1
+ https://github.com/cake-contrib/Cake.Issues/releases/tag/0.9.0
diff --git a/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs b/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs
index c71f7f198..69b1799ac 100644
--- a/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs
+++ b/src/Cake.Issues.Testing/BaseIssueProviderFixture.cs
@@ -19,7 +19,7 @@ public abstract class BaseIssueProviderFixture
protected BaseIssueProviderFixture()
{
this.Log = new FakeLog { Verbosity = Verbosity.Normal };
- this.RepositorySettings = new RepositorySettings(@"c:\repo");
+ this.ReadIssuesSettings = new ReadIssuesSettings(@"c:\repo");
}
///
@@ -30,7 +30,7 @@ protected BaseIssueProviderFixture()
///
/// Gets or sets the repository settings.
///
- public RepositorySettings RepositorySettings { get; set; }
+ public ReadIssuesSettings ReadIssuesSettings { get; set; }
///
/// Calls .
@@ -67,12 +67,12 @@ private T CreateIssueProvider()
typeof(T),
this.GetCreateIssueProviderArguments().ToArray());
- if (this.RepositorySettings == null)
+ if (this.ReadIssuesSettings == null)
{
- throw new InvalidOperationException("No repository settings set.");
+ throw new InvalidOperationException("No settings for reading issues set.");
}
- provider.Initialize(this.RepositorySettings);
+ provider.Initialize(this.ReadIssuesSettings);
return provider;
}
}
diff --git a/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj b/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj
index 4347c3be9..ef03c32ac 100644
--- a/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj
+++ b/src/Cake.Issues.Testing/Cake.Issues.Testing.csproj
@@ -26,7 +26,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs b/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs
index 5a7c9f061..4330764da 100644
--- a/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs
+++ b/src/Cake.Issues.Testing/FakeConfigurableIssueProvider.cs
@@ -48,7 +48,7 @@ public FakeConfigurableIssueProvider(
///
/// Gets the repository settings.
///
- public RepositorySettings RepositorySettings => this.Settings;
+ public IRepositorySettings RepositorySettings => this.Settings;
///
/// Gets the issue provider settings.
diff --git a/src/Cake.Issues.Testing/FakeIssueProvider.cs b/src/Cake.Issues.Testing/FakeIssueProvider.cs
index 8dcef5169..ae83e6481 100644
--- a/src/Cake.Issues.Testing/FakeIssueProvider.cs
+++ b/src/Cake.Issues.Testing/FakeIssueProvider.cs
@@ -42,7 +42,7 @@ public FakeIssueProvider(ICakeLog log, IEnumerable issues)
///
/// Gets the settings.
///
- public new RepositorySettings Settings => base.Settings;
+ public new IRepositorySettings Settings => base.Settings;
///
public override string ProviderName => "Fake Issue Provider";
diff --git a/src/Cake.Issues.Testing/FakeLogFileFormat.cs b/src/Cake.Issues.Testing/FakeLogFileFormat.cs
index 8e39bfd73..6d1dbfc90 100644
--- a/src/Cake.Issues.Testing/FakeLogFileFormat.cs
+++ b/src/Cake.Issues.Testing/FakeLogFileFormat.cs
@@ -42,7 +42,7 @@ public FakeLogFileFormat(ICakeLog log, IEnumerable issues)
///
public override IEnumerable ReadIssues(
FakeMultiFormatIssueProvider issueProvider,
- RepositorySettings repositorySettings,
+ IRepositorySettings repositorySettings,
FakeMultiFormatIssueProviderSettings issueProviderSettings)
{
return this.issues;
diff --git a/src/Cake.Issues.Testing/FakeMultiFormatIssueProvider.cs b/src/Cake.Issues.Testing/FakeMultiFormatIssueProvider.cs
index b53d8b55e..3c35c884a 100644
--- a/src/Cake.Issues.Testing/FakeMultiFormatIssueProvider.cs
+++ b/src/Cake.Issues.Testing/FakeMultiFormatIssueProvider.cs
@@ -26,7 +26,7 @@ public FakeMultiFormatIssueProvider(ICakeLog log, FakeMultiFormatIssueProviderSe
///
/// Gets the repository settings.
///
- public RepositorySettings RepositorySettings => this.Settings;
+ public IRepositorySettings RepositorySettings => this.Settings;
///
/// Gets the issue provider settings.
diff --git a/src/Cake.Issues.Testing/IssueChecker.cs b/src/Cake.Issues.Testing/IssueChecker.cs
index d68a51799..49a4b26a6 100644
--- a/src/Cake.Issues.Testing/IssueChecker.cs
+++ b/src/Cake.Issues.Testing/IssueChecker.cs
@@ -41,10 +41,16 @@ public static void Check(
issueToCheck,
expectedIssue.ProviderType,
expectedIssue.ProviderName,
+ expectedIssue.Run,
+ expectedIssue.Identifier,
expectedIssue.ProjectFileRelativePath?.ToString(),
expectedIssue.ProjectName,
expectedIssue.AffectedFileRelativePath?.ToString(),
expectedIssue.Line,
+ expectedIssue.EndLine,
+ expectedIssue.Column,
+ expectedIssue.EndColumn,
+ expectedIssue.FileLink,
expectedIssue.MessageText,
expectedIssue.MessageHtml,
expectedIssue.MessageMarkdown,
@@ -60,6 +66,8 @@ public static void Check(
/// Issue which should be checked.
/// Expected type of the issue provider.
/// Expected human friendly name of the issue provider.
+ /// Expected name of the run which reported the issue.
+ /// Expected identifier of the issue.
/// Expected relative path of the project file.
/// null if the issue is not expected to be related to a project.
/// Expected project name.
@@ -68,6 +76,14 @@ public static void Check(
/// null if the issue is not expected to be related to a change in a file.
/// Expected line number.
/// null if the issue is not expected to be related to a file or specific line.
+ /// Expected end of line range.
+ /// null if the issue is not expected to be related to a file, specific line or range of lines.
+ /// Expected column.
+ /// null if the issue is not expected to be related to a file or specific column.
+ /// Expected end of column range.
+ /// null if the issue is not expected to be related to a file, specific column or range of columns.
+ /// Expected file link.
+ /// null if the issue is not expected to have a file link.
/// Expected message in plain text format.
/// Expected message in HTML format.
/// Expected message in Markdown format.
@@ -83,10 +99,16 @@ public static void Check(
IIssue issue,
string providerType,
string providerName,
+ string run,
+ string identifier,
string projectFileRelativePath,
string projectName,
string affectedFileRelativePath,
int? line,
+ int? endLine,
+ int? column,
+ int? endColumn,
+ Uri fileLink,
string messageText,
string messageHtml,
string messageMarkdown,
@@ -109,6 +131,18 @@ public static void Check(
$"Expected issue.ProviderName to be '{providerName}' but was '{issue.ProviderName}'.");
}
+ if (issue.Run != run)
+ {
+ throw new Exception(
+ $"Expected issue.Run to be '{run}' but was '{issue.Run}'.");
+ }
+
+ if (issue.Identifier != identifier)
+ {
+ throw new Exception(
+ $"Expected issue.Identifier to be '{identifier}' but was '{issue.Identifier}'.");
+ }
+
if (issue.ProjectFileRelativePath == null)
{
if (projectFileRelativePath != null)
@@ -122,7 +156,7 @@ public static void Check(
if (issue.ProjectFileRelativePath.ToString() != new FilePath(projectFileRelativePath).ToString())
{
throw new Exception(
- $"Expected issue.ProjectFileRelativePath to be '{projectFileRelativePath}' but was '{issue.ProjectFileRelativePath.ToString()}'.");
+ $"Expected issue.ProjectFileRelativePath to be '{projectFileRelativePath}' but was '{issue.ProjectFileRelativePath}'.");
}
if (!issue.ProjectFileRelativePath.IsRelative)
@@ -151,7 +185,7 @@ public static void Check(
if (issue.AffectedFileRelativePath.ToString() != new FilePath(affectedFileRelativePath).ToString())
{
throw new Exception(
- $"Expected issue.AffectedFileRelativePath to be '{affectedFileRelativePath}' but was '{issue.AffectedFileRelativePath.ToString()}'.");
+ $"Expected issue.AffectedFileRelativePath to be '{affectedFileRelativePath}' but was '{issue.AffectedFileRelativePath}'.");
}
if (!issue.AffectedFileRelativePath.IsRelative)
@@ -167,6 +201,30 @@ public static void Check(
$"Expected issue.Line to be '{line}' but was '{issue.Line}'.");
}
+ if (issue.EndLine != endLine)
+ {
+ throw new Exception(
+ $"Expected issue.EndLine to be '{endLine}' but was '{issue.EndLine}'.");
+ }
+
+ if (issue.Column != column)
+ {
+ throw new Exception(
+ $"Expected issue.Column to be '{column}' but was '{issue.Column}'.");
+ }
+
+ if (issue.EndColumn != endColumn)
+ {
+ throw new Exception(
+ $"Expected issue.EndColumn to be '{endColumn}' but was '{issue.EndColumn}'.");
+ }
+
+ if (issue.FileLink?.ToString() != fileLink?.ToString())
+ {
+ throw new Exception(
+ $"Expected issue.FileLink to be '{fileLink}' but was '{issue.FileLink}'.");
+ }
+
if (issue.MessageText != messageText)
{
throw new Exception(
diff --git a/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs b/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs
index f446e83d8..af78a89b0 100644
--- a/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs
+++ b/src/Cake.Issues.Tests/BaseMultiFormatIssueProviderTests.cs
@@ -110,7 +110,7 @@ public void Should_Read_Issues_From_Format()
"Foo".ToByteArray(),
format);
var provider = new FakeMultiFormatIssueProvider(log, settings);
- provider.Initialize(new RepositorySettings(@"c:\repo"));
+ provider.Initialize(new ReadIssuesSettings(@"c:\repo"));
// When
var result = provider.ReadIssues();
diff --git a/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj b/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj
index 23d9e2e35..a21b89da7 100644
--- a/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj
+++ b/src/Cake.Issues.Tests/Cake.Issues.Tests.csproj
@@ -25,7 +25,7 @@
-
+
@@ -34,7 +34,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
@@ -43,9 +43,15 @@
+
+ Always
+
Always
+
+ Always
+
Always
diff --git a/src/Cake.Issues.Tests/FileLinkSettingsTests.cs b/src/Cake.Issues.Tests/FileLinkSettingsTests.cs
new file mode 100644
index 000000000..a80847747
--- /dev/null
+++ b/src/Cake.Issues.Tests/FileLinkSettingsTests.cs
@@ -0,0 +1,133 @@
+namespace Cake.Issues.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class FileLinkSettingsTests
+ {
+ public sealed class TheCtor
+ {
+ [Fact]
+ public void Should_Throw_If_Builder_Is_Null()
+ {
+ // Given
+ Func, Uri> builder = null;
+
+ // When
+ var result = Record.Exception(() => new FileLinkSettings(builder));
+
+ // Then
+ result.IsArgumentNullException("builder");
+ }
+ }
+
+ public sealed class TheForPatternMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Pattern_Is_Null()
+ {
+ // Given
+ string pattern = null;
+
+ // When
+ var result = Record.Exception(() => FileLinkSettings.ForPattern(pattern));
+
+ // Then
+ result.IsArgumentNullException("pattern");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Pattern_Is_Empty()
+ {
+ // Given
+ var pattern = string.Empty;
+
+ // When
+ var result = Record.Exception(() => FileLinkSettings.ForPattern(pattern));
+
+ // Then
+ result.IsArgumentOutOfRangeException("pattern");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Pattern_Is_WhiteSpace()
+ {
+ // Given
+ var pattern = " ";
+
+ // When
+ var result = Record.Exception(() => FileLinkSettings.ForPattern(pattern));
+
+ // Then
+ result.IsArgumentOutOfRangeException("pattern");
+ }
+ }
+
+ public sealed class TheForActionMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Builder_Is_Null()
+ {
+ // Given
+ Func builder = null;
+
+ // When
+ var result = Record.Exception(() => FileLinkSettings.ForAction(builder));
+
+ // Then
+ result.IsArgumentNullException("builder");
+ }
+ }
+
+ public sealed class TheForGitHubMethod
+ {
+ [Fact]
+ public void Should_Throw_If_RepositoryUrl_Is_Null()
+ {
+ // Given
+ Uri repositoryUrl = null;
+
+ // When
+ var result = Record.Exception(() => FileLinkSettings.ForGitHub(repositoryUrl));
+
+ // Then
+ result.IsArgumentNullException("repositoryUrl");
+ }
+ }
+
+ public sealed class TheForAzureDevOpsMethod
+ {
+ [Fact]
+ public void Should_Throw_If_RepositoryUrl_Is_Null()
+ {
+ // Given
+ Uri repositoryUrl = null;
+
+ // When
+ var result = Record.Exception(() => FileLinkSettings.ForAzureDevOps(repositoryUrl));
+
+ // Then
+ result.IsArgumentNullException("repositoryUrl");
+ }
+ }
+
+ public sealed class TheGetFileLinkMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue = null;
+
+ // When
+ var result = Record.Exception(() => FileLinkSettings.ForPattern("foo").GetFileLink(issue));
+
+ // Then
+ result.IsArgumentNullException("issue");
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.Tests/FileLinking/AzureDevOpsFileLinkSettingsBuilderTests.cs b/src/Cake.Issues.Tests/FileLinking/AzureDevOpsFileLinkSettingsBuilderTests.cs
new file mode 100644
index 000000000..cb9f18c89
--- /dev/null
+++ b/src/Cake.Issues.Tests/FileLinking/AzureDevOpsFileLinkSettingsBuilderTests.cs
@@ -0,0 +1,411 @@
+namespace Cake.Issues.Tests.FileLinking
+{
+ using System;
+ using Cake.Issues.FileLinking;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class AzureDevOpsFileLinkSettingsBuilderTests
+ {
+ public sealed class TheCtor
+ {
+ [Fact]
+ public void Should_Throw_If_RepositoryUrl_Is_Null()
+ {
+ // Given
+ Uri repositoryUrl = null;
+
+ // When
+ var result = Record.Exception(() => new AzureDevOpsFileLinkSettingsBuilder(repositoryUrl));
+
+ // Then
+ result.IsArgumentNullException("repositoryUrl");
+ }
+ }
+
+ public sealed class TheBranchMethod
+ {
+ [Fact]
+ public void Should_Throw_If_BranchName_Is_Null()
+ {
+ // Given
+ string branch = null;
+
+ // When
+ var result =
+ Record.Exception(() => new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com")).Branch(branch));
+
+ // Then
+ result.IsArgumentNullException("branchName");
+ }
+
+ [Fact]
+ public void Should_Throw_If_BranchName_Is_Empty()
+ {
+ // Given
+ var branch = string.Empty;
+
+ // When
+ var result =
+ Record.Exception(() => new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com")).Branch(branch));
+
+ // Then
+ result.IsArgumentOutOfRangeException("branchName");
+ }
+
+ [Fact]
+ public void Should_Throw_If_BranchName_Is_WhiteSpace()
+ {
+ // Given
+ var branch = " ";
+
+ // When
+ var result =
+ Record.Exception(() => new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com")).Branch(branch));
+
+ // Then
+ result.IsArgumentOutOfRangeException("branchName");
+ }
+
+ [Theory]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ 30,
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=30")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo/",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ 30,
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=30")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ null,
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=2147483647")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ null,
+ null,
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster&line=10&lineEnd=12&lineStartColumn=1&lineEndColumn=2147483647")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ null,
+ null,
+ null,
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster&line=10&lineEnd=10&lineStartColumn=1&lineEndColumn=2147483647")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ null,
+ null,
+ null,
+ null,
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster")]
+ [InlineData(
+ "http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ 30,
+ "master",
+ "http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=30")]
+ public void Should_Return_The_Correct_Link(
+ string repositoryUrl,
+ string filePath,
+ int? line,
+ int? endLine,
+ int? column,
+ int? endColumn,
+ string branch,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath, line, endLine, column, endColumn)
+ .Create();
+
+ // When
+ var result =
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Branch(branch)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+
+ [Theory]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "foo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "/foo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "foo/",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "foo/bar",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/bar/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ null,
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "master",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GBmaster")]
+ public void Should_Return_The_Correct_Link_For_RootPath(
+ string repositoryUrl,
+ string rootPath,
+ string filePath,
+ string branch,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath)
+ .Create();
+
+ // When
+ var result =
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Branch(branch)
+ .WithRootPath(rootPath)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+ }
+
+ public sealed class TheCommitMethod
+ {
+ [Fact]
+ public void Should_Throw_If_CommitId_Is_Null()
+ {
+ // Given
+ string commitId = null;
+
+ // When
+ var result =
+ Record.Exception(() => new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com")).Commit(commitId));
+
+ // Then
+ result.IsArgumentNullException("commitId");
+ }
+
+ [Fact]
+ public void Should_Throw_If_CommitId_Is_Empty()
+ {
+ // Given
+ var commitId = string.Empty;
+
+ // When
+ var result =
+ Record.Exception(() => new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com")).Commit(commitId));
+
+ // Then
+ result.IsArgumentOutOfRangeException("commitId");
+ }
+
+ [Fact]
+ public void Should_Throw_If_CommitId_Is_WhiteSpace()
+ {
+ // Given
+ var commitId = " ";
+
+ // When
+ var result =
+ Record.Exception(() => new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com")).Commit(commitId));
+
+ // Then
+ result.IsArgumentOutOfRangeException("commitId");
+ }
+
+ [Theory]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ 30,
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=30")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo/",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ 30,
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=30")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ null,
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=2147483647")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ null,
+ null,
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466&line=10&lineEnd=12&lineStartColumn=1&lineEndColumn=2147483647")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ null,
+ null,
+ null,
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466&line=10&lineEnd=10&lineStartColumn=1&lineEndColumn=2147483647")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ null,
+ null,
+ null,
+ null,
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466")]
+ [InlineData(
+ "http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ 10,
+ 12,
+ 20,
+ 30,
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "http://myserver:8080/tfs/defaultcollection/myproject/_git/myrepository?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466&line=10&lineEnd=12&lineStartColumn=20&lineEndColumn=30")]
+ public void Should_Return_The_Correct_Link(
+ string repositoryUrl,
+ string filePath,
+ int? line,
+ int? endLine,
+ int? column,
+ int? endColumn,
+ string commitId,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath, line, endLine, column, endColumn)
+ .Create();
+
+ // When
+ var result =
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Commit(commitId)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+
+ [Theory]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "foo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "/foo",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "foo/",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ "foo/bar",
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/foo/bar/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466")]
+ [InlineData(
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo",
+ null,
+ @"src\ClassLibrary1\ClassLibrary1.csproj",
+ "734bd70b03e45741426ed2916d1fa72c6ff20466",
+ "https://dev.azure.com/pberger/_git/Cake.Issues-Demo?path=/src/ClassLibrary1/ClassLibrary1.csproj&version=GC734bd70b03e45741426ed2916d1fa72c6ff20466")]
+ public void Should_Return_The_Correct_Link_For_RootPath(
+ string repositoryUrl,
+ string rootPath,
+ string filePath,
+ string commitId,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath)
+ .Create();
+
+ // When
+ var result =
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Commit(commitId)
+ .WithRootPath(rootPath)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.Tests/FileLinking/FileLinkOptionalSettingsBuilderTests.cs b/src/Cake.Issues.Tests/FileLinking/FileLinkOptionalSettingsBuilderTests.cs
new file mode 100644
index 000000000..75f48322e
--- /dev/null
+++ b/src/Cake.Issues.Tests/FileLinking/FileLinkOptionalSettingsBuilderTests.cs
@@ -0,0 +1,98 @@
+namespace Cake.Issues.Tests.FileLinking
+{
+ using System;
+ using System.Collections.Generic;
+ using Cake.Issues.FileLinking;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class FileLinkOptionalSettingsBuilderTests
+ {
+ public sealed class TheCtor
+ {
+ [Fact]
+ public void Should_Throw_If_Builder_Is_Null()
+ {
+ // Given
+ Func, Uri> builder = null;
+
+ // When
+ var result = Record.Exception(() => new FileLinkOptionalSettingsBuilder(builder));
+
+ // Then
+ result.IsArgumentNullException("builder");
+ }
+ }
+
+ public sealed class TheWithRootPathMethod
+ {
+ [Fact]
+ public void Should_Not_Throw_If_RootPath_Is_Null()
+ {
+ // Given
+ string rootPath = null;
+
+ // When
+ var result =
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com"))
+ .Branch("master")
+ .WithRootPath(rootPath);
+
+ // Then
+ result.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public void Should_Throw_If_RootPath_Is_Empty()
+ {
+ // Given
+ var rootPath = string.Empty;
+
+ // When
+ var result =
+ Record.Exception(() =>
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com"))
+ .Branch("master")
+ .WithRootPath(rootPath));
+
+ // Then
+ result.IsArgumentOutOfRangeException("rootPath");
+ }
+
+ [Fact]
+ public void Should_Throw_If_RootPath_Is_WhiteSpace()
+ {
+ // Given
+ var rootPath = " ";
+
+ // When
+ var result =
+ Record.Exception(() =>
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com"))
+ .Branch("master")
+ .WithRootPath(rootPath));
+
+ // Then
+ result.IsArgumentOutOfRangeException("rootPath");
+ }
+
+ [Theory]
+ [InlineData("foo\tbar")]
+ public void Should_Throw_If_RootPath_Is_Invalid(string rootPath)
+ {
+ // Given
+
+ // When
+ var result =
+ Record.Exception(() =>
+ new AzureDevOpsFileLinkSettingsBuilder(new Uri("https://github.com"))
+ .Branch("master")
+ .WithRootPath(rootPath));
+
+ // Then
+ result.IsArgumentException("rootPath");
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.Tests/FileLinking/GitHubFileLinkSettingsBuilderTests.cs b/src/Cake.Issues.Tests/FileLinking/GitHubFileLinkSettingsBuilderTests.cs
new file mode 100644
index 000000000..7db305c89
--- /dev/null
+++ b/src/Cake.Issues.Tests/FileLinking/GitHubFileLinkSettingsBuilderTests.cs
@@ -0,0 +1,339 @@
+namespace Cake.Issues.Tests.FileLinking
+{
+ using System;
+ using Cake.Issues.FileLinking;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class GitHubFileLinkSettingsBuilderTests
+ {
+ public sealed class TheCtor
+ {
+ [Fact]
+ public void Should_Throw_If_RepositoryUrl_Is_Null()
+ {
+ // Given
+ Uri repositoryUrl = null;
+
+ // When
+ var result = Record.Exception(() => new GitHubFileLinkSettingsBuilder(repositoryUrl));
+
+ // Then
+ result.IsArgumentNullException("repositoryUrl");
+ }
+ }
+
+ public sealed class TheBranchMethod
+ {
+ [Fact]
+ public void Should_Throw_If_BranchName_Is_Null()
+ {
+ // Given
+ string branch = null;
+
+ // When
+ var result =
+ Record.Exception(() => new GitHubFileLinkSettingsBuilder(new Uri("https://github.com")).Branch(branch));
+
+ // Then
+ result.IsArgumentNullException("branchName");
+ }
+
+ [Fact]
+ public void Should_Throw_If_BranchName_Is_Empty()
+ {
+ // Given
+ var branch = string.Empty;
+
+ // When
+ var result =
+ Record.Exception(() => new GitHubFileLinkSettingsBuilder(new Uri("https://github.com")).Branch(branch));
+
+ // Then
+ result.IsArgumentOutOfRangeException("branchName");
+ }
+
+ [Fact]
+ public void Should_Throw_If_BranchName_Is_WhiteSpace()
+ {
+ // Given
+ var branch = " ";
+
+ // When
+ var result =
+ Record.Exception(() => new GitHubFileLinkSettingsBuilder(new Uri("https://github.com")).Branch(branch));
+
+ // Then
+ result.IsArgumentOutOfRangeException("branchName");
+ }
+
+ [Theory]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ 10,
+ 12,
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/src/Cake.Issues/Cake.Issues.csproj#L10-L12")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ 10,
+ 12,
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/src/Cake.Issues/Cake.Issues.csproj#L10-L12")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ 10,
+ null,
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/src/Cake.Issues/Cake.Issues.csproj#L10")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ null,
+ null,
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/src/Cake.Issues/Cake.Issues.csproj")]
+ public void Should_Return_The_Correct_Link(
+ string repositoryUrl,
+ string filePath,
+ int? line,
+ int? endLine,
+ string branch,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath, line, endLine, null, null)
+ .Create();
+
+ // When
+ var result =
+ new GitHubFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Branch(branch)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+
+ [Theory]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "foo",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/foo/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "/foo",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/foo/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "foo/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/foo/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "foo/bar",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/foo/bar/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ null,
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "master",
+ "https://github.com/cake-contrib/Cake.Issues/blob/master/src/Cake.Issues/Cake.Issues.csproj")]
+ public void Should_Return_The_Correct_Link_For_RootPath(
+ string repositoryUrl,
+ string rootPath,
+ string filePath,
+ string branch,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath)
+ .Create();
+
+ // When
+ var result =
+ new GitHubFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Branch(branch)
+ .WithRootPath(rootPath)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+ }
+
+ public sealed class TheCommitMethod
+ {
+ [Fact]
+ public void Should_Throw_If_CommitId_Is_Null()
+ {
+ // Given
+ string commitId = null;
+
+ // When
+ var result =
+ Record.Exception(() => new GitHubFileLinkSettingsBuilder(new Uri("https://github.com")).Commit(commitId));
+
+ // Then
+ result.IsArgumentNullException("commitId");
+ }
+
+ [Fact]
+ public void Should_Throw_If_CommitId_Is_Empty()
+ {
+ // Given
+ var commitId = string.Empty;
+
+ // When
+ var result =
+ Record.Exception(() => new GitHubFileLinkSettingsBuilder(new Uri("https://github.com")).Commit(commitId));
+
+ // Then
+ result.IsArgumentOutOfRangeException("commitId");
+ }
+
+ [Fact]
+ public void Should_Throw_If_CommitId_Is_WhiteSpace()
+ {
+ // Given
+ var commitId = " ";
+
+ // When
+ var result =
+ Record.Exception(() => new GitHubFileLinkSettingsBuilder(new Uri("https://github.com")).Commit(commitId));
+
+ // Then
+ result.IsArgumentOutOfRangeException("commitId");
+ }
+
+ [Theory]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ 10,
+ 12,
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/src/Cake.Issues/Cake.Issues.csproj#L10-L12")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ 10,
+ 12,
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/src/Cake.Issues/Cake.Issues.csproj#L10-L12")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ 10,
+ null,
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/src/Cake.Issues/Cake.Issues.csproj#L10")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ null,
+ null,
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/src/Cake.Issues/Cake.Issues.csproj")]
+ public void Should_Return_The_Correct_Link(
+ string repositoryUrl,
+ string filePath,
+ int? line,
+ int? endLine,
+ string commitId,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath, line, endLine, null, null)
+ .OfRule("Foo")
+ .WithPriority(IssuePriority.Warning)
+ .Create();
+
+ // When
+ var result =
+ new GitHubFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Commit(commitId)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+
+ [Theory]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "foo",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/foo/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "/foo",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/foo/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "foo/",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/foo/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ "foo/bar",
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/foo/bar/src/Cake.Issues/Cake.Issues.csproj")]
+ [InlineData(
+ "https://github.com/cake-contrib/Cake.Issues/",
+ null,
+ @"src\Cake.Issues\Cake.Issues.csproj",
+ "6d035013812a4a3ab8be5e84c0f2a8b5ce60720a",
+ "https://github.com/cake-contrib/Cake.Issues/blob/6d035013812a4a3ab8be5e84c0f2a8b5ce60720a/src/Cake.Issues/Cake.Issues.csproj")]
+ public void Should_Return_The_Correct_Link_For_RootPath(
+ string repositoryUrl,
+ string rootPath,
+ string filePath,
+ string commitId,
+ string expectedLink)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath)
+ .Create();
+
+ // When
+ var result =
+ new GitHubFileLinkSettingsBuilder(new Uri(repositoryUrl))
+ .Commit(commitId)
+ .WithRootPath(rootPath)
+ .GetFileLink(issue);
+
+ // Then
+ result.ToString().ShouldBe(expectedLink);
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.Tests/FileLinking/IDictionaryExtensionsTests.cs b/src/Cake.Issues.Tests/FileLinking/IDictionaryExtensionsTests.cs
new file mode 100644
index 000000000..430b7705d
--- /dev/null
+++ b/src/Cake.Issues.Tests/FileLinking/IDictionaryExtensionsTests.cs
@@ -0,0 +1,55 @@
+namespace Cake.Issues.Tests.FileLinking
+{
+ using Cake.Issues.FileLinking;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class IDictionaryExtensionsTests
+ {
+ public sealed class TheGetValueOrDefaultExtension
+ {
+ [Fact]
+ public void Should_Throw_If_Dictionary_Is_Null()
+ {
+ // Given
+ System.Collections.Generic.IDictionary dictionary = null;
+
+ // When
+ var result = Record.Exception(() => dictionary.GetValueOrDefault("foo", null));
+
+ // Then
+ result.IsArgumentNullException("dictionary");
+ }
+
+ [Fact]
+ public void Should_Return_Value_If_Exists()
+ {
+ // Given
+ var key = "foo";
+ var value = "bar";
+ var dictionary = new System.Collections.Generic.Dictionary { { key, value } };
+
+ // When
+ var result = dictionary.GetValueOrDefault(key, null);
+
+ // Then
+ result.ShouldBe(value);
+ }
+
+ [Fact]
+ public void Should_Return_DefaultValue_If_Value_Does_Not_Exist()
+ {
+ // Given
+ var defaultValue = "defaultValue";
+ var dictionary = new System.Collections.Generic.Dictionary { { "foo", "bar" } };
+
+ // When
+ var result = dictionary.GetValueOrDefault("bar", defaultValue);
+
+ // Then
+ result.ShouldBe(defaultValue);
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues.Tests/IIssueComparerTests.cs b/src/Cake.Issues.Tests/IIssueComparerTests.cs
index 169003a5a..ab0f7ed2c 100644
--- a/src/Cake.Issues.Tests/IIssueComparerTests.cs
+++ b/src/Cake.Issues.Tests/IIssueComparerTests.cs
@@ -131,6 +131,65 @@ public void Should_Return_False_If_Line_Is_Different(int? line1, int? line2)
CompareIssues(issue1, issue2, false);
}
+ [Theory]
+ [InlineData(1, 2)]
+ [InlineData(1, null)]
+ [InlineData(null, 1)]
+ [InlineData(int.MaxValue, 1)]
+ [InlineData(1, int.MaxValue)]
+ public void Should_Return_False_If_Column_Is_Different(int? column1, int? column2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://bar")]
+ [InlineData("http://foo", null)]
+ [InlineData(null, "http://foo")]
+ public void Should_Return_False_If_FileLink_Is_Different(string fileLink1, string fileLink2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink1))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink2))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
[Fact]
public void Should_Return_False_If_MessageText_Is_Different()
{
@@ -268,7 +327,7 @@ public void Should_Return_False_If_Rule_Is_Different(string rule1, string rule2)
[InlineData("http://foo", "http://bar")]
[InlineData("http://foo", null)]
[InlineData(null, "http://foo")]
- public void Should_Return_False_If_RuleUlr_Is_Different(string ruleUrl1, string ruleUrl2)
+ public void Should_Return_False_If_RuleUrl_Is_Different(string ruleUrl1, string ruleUrl2)
{
// Given
var issueBuilder =
@@ -333,6 +392,25 @@ public void Should_Return_False_If_ProviderName_Is_Different()
CompareIssues(issue1, issue2, false);
}
+ [Fact]
+ public void Should_Return_False_If_Run_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run1")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run2")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
[Fact]
public void Should_Return_True_If_Same_Reference()
{
@@ -467,6 +545,63 @@ public void Should_Return_True_If_Line_Is_Same(int? line1, int? line2)
CompareIssues(issue1, issue2, true);
}
+ [Theory]
+ [InlineData(1, 1)]
+ [InlineData(null, null)]
+ [InlineData(int.MaxValue, int.MaxValue)]
+ public void Should_Return_True_If_Column_Is_Same(int? column1, int? column2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://foo")]
+ [InlineData("http://foo", "http://Foo")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_FileLink_Is_Same(string fileLink1, string fileLink2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink1))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink2))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
[Fact]
public void Should_Return_True_If_MessageText_Is_Same()
{
@@ -600,7 +735,7 @@ public void Should_Return_True_If_Rule_Is_Same(string rule1, string rule2)
[InlineData("http://foo", "http://foo")]
[InlineData("http://foo", "http://Foo")]
[InlineData(null, null)]
- public void Should_Return_True_If_RuleUlr_Is_Same(string ruleUrl1, string ruleUrl2)
+ public void Should_Return_True_If_RuleUrl_Is_Same(string ruleUrl1, string ruleUrl2)
{
// Given
var issueBuilder =
@@ -665,6 +800,25 @@ public void Should_Return_True_If_ProviderName_Is_Same()
CompareIssues(issue1, issue2, true);
}
+ [Fact]
+ public void Should_Return_True_If_Run_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
[Fact]
public void Should_Remove_Identical_Issues_From_List_Of_Issues()
{
@@ -904,7 +1058,7 @@ public void Should_Return_False_If_Rule_Is_Different(string rule1, string rule2)
[InlineData("http://foo", "http://bar")]
[InlineData("http://foo", null)]
[InlineData(null, "http://foo")]
- public void Should_Return_False_If_RuleUlr_Is_Different(string ruleUrl1, string ruleUrl2)
+ public void Should_Return_False_If_RuleUrl_Is_Different(string ruleUrl1, string ruleUrl2)
{
// Given
var issueBuilder =
@@ -969,6 +1123,25 @@ public void Should_Return_False_If_ProviderName_Is_Different()
CompareIssues(issue1, issue2, false);
}
+ [Fact]
+ public void Should_Return_False_If_Run_Is_Different()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run1")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run2")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, false);
+ }
+
[Fact]
public void Should_Return_True_If_Same_Reference()
{
@@ -1173,6 +1346,122 @@ public void Should_Return_True_If_Line_Is_Same(int? line1, int? line2)
CompareIssues(issue1, issue2, true);
}
+ [Theory]
+ [InlineData(1, 2)]
+ [InlineData(1, null)]
+ [InlineData(null, 1)]
+ [InlineData(int.MaxValue, 1)]
+ [InlineData(1, int.MaxValue)]
+ public void Should_Return_True_If_Column_Is_Different(int? column1, int? column2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData(1, 1)]
+ [InlineData(null, null)]
+ [InlineData(int.MaxValue, int.MaxValue)]
+ public void Should_Return_True_If_Column_Is_Same(int? column1, int? column2)
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column1)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile("foo", 42, column2)
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://bar")]
+ [InlineData("http://foo", null)]
+ [InlineData(null, "http://foo")]
+ public void Should_Return_True_If_FileLink_Is_Different(string fileLink1, string fileLink2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink1))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink2))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
+ [Theory]
+ [InlineData("http://foo", "http://foo")]
+ [InlineData("http://foo", "http://Foo")]
+ [InlineData(null, null)]
+ public void Should_Return_True_If_FileLink_Is_Same(string fileLink1, string fileLink2)
+ {
+ // Given
+ var issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink1))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink1));
+ }
+
+ var issue1 = issueBuilder.Create();
+
+ issueBuilder =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName");
+ if (!string.IsNullOrEmpty(fileLink2))
+ {
+ issueBuilder =
+ issueBuilder
+ .WithFileLink(new Uri(fileLink2));
+ }
+
+ var issue2 = issueBuilder.Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
[Fact]
public void Should_Return_True_If_MessageText_Is_Same()
{
@@ -1306,7 +1595,7 @@ public void Should_Return_True_If_Rule_Is_Same(string rule1, string rule2)
[InlineData("http://foo", "http://foo")]
[InlineData("http://foo", "http://Foo")]
[InlineData(null, null)]
- public void Should_Return_True_If_RuleUlr_Is_Same(string ruleUrl1, string ruleUrl2)
+ public void Should_Return_True_If_RuleUrl_Is_Same(string ruleUrl1, string ruleUrl2)
{
// Given
var issueBuilder =
@@ -1371,6 +1660,25 @@ public void Should_Return_True_If_ProviderName_Is_Same()
CompareIssues(issue1, issue2, true);
}
+ [Fact]
+ public void Should_Return_True_If_Run_Is_Same()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run")
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun("run")
+ .Create();
+
+ // When / Then
+ CompareIssues(issue1, issue2, true);
+ }
+
[Fact]
public void Should_Remove_Identical_Issues_From_List_Of_Issues()
{
diff --git a/src/Cake.Issues.Tests/IIssueExtensionsTests.cs b/src/Cake.Issues.Tests/IIssueExtensionsTests.cs
index c444ac375..ca488dbef 100644
--- a/src/Cake.Issues.Tests/IIssueExtensionsTests.cs
+++ b/src/Cake.Issues.Tests/IIssueExtensionsTests.cs
@@ -7,6 +7,98 @@
public sealed class IIssueExtensionsTests
{
+ public sealed class TheLineRangeExtension
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue = null;
+
+ // When
+ var result = Record.Exception(() => issue.LineRange());
+
+ // Then
+ result.IsArgumentNullException("issue");
+ }
+
+ [Theory]
+ [InlineData(null, null, null, null, "")]
+ [InlineData(10, null, null, null, "10")]
+ [InlineData(23, 42, null, null, "23-42")]
+ [InlineData(23, 42, 5, null, "23:5-42")]
+ [InlineData(23, 42, 5, 10, "23:5-42:10")]
+ public void Should_Return_Correct_LineRange(
+ int? startLine,
+ int? endLine,
+ int? startColumn,
+ int? endColumn,
+ string expectedLineRange)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Message Foo", "ProviderType Foo", "ProviderName Foo")
+ .InFile("foo.ch", startLine, endLine, startColumn, endColumn)
+ .Create();
+
+ // When
+ var result = issue.LineRange();
+
+ // Then
+ result.ShouldBe(expectedLineRange);
+ }
+ }
+
+ public sealed class TheLineRangeExtensionWithAddColumnParameter
+ {
+ [Fact]
+ public void Should_Throw_If_Issue_Is_Null()
+ {
+ // Given
+ IIssue issue = null;
+
+ // When
+ var result = Record.Exception(() => issue.LineRange(false));
+
+ // Then
+ result.IsArgumentNullException("issue");
+ }
+
+ [Theory]
+ [InlineData(null, null, null, null, true, "")]
+ [InlineData(10, null, null, null, true, "10")]
+ [InlineData(23, 42, null, null, true, "23-42")]
+ [InlineData(23, 42, 5, null, true, "23:5-42")]
+ [InlineData(23, 42, 5, 10, true, "23:5-42:10")]
+ [InlineData(null, null, null, null, false, "")]
+ [InlineData(10, null, null, null, false, "10")]
+ [InlineData(23, 42, null, null, false, "23-42")]
+ [InlineData(23, 42, 5, null, false, "23-42")]
+ [InlineData(23, 42, 5, 10, false, "23-42")]
+ public void Should_Return_Correct_LineRange(
+ int? startLine,
+ int? endLine,
+ int? startColumn,
+ int? endColumn,
+ bool addColumnInformation,
+ string expectedLineRange)
+ {
+ // Given
+ var issue =
+ IssueBuilder
+ .NewIssue("Message Foo", "ProviderType Foo", "ProviderName Foo")
+ .InFile("foo.ch", startLine, endLine, startColumn, endColumn)
+ .Create();
+
+ // When
+ var result = issue.LineRange(addColumnInformation);
+
+ // Then
+ result.ShouldBe(expectedLineRange);
+ }
+ }
+
public sealed class TheProjectPathExtension
{
[Fact]
@@ -297,6 +389,8 @@ public void Should_Throw_If_Issue_Is_Null()
[InlineData("{foo}", "{foo}")]
[InlineData("foo {ProviderType} bar", "foo ProviderType Foo bar")]
[InlineData("foo {ProviderName} bar", "foo ProviderName Foo bar")]
+ [InlineData("foo {Run} bar", "foo Run bar")]
+ [InlineData("foo {Identifier} bar", "foo Identifier Foo bar")]
[InlineData("foo {Priority} bar", "foo 400 bar")]
[InlineData("foo {PriorityName} bar", "foo Error bar")]
[InlineData("foo {ProjectPath} bar", "foo src/Cake.Issues/Cake.Issues.csproj bar")]
@@ -306,6 +400,10 @@ public void Should_Throw_If_Issue_Is_Null()
[InlineData("foo {FileDirectory} bar", "foo src/Cake.Issues bar")]
[InlineData("foo {FileName} bar", "foo foo.cs bar")]
[InlineData("foo {Line} bar", "foo 42 bar")]
+ [InlineData("foo {EndLine} bar", "foo 420 bar")]
+ [InlineData("foo {Column} bar", "foo 23 bar")]
+ [InlineData("foo {EndColumn} bar", "foo 230 bar")]
+ [InlineData("foo {FileLink} bar", "foo https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12 bar")]
[InlineData("foo {Rule} bar", "foo Rule Foo bar")]
[InlineData("foo {RuleUrl} bar", "foo https://google.com/ bar")]
[InlineData("foo {MessageText} bar", "foo MessageText Foo bar")]
@@ -316,11 +414,13 @@ public void Should_Replace_Tokens(string pattern, string expectedResult)
// Given
var issue =
IssueBuilder
- .NewIssue("MessageText Foo", "ProviderType Foo", "ProviderName Foo")
+ .NewIssue("Identifier Foo", "MessageText Foo", "ProviderType Foo", "ProviderName Foo")
+ .ForRun("Run")
.WithMessageInHtmlFormat("MessageHtml Foo")
.WithMessageInMarkdownFormat("MessageMarkdown Foo")
- .InFile(@"src/Cake.Issues/foo.cs", 42)
+ .InFile(@"src/Cake.Issues/foo.cs", 42, 420, 23, 230)
.InProject(@"src/Cake.Issues/Cake.Issues.csproj", "Cake.Issues")
+ .WithFileLink(new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12"))
.OfRule("Rule Foo", new Uri("https://google.com"))
.WithPriority(IssuePriority.Error)
.Create();
diff --git a/src/Cake.Issues.Tests/IssueBuilderFixture.cs b/src/Cake.Issues.Tests/IssueBuilderFixture.cs
index 7b5e1cbc0..c81ff3cf1 100644
--- a/src/Cake.Issues.Tests/IssueBuilderFixture.cs
+++ b/src/Cake.Issues.Tests/IssueBuilderFixture.cs
@@ -3,14 +3,14 @@
internal class IssueBuilderFixture
{
public IssueBuilderFixture()
- : this("Message", "ProviderType", "ProviderName")
+ : this("Identifier", "Message", "ProviderType", "ProviderName")
{
}
- public IssueBuilderFixture(string messageText, string providerType, string providerName)
+ public IssueBuilderFixture(string identifier, string messageText, string providerType, string providerName)
{
this.IssueBuilder =
- IssueBuilder.NewIssue(messageText, providerType, providerName);
+ IssueBuilder.NewIssue(identifier, messageText, providerType, providerName);
}
public IssueBuilder IssueBuilder { get; private set; }
diff --git a/src/Cake.Issues.Tests/IssueBuilderTests.cs b/src/Cake.Issues.Tests/IssueBuilderTests.cs
index d73fb1bf5..8ac9eec94 100644
--- a/src/Cake.Issues.Tests/IssueBuilderTests.cs
+++ b/src/Cake.Issues.Tests/IssueBuilderTests.cs
@@ -8,7 +8,7 @@
public sealed class IssueBuilderTests
{
- public sealed class TheNewIssueMethod
+ public sealed class TheNewIssueMethodWithMessageAsIdentifier
{
[Fact]
public void Should_Throw_If_Message_Is_Null()
@@ -153,20 +153,145 @@ public void Should_Throw_If_ProviderName_Is_WhiteSpace()
// Then
result.IsArgumentOutOfRangeException("providerName");
}
+
+ [Fact]
+ public void Should_Set_Identifier()
+ {
+ // Given
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.Identifier.ShouldBe(message);
+ }
+
+ [Fact]
+ public void Should_Set_Message()
+ {
+ // Given
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.MessageText.ShouldBe(message);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderType()
+ {
+ // Given
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.ProviderType.ShouldBe(providerType);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderName()
+ {
+ // Given
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.ProviderName.ShouldBe(providerName);
+ }
}
- public sealed class TheNewIssueOfTMethod
+ public sealed class TheNewIssueMethod
{
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_Null()
+ {
+ // Given
+ string identifier = null;
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentNullException("identifier");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_Empty()
+ {
+ // Given
+ var identifier = string.Empty;
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("identifier");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_WhiteSpace()
+ {
+ // Given
+ var identifier = " ";
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("identifier");
+ }
+
[Fact]
public void Should_Throw_If_Message_Is_Null()
{
// Given
+ var identifier = "Identifier";
string message = null;
- var issueProvider = new FakeIssueProvider(new FakeLog());
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
// When
var result = Record.Exception(() =>
- IssueBuilder.NewIssue(message, issueProvider));
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
// Then
result.IsArgumentNullException("message");
@@ -176,12 +301,14 @@ public void Should_Throw_If_Message_Is_Null()
public void Should_Throw_If_Message_Is_Empty()
{
// Given
+ var identifier = "Identifier";
var message = string.Empty;
- var issueProvider = new FakeIssueProvider(new FakeLog());
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
// When
var result = Record.Exception(() =>
- IssueBuilder.NewIssue(message, issueProvider));
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
// Then
result.IsArgumentOutOfRangeException("message");
@@ -191,313 +318,1206 @@ public void Should_Throw_If_Message_Is_Empty()
public void Should_Throw_If_Message_Is_WhiteSpace()
{
// Given
+ var identifier = "Identifier";
var message = " ";
- var issueProvider = new FakeIssueProvider(new FakeLog());
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
// When
var result = Record.Exception(() =>
- IssueBuilder.NewIssue(message, issueProvider));
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
// Then
result.IsArgumentOutOfRangeException("message");
}
[Fact]
- public void Should_Throw_If_IssueProvider_Is_Null()
+ public void Should_Throw_If_ProviderType_Is_Null()
{
// Given
+ var identifier = "Identifier";
var message = "Message";
- IIssueProvider issueProvider = null;
+ string providerType = null;
+ var providerName = "ProviderName";
// When
var result = Record.Exception(() =>
- IssueBuilder.NewIssue(message, issueProvider));
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
// Then
- result.IsArgumentNullException("issueProvider");
+ result.IsArgumentNullException("providerType");
+ }
+
+ [Fact]
+ public void Should_Throw_If_ProviderType_Is_Empty()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = string.Empty;
+ var providerName = "ProviderName";
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("providerType");
+ }
+
+ [Fact]
+ public void Should_Throw_If_ProviderType_Is_WhiteSpace()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = " ";
+ var providerName = "ProviderName";
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("providerType");
+ }
+
+ [Fact]
+ public void Should_Throw_If_ProviderName_Is_Null()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = "ProviderType";
+ string providerName = null;
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentNullException("providerName");
+ }
+
+ [Fact]
+ public void Should_Throw_If_ProviderName_Is_Empty()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = string.Empty;
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("providerName");
+ }
+
+ [Fact]
+ public void Should_Throw_If_ProviderName_Is_WhiteSpace()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = " ";
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, providerType, providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("providerName");
+ }
+
+ [Fact]
+ public void Should_Set_Identifier()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.Identifier.ShouldBe(identifier);
+ }
+
+ [Fact]
+ public void Should_Set_Message()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.MessageText.ShouldBe(message);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderType()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.ProviderType.ShouldBe(providerType);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderName()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, providerType, providerName)
+ .Create();
+
+ // Then
+ result.ProviderName.ShouldBe(providerName);
}
}
- public sealed class TheInProjectFileMethod
+ public sealed class TheNewIssueOfTMethodWithMessageAsIdentifier
{
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_Null()
+ public void Should_Throw_If_Message_Is_Null()
{
// Given
- var fixture = new IssueBuilderFixture();
- string projectPath = null;
+ string message = null;
+ var issueProvider = new FakeIssueProvider(new FakeLog());
// When
- var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(message, issueProvider));
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ result.IsArgumentNullException("message");
}
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_Empty()
+ public void Should_Throw_If_Message_Is_Empty()
+ {
+ // Given
+ var message = string.Empty;
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(message, issueProvider));
+
+ // Then
+ result.IsArgumentOutOfRangeException("message");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Message_Is_WhiteSpace()
+ {
+ // Given
+ var message = " ";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(message, issueProvider));
+
+ // Then
+ result.IsArgumentOutOfRangeException("message");
+ }
+
+ [Fact]
+ public void Should_Throw_If_IssueProvider_Is_Null()
+ {
+ // Given
+ var message = "Message";
+ IIssueProvider issueProvider = null;
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(message, issueProvider));
+
+ // Then
+ result.IsArgumentNullException("issueProvider");
+ }
+
+ [Fact]
+ public void Should_Set_Identifier()
+ {
+ // Given
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, issueProvider)
+ .Create();
+
+ // Then
+ result.Identifier.ShouldBe(message);
+ }
+
+ [Fact]
+ public void Should_Set_Message()
+ {
+ // Given
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, issueProvider)
+ .Create();
+
+ // Then
+ result.MessageText.ShouldBe(message);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderType()
+ {
+ // Given
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, issueProvider)
+ .Create();
+
+ // Then
+ result.ProviderType.ShouldBe(issueProvider.GetType().FullName);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderName()
+ {
+ // Given
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(message, issueProvider)
+ .Create();
+
+ // Then
+ result.ProviderName.ShouldBe(issueProvider.ProviderName);
+ }
+ }
+
+ public sealed class TheNewIssueOfTMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_Null()
+ {
+ // Given
+ string identifier = null;
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, issueProvider));
+
+ // Then
+ result.IsArgumentNullException("identifier");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_Empty()
+ {
+ // Given
+ var identifier = string.Empty;
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, issueProvider));
+
+ // Then
+ result.IsArgumentOutOfRangeException("identifier");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_WhiteSpace()
+ {
+ // Given
+ var identifier = " ";
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, issueProvider));
+
+ // Then
+ result.IsArgumentOutOfRangeException("identifier");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Message_Is_Null()
+ {
+ // Given
+ var identifier = "Identifier";
+ string message = null;
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, issueProvider));
+
+ // Then
+ result.IsArgumentNullException("message");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Message_Is_Empty()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = string.Empty;
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, issueProvider));
+
+ // Then
+ result.IsArgumentOutOfRangeException("message");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Message_Is_WhiteSpace()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = " ";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, issueProvider));
+
+ // Then
+ result.IsArgumentOutOfRangeException("message");
+ }
+
+ [Fact]
+ public void Should_Throw_If_IssueProvider_Is_Null()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ IIssueProvider issueProvider = null;
+
+ // When
+ var result = Record.Exception(() =>
+ IssueBuilder.NewIssue(identifier, message, issueProvider));
+
+ // Then
+ result.IsArgumentNullException("issueProvider");
+ }
+
+ [Fact]
+ public void Should_Set_Identifier()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, issueProvider)
+ .Create();
+
+ // Then
+ result.Identifier.ShouldBe(identifier);
+ }
+
+ [Fact]
+ public void Should_Set_Message()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, issueProvider)
+ .Create();
+
+ // Then
+ result.MessageText.ShouldBe(message);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderType()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, issueProvider)
+ .Create();
+
+ // Then
+ result.ProviderType.ShouldBe(issueProvider.GetType().FullName);
+ }
+
+ [Fact]
+ public void Should_Set_ProviderName()
+ {
+ // Given
+ var identifier = "Identifier";
+ var message = "Message";
+ var issueProvider = new FakeIssueProvider(new FakeLog());
+
+ // When
+ var result =
+ IssueBuilder
+ .NewIssue(identifier, message, issueProvider)
+ .Create();
+
+ // Then
+ result.ProviderName.ShouldBe(issueProvider.ProviderName);
+ }
+ }
+
+ public sealed class TheInProjectFileMethod
+ {
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_Null()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ string projectPath = null;
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_Empty()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectPath = string.Empty;
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Path_Which_Are_WhiteSpace()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectPath = " ";
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Theory]
+ [InlineData(@"src/project.csproj")]
+ public void Should_Set_ProjectFileRelativePath(string projectPath)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ToString().ShouldBe(projectPath);
+ }
+ }
+
+ public sealed class TheInProjectOfNameMethod
+ {
+ [Fact]
+ public void Should_Handle_Project_Names_Which_Are_Null()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ string projectName = null;
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Names_Which_Are_Empty()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectName = string.Empty;
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Names_Which_Are_WhiteSpace()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectName = " ";
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Theory]
+ [InlineData("project")]
+ public void Should_Set_ProjectName(string projectName)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+ }
+
+ public sealed class TheInProjectMethod
+ {
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_Null()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ string projectPath = null;
+ var projectName = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_Empty()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectPath = string.Empty;
+ var projectName = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectPath = " ";
+ var projectName = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Names_Which_Are_Null()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ string projectName = null;
+ var projectPath = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Names_Which_Are_Empty()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectName = string.Empty;
+ var projectPath = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Names_Which_Are_WhiteSpace()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectName = " ";
+ var projectPath = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Theory]
+ [InlineData(@"src/project.csproj")]
+ public void Should_Set_ProjectFileRelativePath(string projectPath)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectName = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectFileRelativePath.ToString().ShouldBe(projectPath);
+ }
+
+ [Theory]
+ [InlineData("project")]
+ public void Should_Set_ProjectName(string projectName)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ var projectPath = "foo";
+
+ // When
+ var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+ }
+
+ public sealed class TheInFileMethod
+ {
+ [Fact]
+ public void Should_Handle_File_Paths_Which_Are_Null()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InFile(null).Create();
+
+ // Then
+ issue.AffectedFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_File_Paths_Which_Are_Empty()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InFile(string.Empty).Create();
+
+ // Then
+ issue.AffectedFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InFile(" ").Create();
+
+ // Then
+ issue.AffectedFileRelativePath.ShouldBe(null);
+ }
+
+ [Theory]
+ [InlineData(@"foo", @"foo")]
+ [InlineData(@"foo\bar", @"foo/bar")]
+ [InlineData(@"foo/bar", @"foo/bar")]
+ [InlineData(@"foo\bar\", @"foo/bar")]
+ [InlineData(@"foo/bar/", @"foo/bar")]
+ [InlineData(@".\foo", @"foo")]
+ [InlineData(@"./foo", @"foo")]
+ [InlineData(@"foo\..\bar", @"foo/../bar")]
+ [InlineData(@"foo/../bar", @"foo/../bar")]
+ public void Should_Set_FilePath(string filePath, string expectedFilePath)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InFile(filePath).Create();
+
+ // Then
+ issue.AffectedFileRelativePath.ToString().ShouldBe(expectedFilePath);
+ issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "File path was not set as relative.");
+ }
+ }
+
+ public sealed class TheInFileLineMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Line_Is_Negative()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", -1));
+
+ // Then
+ result.IsArgumentOutOfRangeException("line");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Line_Is_Zero()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 0));
+
+ // Then
+ result.IsArgumentOutOfRangeException("line");
+ }
+
+ [Fact]
+ public void Should_Handle_Line_Which_Is_Null()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InFile("foo", null).Create();
+
+ // Then
+ issue.Line.ShouldBe(null);
+ }
+
+ [Theory]
+ [InlineData(@"foo", @"foo")]
+ [InlineData(@"foo\bar", @"foo/bar")]
+ [InlineData(@"foo/bar", @"foo/bar")]
+ [InlineData(@"foo\bar\", @"foo/bar")]
+ [InlineData(@"foo/bar/", @"foo/bar")]
+ [InlineData(@".\foo", @"foo")]
+ [InlineData(@"./foo", @"foo")]
+ [InlineData(@"foo\..\bar", @"foo/../bar")]
+ [InlineData(@"foo/../bar", @"foo/../bar")]
+ public void Should_Set_FilePath(string filePath, string expectedFilePath)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InFile(filePath, 10).Create();
+
+ // Then
+ issue.AffectedFileRelativePath.ToString().ShouldBe(expectedFilePath);
+ issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "File path was not set as relative.");
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_Line(int line)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.InFile("foo", line).Create();
+
+ // Then
+ issue.Line.ShouldBe(line);
+ }
+ }
+
+ public sealed class TheInFileLineColumnMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Line_Is_Negative()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", -1, 50));
+
+ // Then
+ result.IsArgumentOutOfRangeException("line");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Line_Is_Zero()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 0, 50));
+
+ // Then
+ result.IsArgumentOutOfRangeException("line");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Column_Is_Negative()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 100, -1));
+
+ // Then
+ result.IsArgumentOutOfRangeException("column");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Column_Is_Zero()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectPath = string.Empty;
// When
- var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 100, 0));
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("column");
}
[Fact]
- public void Should_Handle_Project_Path_Which_Are_WhiteSpace()
+ public void Should_Handle_Line_Which_Is_Null()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectPath = " ";
// When
- var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", null, null).Create();
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ issue.Line.ShouldBe(null);
}
- [Theory]
- [InlineData(@"src/project.csproj")]
- public void Should_Set_ProjectFileRelativePath(string projectPath)
+ [Fact]
+ public void Should_Handle_Column_Which_Is_Null()
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InProjectFile(projectPath).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", 100, null).Create();
// Then
- issue.ProjectFileRelativePath.ToString().ShouldBe(projectPath);
+ issue.Column.ShouldBe(null);
}
- }
- public sealed class TheInProjectOfNameMethod
- {
- [Fact]
- public void Should_Handle_Project_Names_Which_Are_Null()
+ [Theory]
+ [InlineData(@"foo", @"foo")]
+ [InlineData(@"foo\bar", @"foo/bar")]
+ [InlineData(@"foo/bar", @"foo/bar")]
+ [InlineData(@"foo\bar\", @"foo/bar")]
+ [InlineData(@"foo/bar/", @"foo/bar")]
+ [InlineData(@".\foo", @"foo")]
+ [InlineData(@"./foo", @"foo")]
+ [InlineData(@"foo\..\bar", @"foo/../bar")]
+ [InlineData(@"foo/../bar", @"foo/../bar")]
+ public void Should_Set_FilePath(string filePath, string expectedFilePath)
{
// Given
var fixture = new IssueBuilderFixture();
- string projectName = null;
// When
- var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+ var issue = fixture.IssueBuilder.InFile(filePath, 10, 50).Create();
// Then
- issue.ProjectName.ShouldBe(projectName);
+ issue.AffectedFileRelativePath.ToString().ShouldBe(expectedFilePath);
+ issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "File path was not set as relative.");
}
- [Fact]
- public void Should_Handle_Project_Names_Which_Are_Empty()
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_Line(int line)
{
// Given
var fixture = new IssueBuilderFixture();
- var projectName = string.Empty;
// When
- var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", line, 50).Create();
// Then
- issue.ProjectName.ShouldBe(projectName);
+ issue.Line.ShouldBe(line);
}
- [Fact]
- public void Should_Handle_Project_Names_Which_Are_WhiteSpace()
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_Column(int column)
{
// Given
var fixture = new IssueBuilderFixture();
- var projectName = " ";
// When
- var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", 100, column).Create();
// Then
- issue.ProjectName.ShouldBe(projectName);
+ issue.Column.ShouldBe(column);
}
+ }
- [Theory]
- [InlineData("project")]
- public void Should_Set_ProjectName(string projectName)
+ public sealed class TheInFileLineRangeColumnRangeMethod
+ {
+ [Fact]
+ public void Should_Throw_If_StartLine_Is_Negative()
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InProjectOfName(projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", -1, 50, 1, 10));
// Then
- issue.ProjectName.ShouldBe(projectName);
+ result.IsArgumentOutOfRangeException("startLine");
}
- }
- public sealed class TheInProjectMethod
- {
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_Null()
+ public void Should_Throw_If_StartLine_Is_Zero()
{
// Given
var fixture = new IssueBuilderFixture();
- string projectPath = null;
- var projectName = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 0, 50, 1, 10));
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("startLine");
}
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_Empty()
+ public void Should_Throw_If_EndLine_Is_Negative()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectPath = string.Empty;
- var projectName = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 5, -1, 1, 10));
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("endLine");
}
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
+ public void Should_Throw_If_EndLine_Is_Zero()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectPath = " ";
- var projectName = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 5, 0, 1, 10));
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("endLine");
}
[Fact]
- public void Should_Handle_Project_Names_Which_Are_Null()
+ public void Should_Throw_If_StartColumn_Is_Negative()
{
// Given
var fixture = new IssueBuilderFixture();
- string projectName = null;
- var projectPath = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 5, 50, -1, 10));
// Then
- issue.ProjectName.ShouldBe(projectName);
+ result.IsArgumentOutOfRangeException("startColumn");
}
[Fact]
- public void Should_Handle_Project_Names_Which_Are_Empty()
+ public void Should_Throw_If_StartColumn_Is_Zero()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectName = string.Empty;
- var projectPath = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 5, 50, 0, 10));
// Then
- issue.ProjectName.ShouldBe(projectName);
+ result.IsArgumentOutOfRangeException("startColumn");
}
[Fact]
- public void Should_Handle_Project_Names_Which_Are_WhiteSpace()
+ public void Should_Throw_If_EndColumn_Is_Negative()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectName = " ";
- var projectPath = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 5, 50, 1, -1));
// Then
- issue.ProjectName.ShouldBe(projectName);
+ result.IsArgumentOutOfRangeException("endColumn");
}
- [Theory]
- [InlineData(@"src/project.csproj")]
- public void Should_Set_ProjectFileRelativePath(string projectPath)
+ [Fact]
+ public void Should_Throw_If_EndColumn_Is_Zero()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectName = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.InFile("foo", 5, 50, 1, 0));
// Then
- issue.ProjectFileRelativePath.ToString().ShouldBe(projectPath);
+ result.IsArgumentOutOfRangeException("endColumn");
}
- [Theory]
- [InlineData("project")]
- public void Should_Set_ProjectName(string projectName)
+ [Fact]
+ public void Should_Handle_StartLine_Which_Is_Null()
{
// Given
var fixture = new IssueBuilderFixture();
- var projectPath = "foo";
// When
- var issue = fixture.IssueBuilder.InProject(projectPath, projectName).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", null, null, null, null).Create();
// Then
- issue.ProjectName.ShouldBe(projectName);
+ issue.Line.ShouldBe(null);
}
- }
- public sealed class TheInFileMethod
- {
[Fact]
- public void Should_Handle_File_Paths_Which_Are_Null()
+ public void Should_Handle_EndLine_Which_Is_Null()
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile(null).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", 5, null, null, null).Create();
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ issue.EndLine.ShouldBe(null);
}
[Fact]
- public void Should_Handle_File_Paths_Which_Are_Empty()
+ public void Should_Handle_StartColumn_Which_Is_Null()
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile(string.Empty).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", 5, 50, null, null).Create();
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ issue.Column.ShouldBe(null);
}
[Fact]
- public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
+ public void Should_Handle_EndColumn_Which_Is_Null()
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile(" ").Create();
+ var issue = fixture.IssueBuilder.InFile("foo", 5, 50, 1, null).Create();
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ issue.EndColumn.ShouldBe(null);
}
[Theory]
@@ -516,132 +1536,103 @@ public void Should_Set_FilePath(string filePath, string expectedFilePath)
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile(filePath).Create();
+ var issue = fixture.IssueBuilder.InFile(filePath, 5, 50, 1, 10).Create();
// Then
issue.AffectedFileRelativePath.ToString().ShouldBe(expectedFilePath);
issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "File path was not set as relative.");
}
- }
- public sealed class TheInFileLineMethod
- {
- [Fact]
- public void Should_Handle_File_Paths_Which_Are_Null()
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_StartLine(int startLine)
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile(null).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", startLine, null, 1, 10).Create();
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ issue.Line.ShouldBe(startLine);
}
- [Fact]
- public void Should_Handle_File_Paths_Which_Are_Empty()
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_EndLine(int endLine)
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile(string.Empty).Create();
+ var issue = fixture.IssueBuilder.InFile("foo", 1, endLine, 1, 10).Create();
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ issue.EndLine.ShouldBe(endLine);
}
- [Fact]
- public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_StartColumn(int startColumn)
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile(" ").Create();
+ var issue = fixture.IssueBuilder.InFile("foo", 5, 50, startColumn, null).Create();
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ issue.Column.ShouldBe(startColumn);
}
- [Fact]
- public void Should_Throw_If_Line_Is_Negative()
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_EndColumn(int endColumn)
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var result = Record.Exception(() =>
- fixture.IssueBuilder.InFile("foo", -1));
+ var issue = fixture.IssueBuilder.InFile("foo", 5, 50, 1, endColumn).Create();
// Then
- result.IsArgumentOutOfRangeException("line");
+ issue.EndColumn.ShouldBe(endColumn);
}
+ }
+ public sealed class TheWithFileLinkMethod
+ {
[Fact]
- public void Should_Throw_If_Line_Is_Zero()
+ public void Should_Throw_If_FileLink_Is_Null()
{
// Given
var fixture = new IssueBuilderFixture();
+ Uri fileLink = null;
// When
var result = Record.Exception(() =>
- fixture.IssueBuilder.InFile("foo", 0));
-
- // Then
- result.IsArgumentOutOfRangeException("line");
- }
-
- [Fact]
- public void Should_Handle_Line_Which_Is_Null()
- {
- // Given
- var fixture = new IssueBuilderFixture();
-
- // When
- var issue = fixture.IssueBuilder.InFile("foo", null).Create();
-
- // Then
- issue.Line.ShouldBe(null);
- }
-
- [Theory]
- [InlineData(@"foo", @"foo")]
- [InlineData(@"foo\bar", @"foo/bar")]
- [InlineData(@"foo/bar", @"foo/bar")]
- [InlineData(@"foo\bar\", @"foo/bar")]
- [InlineData(@"foo/bar/", @"foo/bar")]
- [InlineData(@".\foo", @"foo")]
- [InlineData(@"./foo", @"foo")]
- [InlineData(@"foo\..\bar", @"foo/../bar")]
- [InlineData(@"foo/../bar", @"foo/../bar")]
- public void Should_Set_FilePath(string filePath, string expectedFilePath)
- {
- // Given
- var fixture = new IssueBuilderFixture();
-
- // When
- var issue = fixture.IssueBuilder.InFile(filePath, 10).Create();
+ fixture.IssueBuilder.WithFileLink(fileLink));
// Then
- issue.AffectedFileRelativePath.ToString().ShouldBe(expectedFilePath);
- issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "File path was not set as relative.");
+ result.IsArgumentNullException("fileLink");
}
[Theory]
- [InlineData(1)]
- [InlineData(int.MaxValue)]
- public void Should_Set_Line(int line)
+ [InlineData("https://google.com/")]
+ public void Should_Set_FileLink(string fileLink)
{
// Given
var fixture = new IssueBuilderFixture();
// When
- var issue = fixture.IssueBuilder.InFile("foo", line).Create();
+ var issue = fixture.IssueBuilder.WithFileLink(new Uri(fileLink)).Create();
// Then
- issue.Line.ShouldBe(line);
+ issue.FileLink.ToString().ShouldBe(fileLink);
}
}
@@ -902,5 +1893,67 @@ public void Should_Set_RuleUrl(string ruleUri)
issue.RuleUrl.ToString().ShouldBe(ruleUri);
}
}
+
+ public sealed class TheForRunMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Run_Is_Null()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ string run = null;
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.ForRun(run));
+
+ // Then
+ result.IsArgumentNullException("run");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Run_Is_Empty()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ string run = string.Empty;
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.ForRun(run));
+
+ // Then
+ result.IsArgumentException("run");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Run_Is_WhiteSpace()
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+ string run = " ";
+
+ // When
+ var result = Record.Exception(() =>
+ fixture.IssueBuilder.ForRun(run));
+
+ // Then
+ result.IsArgumentException("run");
+ }
+
+ [Theory]
+ [InlineData("run")]
+ public void Should_Set_Run(string run)
+ {
+ // Given
+ var fixture = new IssueBuilderFixture();
+
+ // When
+ var issue = fixture.IssueBuilder.ForRun(run).Create();
+
+ // Then
+ issue.Run.ToString().ShouldBe(run);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/IssueReaderTests.cs b/src/Cake.Issues.Tests/IssueReaderTests.cs
index 6a6696d62..de69051c1 100644
--- a/src/Cake.Issues.Tests/IssueReaderTests.cs
+++ b/src/Cake.Issues.Tests/IssueReaderTests.cs
@@ -288,6 +288,99 @@ public void Should_Read_Correct_Number_Of_Issues_From_Multiple_Providers()
issues.ShouldContain(issue3);
issues.ShouldContain(issue4);
}
+
+ [Fact]
+ public void Should_Set_Run_Property()
+ {
+ // Given
+ var issue1 =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(@"src\Cake.Issues.Tests\FakeIssueProvider.cs", 10)
+ .OfRule("Foo")
+ .WithPriority(IssuePriority.Warning)
+ .Create();
+ var issue2 =
+ IssueBuilder
+ .NewIssue("Bar", "ProviderTypeBar", "ProviderNameBar")
+ .InFile(@"src\Cake.Issues.Tests\FakeIssueProvider.cs", 12)
+ .OfRule("Bar")
+ .WithPriority(IssuePriority.Warning)
+ .Create();
+ var fixture = new IssuesFixture();
+ fixture.IssueProviders.Clear();
+ fixture.IssueProviders.Add(
+ new FakeIssueProvider(
+ fixture.Log,
+ new List
+ {
+ issue1,
+ issue2,
+ }));
+ var run = "Run";
+ fixture.Settings.Run = run;
+
+ // When
+ var issues = fixture.ReadIssues().ToList();
+
+ // Then
+ issues.Count.ShouldBe(2);
+ issues.ShouldContain(issue1);
+ issue1.Run.ShouldBe(run);
+ issues.ShouldContain(issue2);
+ issue2.Run.ShouldBe(run);
+ }
+
+ [Fact]
+ public void Should_Set_FileLink_Property()
+ {
+ // Given
+ var filePath1 = @"src\Cake.Issues.Tests\Foo.cs";
+ var line1 = 10;
+ var endLine1 = 12;
+ var issue1 =
+ IssueBuilder
+ .NewIssue("Foo", "ProviderTypeFoo", "ProviderNameFoo")
+ .InFile(filePath1, line1, endLine1, 1, 1)
+ .OfRule("Foo")
+ .WithPriority(IssuePriority.Warning)
+ .Create();
+ var filePath2 = @"src\Cake.Issues.Tests\Bar.cs";
+ var line2 = 12;
+ var issue2 =
+ IssueBuilder
+ .NewIssue("Bar", "ProviderTypeBar", "ProviderNameBar")
+ .InFile(filePath2, line2)
+ .OfRule("Bar")
+ .WithPriority(IssuePriority.Warning)
+ .Create();
+ var fixture = new IssuesFixture();
+ fixture.IssueProviders.Clear();
+ fixture.IssueProviders.Add(
+ new FakeIssueProvider(
+ fixture.Log,
+ new List
+ {
+ issue1,
+ issue2,
+ }));
+ var repoUrl = "https://github.com/cake-contrib/Cake.Issues.Website";
+ var branch = "develop";
+ fixture.Settings.FileLinkSettings =
+ FileLinkSettings.ForGitHub(new System.Uri(repoUrl)).Branch(branch);
+
+ // When
+ var issues = fixture.ReadIssues().ToList();
+
+ // Then
+ issues.Count.ShouldBe(2);
+ issues.ShouldContain(issue1);
+ issue1.FileLink.ToString()
+ .ShouldBe($"{repoUrl}/blob/{branch}/{filePath1.Replace(@"\", "/")}#L{line1}-L{endLine1}");
+ issues.ShouldContain(issue2);
+ issue2.FileLink.ToString()
+ .ShouldBe($"{repoUrl}/blob/{branch}/{filePath2.Replace(@"\", "/")}#L{line2}");
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/IssueTests.cs b/src/Cake.Issues.Tests/IssueTests.cs
index 5a5d9b7ea..5286a4aeb 100644
--- a/src/Cake.Issues.Tests/IssueTests.cs
+++ b/src/Cake.Issues.Tests/IssueTests.cs
@@ -9,6 +9,213 @@ public sealed class IssueTests
{
public sealed class TheCtor
{
+ public sealed class TheIdentifierArgument
+ {
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_Null()
+ {
+ // Given
+ string identifier = null;
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentNullException("identifier");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_Empty()
+ {
+ // Given
+ var identifier = string.Empty;
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("identifier");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Identifier_Is_WhiteSpace()
+ {
+ // Given
+ var identifier = " ";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("identifier");
+ }
+
+ [Theory]
+ [InlineData("identifier")]
+ public void Should_Set_Identifier(string identifier)
+ {
+ // Given
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.Identifier.ShouldBe(identifier);
+ }
+ }
+
public sealed class TheProjectFileRelativePathArgument
{
[Theory]
@@ -16,9 +223,1162 @@ public sealed class TheProjectFileRelativePathArgument
public void Should_Throw_If_Project_Path_Is_Invalid(string projectPath)
{
// Given
+ var identifier = "identifier";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentException("projectFileRelativePath");
+ }
+
+ [Theory]
+ [InlineData(@"c:\src\foo.cs")]
+ [InlineData(@"/foo")]
+ [InlineData(@"\foo")]
+ public void Should_Throw_If_File_Path_Is_Absolute(string projectPath)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("projectFileRelativePath");
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_Null()
+ {
+ // Given
+ var identifier = "identifier";
+ string projectPath = null;
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_Empty()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = string.Empty;
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = " ";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectFileRelativePath.ShouldBe(null);
+ }
+
+ [Theory]
+ [InlineData("project")]
+ public void Should_Set_ProjectFileRelativePath(string projectPath)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectFileRelativePath.ToString().ShouldBe(projectPath);
+ }
+ }
+
+ public sealed class TheProjectNameArgument
+ {
+ [Fact]
+ public void Should_Handle_Projects_Which_Are_Null()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ string projectName = null;
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Fact]
+ public void Should_Handle_Projects_Which_Are_Empty()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = string.Empty;
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Fact]
+ public void Should_Handle_Projects_Which_Are_WhiteSpace()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = " ";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+
+ [Theory]
+ [InlineData("project")]
+ public void Should_Set_ProjectName(string projectName)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.ProjectName.ShouldBe(projectName);
+ }
+ }
+
+ public sealed class TheAffectedFileRelativePathArgument
+ {
+ [Theory]
+ [InlineData("foo\tbar")]
+ public void Should_Throw_If_File_Path_Is_Invalid(string filePath)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentException("affectedFileRelativePath");
+ }
+
+ [Theory]
+ [InlineData(@"c:\src\foo.cs")]
+ [InlineData(@"/foo")]
+ [InlineData(@"\foo")]
+ public void Should_Throw_If_File_Path_Is_Absolute(string filePath)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("affectedFileRelativePath");
+ }
+
+ [Fact]
+ public void Should_Handle_File_Paths_Which_Are_Null()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ string filePath = null;
+ int? line = null;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ Uri fileLink = null;
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.AffectedFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_File_Paths_Which_Are_Empty()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = string.Empty;
+ int? line = null;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ Uri fileLink = null;
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.AffectedFileRelativePath.ShouldBe(null);
+ }
+
+ [Fact]
+ public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = " ";
+ int? line = null;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ Uri fileLink = null;
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.AffectedFileRelativePath.ShouldBe(null);
+ }
+
+ [Theory]
+ [InlineData(@"foo", @"foo")]
+ [InlineData(@"foo\bar", @"foo/bar")]
+ [InlineData(@"foo/bar", @"foo/bar")]
+ [InlineData(@"foo\bar\", @"foo/bar")]
+ [InlineData(@"foo/bar/", @"foo/bar")]
+ [InlineData(@".\foo", @"foo")]
+ [InlineData(@"./foo", @"foo")]
+ [InlineData(@"foo\..\bar", @"foo/../bar")]
+ [InlineData(@"foo/../bar", @"foo/../bar")]
+ public void Should_Set_File_Path(string filePath, string expectedFilePath)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.AffectedFileRelativePath.ToString().ShouldBe(expectedFilePath);
+ issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "File path was not set as relative.");
+ }
+ }
+
+ public sealed class TheLineArgument
+ {
+ [Fact]
+ public void Should_Throw_If_Line_Is_Negative()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = -1;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("line");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Line_Is_Zero()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 0;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("line");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Line_Is_Set_But_No_File()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ string filePath = null;
+ var line = 10;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ Uri fileLink = null;
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("line");
+ }
+
+ [Fact]
+ public void Should_Handle_Line_Which_Is_Null()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ int? line = null;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.Line.ShouldBe(line);
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_Line(int line)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ int? endLine = null;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.Line.ShouldBe(line);
+ }
+ }
+
+ public sealed class TheEndLineArgument
+ {
+ [Fact]
+ public void Should_Throw_If_EndLine_Is_Negative()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = -1;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+ var run = "Run";
+
+ // When
+ var result = Record.Exception(() =>
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName));
+
+ // Then
+ result.IsArgumentOutOfRangeException("endLine");
+ }
+
+ [Fact]
+ public void Should_Throw_If_EndLine_Is_Zero()
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
- var line = 100;
+ var line = 10;
+ var endLine = 0;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -28,14 +1388,20 @@ public void Should_Throw_If_Project_Path_Is_Invalid(string projectPath)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -43,23 +1409,27 @@ public void Should_Throw_If_Project_Path_Is_Invalid(string projectPath)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
// Then
- result.IsArgumentException("projectFileRelativePath");
+ result.IsArgumentOutOfRangeException("endLine");
}
- [Theory]
- [InlineData(@"c:\src\foo.cs")]
- [InlineData(@"/foo")]
- [InlineData(@"\foo")]
- public void Should_Throw_If_File_Path_Is_Absolute(string projectPath)
+ [Fact]
+ public void Should_Throw_If_EndLine_Is_Set_But_No_Line()
{
// Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
- var line = 100;
+ int? line = null;
+ var endLine = 12;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -69,14 +1439,20 @@ public void Should_Throw_If_File_Path_Is_Absolute(string projectPath)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -84,21 +1460,27 @@ public void Should_Throw_If_File_Path_Is_Absolute(string projectPath)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
// Then
- result.IsArgumentOutOfRangeException("projectFileRelativePath");
+ result.IsArgumentOutOfRangeException("endLine");
}
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_Null()
+ public void Should_Throw_If_EndLine_Is_Smaller_Line()
{
// Given
- string projectPath = null;
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
- var line = 10;
+ var line = 100;
+ var endLine = 12;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -108,14 +1490,20 @@ public void Should_Handle_Project_Paths_Which_Are_Null()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var issue =
+ var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -123,21 +1511,27 @@ public void Should_Handle_Project_Paths_Which_Are_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName);
+ providerName));
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("endLine");
}
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_Empty()
+ public void Should_Handle_EndLine_Which_Is_Null()
{
// Given
- var projectPath = string.Empty;
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ int? endLine = null;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -147,14 +1541,20 @@ public void Should_Handle_Project_Paths_Which_Are_Empty()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -162,21 +1562,27 @@ public void Should_Handle_Project_Paths_Which_Are_Empty()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ issue.EndLine.ShouldBe(endLine);
}
[Fact]
- public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
+ public void Should_Handle_EndLine_Which_Is_Equals_Line()
{
// Given
- var projectPath = " ";
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 10;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -186,14 +1592,20 @@ public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -201,21 +1613,28 @@ public void Should_Handle_Project_Paths_Which_Are_WhiteSpace()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
// Then
- issue.ProjectFileRelativePath.ShouldBe(null);
+ issue.EndLine.ShouldBe(endLine);
}
[Theory]
- [InlineData("project")]
- public void Should_Set_ProjectFileRelativePath(string projectPath)
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_EndLine(int endLine)
{
// Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
- var line = 10;
+ var line = 1;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -225,14 +1644,20 @@ public void Should_Set_ProjectFileRelativePath(string projectPath)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -240,24 +1665,30 @@ public void Should_Set_ProjectFileRelativePath(string projectPath)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
// Then
- issue.ProjectFileRelativePath.ToString().ShouldBe(projectPath);
+ issue.EndLine.ShouldBe(endLine);
}
}
- public sealed class TheProjectNameArgument
+ public sealed class TheColumnArgument
{
[Fact]
- public void Should_Handle_Projects_Which_Are_Null()
+ public void Should_Throw_If_Column_Is_Negative()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
- string projectName = null;
+ var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = -1;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -267,14 +1698,20 @@ public void Should_Handle_Projects_Which_Are_Null()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var issue =
+ var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -282,21 +1719,27 @@ public void Should_Handle_Projects_Which_Are_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName);
+ providerName));
// Then
- issue.ProjectName.ShouldBe(projectName);
+ result.IsArgumentOutOfRangeException("column");
}
[Fact]
- public void Should_Handle_Projects_Which_Are_Empty()
+ public void Should_Throw_If_Column_Is_Zero()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
- var projectName = string.Empty;
+ var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 0;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -306,14 +1749,20 @@ public void Should_Handle_Projects_Which_Are_Empty()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var issue =
+ var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -321,21 +1770,27 @@ public void Should_Handle_Projects_Which_Are_Empty()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName);
+ providerName));
// Then
- issue.ProjectName.ShouldBe(projectName);
+ result.IsArgumentOutOfRangeException("column");
}
[Fact]
- public void Should_Handle_Projects_Which_Are_WhiteSpace()
+ public void Should_Throw_If_Column_Is_Set_But_No_Line()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
- var projectName = " ";
+ var projectName = "foo";
var filePath = @"src\foo.cs";
- var line = 10;
+ int? line = null;
+ int? endLine = null;
+ var column = 50;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -345,14 +1800,20 @@ public void Should_Handle_Projects_Which_Are_WhiteSpace()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var issue =
+ var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -360,21 +1821,27 @@ public void Should_Handle_Projects_Which_Are_WhiteSpace()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName);
+ providerName));
// Then
- issue.ProjectName.ShouldBe(projectName);
+ result.IsArgumentOutOfRangeException("column");
}
- [Theory]
- [InlineData("project")]
- public void Should_Set_ProjectName(string projectName)
+ [Fact]
+ public void Should_Handle_Column_Which_Is_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -384,14 +1851,20 @@ public void Should_Set_ProjectName(string projectName)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -399,24 +1872,29 @@ public void Should_Set_ProjectName(string projectName)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
// Then
- issue.ProjectName.ShouldBe(projectName);
+ issue.Column.ShouldBe(column);
}
- }
- public sealed class TheAffectedFileRelativePathArgument
- {
[Theory]
- [InlineData("foo\tbar")]
- public void Should_Throw_If_File_Path_Is_Invalid(string filePath)
+ [InlineData(null)]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_Column(int? column)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
- var line = 100;
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -426,14 +1904,20 @@ public void Should_Throw_If_File_Path_Is_Invalid(string filePath)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var result = Record.Exception(() =>
+ var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -441,23 +1925,30 @@ public void Should_Throw_If_File_Path_Is_Invalid(string filePath)
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName));
+ providerName);
// Then
- result.IsArgumentException("affectedFileRelativePath");
+ issue.Column.ShouldBe(column);
}
+ }
- [Theory]
- [InlineData(@"c:\src\foo.cs")]
- [InlineData(@"/foo")]
- [InlineData(@"\foo")]
- public void Should_Throw_If_File_Path_Is_Absolute(string filePath)
+ public sealed class TheEndColumnArgument
+ {
+ [Fact]
+ public void Should_Throw_If_EndColumn_Is_Negative()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
- var line = 100;
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = -1;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -467,14 +1958,20 @@ public void Should_Throw_If_File_Path_Is_Absolute(string filePath)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -482,21 +1979,27 @@ public void Should_Throw_If_File_Path_Is_Absolute(string filePath)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
// Then
- result.IsArgumentOutOfRangeException("affectedFileRelativePath");
+ result.IsArgumentOutOfRangeException("endColumn");
}
[Fact]
- public void Should_Handle_File_Paths_Which_Are_Null()
+ public void Should_Throw_If_EndColumn_Is_Zero()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
- string filePath = null;
- int? line = null;
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 0;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -506,14 +2009,20 @@ public void Should_Handle_File_Paths_Which_Are_Null()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var issue =
+ var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -521,21 +2030,27 @@ public void Should_Handle_File_Paths_Which_Are_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName);
+ providerName));
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("endColumn");
}
[Fact]
- public void Should_Handle_File_Paths_Which_Are_Empty()
+ public void Should_Throw_If_EndColumn_Is_Set_But_No_Column()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
- var filePath = string.Empty;
- int? line = null;
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ int? column = null;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -545,14 +2060,20 @@ public void Should_Handle_File_Paths_Which_Are_Empty()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var issue =
+ var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -560,21 +2081,27 @@ public void Should_Handle_File_Paths_Which_Are_Empty()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName);
+ providerName));
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("endColumn");
}
[Fact]
- public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
+ public void Should_Throw_If_EndColumn_Is_Smaller_Column()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
- var filePath = " ";
- int? line = null;
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 5;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -584,14 +2111,20 @@ public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var issue =
+ var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -599,29 +2132,27 @@ public void Should_Handle_File_Paths_Which_Are_WhiteSpace()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName);
+ providerName));
// Then
- issue.AffectedFileRelativePath.ShouldBe(null);
+ result.IsArgumentOutOfRangeException("endColumn");
}
- [Theory]
- [InlineData(@"foo", @"foo")]
- [InlineData(@"foo\bar", @"foo/bar")]
- [InlineData(@"foo/bar", @"foo/bar")]
- [InlineData(@"foo\bar\", @"foo/bar")]
- [InlineData(@"foo/bar/", @"foo/bar")]
- [InlineData(@".\foo", @"foo")]
- [InlineData(@"./foo", @"foo")]
- [InlineData(@"foo\..\bar", @"foo/../bar")]
- [InlineData(@"foo/../bar", @"foo/../bar")]
- public void Should_Set_File_Path(string filePath, string expectedFilePath)
+ [Fact]
+ public void Should_Handle_EndColumn_Which_Is_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
+ var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ int? column = null;
+ int? endColumn = null;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -631,14 +2162,20 @@ public void Should_Set_File_Path(string filePath, string expectedFilePath)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -646,25 +2183,27 @@ public void Should_Set_File_Path(string filePath, string expectedFilePath)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
// Then
- issue.AffectedFileRelativePath.ToString().ShouldBe(expectedFilePath);
- issue.AffectedFileRelativePath.IsRelative.ShouldBe(true, "File path was not set as relative.");
+ issue.EndColumn.ShouldBe(endColumn);
}
- }
- public sealed class TheLineArgument
- {
[Fact]
- public void Should_Throw_If_Line_Is_Negative()
+ public void Should_Handle_EndColumn_Which_Is_Equals_Column()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
- var line = -1;
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 50;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -674,14 +2213,20 @@ public void Should_Throw_If_Line_Is_Negative()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var result = Record.Exception(() =>
+ var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -689,21 +2234,29 @@ public void Should_Throw_If_Line_Is_Negative()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName));
+ providerName);
// Then
- result.IsArgumentOutOfRangeException("line");
+ issue.EndColumn.ShouldBe(endColumn);
}
- [Fact]
- public void Should_Throw_If_Line_Is_Zero()
+ [Theory]
+ [InlineData(null)]
+ [InlineData(1)]
+ [InlineData(int.MaxValue)]
+ public void Should_Set_EndColumn(int? endColumn)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
- var line = 0;
+ var line = 10;
+ var endLine = 12;
+ var column = 1;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -713,14 +2266,20 @@ public void Should_Throw_If_Line_Is_Zero()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var result = Record.Exception(() =>
+ var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -728,21 +2287,30 @@ public void Should_Throw_If_Line_Is_Zero()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName));
+ providerName);
// Then
- result.IsArgumentOutOfRangeException("line");
+ issue.EndColumn.ShouldBe(endColumn);
}
+ }
+ public sealed class TheFileLinkArgument
+ {
[Fact]
- public void Should_Throw_If_Line_Is_Set_But_No_File()
+ public void Should_Set_FileLink()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
- string filePath = null;
+ var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -752,14 +2320,20 @@ public void Should_Throw_If_Line_Is_Set_But_No_File()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
- var result = Record.Exception(() =>
+ var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -767,23 +2341,27 @@ public void Should_Throw_If_Line_Is_Set_But_No_File()
priorityName,
rule,
ruleUri,
+ run,
providerType,
- providerName));
+ providerName);
// Then
- result.IsArgumentOutOfRangeException("line");
+ issue.FileLink.ShouldBe(fileLink);
}
- [Theory]
- [InlineData(null)]
- [InlineData(1)]
- [InlineData(int.MaxValue)]
- public void Should_Set_Line(int? line)
+ [Fact]
+ public void Should_Set_FileLink_If_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ Uri fileLink = null;
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -793,14 +2371,20 @@ public void Should_Set_Line(int? line)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -808,11 +2392,12 @@ public void Should_Set_Line(int? line)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
// Then
- issue.Line.ShouldBe(line);
+ issue.FileLink.ShouldBe(fileLink);
}
}
@@ -822,10 +2407,15 @@ public sealed class TheMessageTextArgument
public void Should_Throw_If_MessageText_Is_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
string messageText = null;
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -835,14 +2425,20 @@ public void Should_Throw_If_MessageText_Is_Null()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -850,6 +2446,7 @@ public void Should_Throw_If_MessageText_Is_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -861,10 +2458,15 @@ public void Should_Throw_If_MessageText_Is_Null()
public void Should_Throw_If_MessageText_Is_Empty()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = string.Empty;
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -874,14 +2476,20 @@ public void Should_Throw_If_MessageText_Is_Empty()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -889,6 +2497,7 @@ public void Should_Throw_If_MessageText_Is_Empty()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -900,10 +2509,15 @@ public void Should_Throw_If_MessageText_Is_Empty()
public void Should_Throw_If_MessageText_Is_WhiteSpace()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = " ";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -913,14 +2527,20 @@ public void Should_Throw_If_MessageText_Is_WhiteSpace()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -928,6 +2548,7 @@ public void Should_Throw_If_MessageText_Is_WhiteSpace()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -940,10 +2561,15 @@ public void Should_Throw_If_MessageText_Is_WhiteSpace()
public void Should_Set_MessageText(string messageText)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
var priority = 1;
@@ -952,14 +2578,20 @@ public void Should_Set_MessageText(string messageText)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -967,6 +2599,7 @@ public void Should_Set_MessageText(string messageText)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -985,10 +2618,15 @@ public sealed class TheMessageHtmlArgument
public void Should_Set_MessageHtml(string messageHtml)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageMarkdown = "MessageMarkdown";
var priority = 1;
@@ -997,14 +2635,20 @@ public void Should_Set_MessageHtml(string messageHtml)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1012,6 +2656,7 @@ public void Should_Set_MessageHtml(string messageHtml)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1030,10 +2675,15 @@ public sealed class TheMessageMarkdownArgument
public void Should_Set_MessageHtml(string messageMarkdown)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var priority = 1;
@@ -1042,14 +2692,20 @@ public void Should_Set_MessageHtml(string messageMarkdown)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1057,6 +2713,7 @@ public void Should_Set_MessageHtml(string messageMarkdown)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1077,10 +2734,15 @@ public sealed class ThePriorityArgument
public void Should_Set_Priority(int? priority)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1089,14 +2751,20 @@ public void Should_Set_Priority(int? priority)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1104,6 +2772,7 @@ public void Should_Set_Priority(int? priority)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1118,10 +2787,15 @@ public sealed class ThePriorityNameArgument
public void Should_Handle_PriorityNames_Which_Are_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1131,14 +2805,20 @@ public void Should_Handle_PriorityNames_Which_Are_Null()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1146,6 +2826,7 @@ public void Should_Handle_PriorityNames_Which_Are_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1157,10 +2838,15 @@ public void Should_Handle_PriorityNames_Which_Are_Null()
public void Should_Handle_PriorityNames_Which_Are_Empty()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1170,14 +2856,20 @@ public void Should_Handle_PriorityNames_Which_Are_Empty()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1185,6 +2877,7 @@ public void Should_Handle_PriorityNames_Which_Are_Empty()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1196,10 +2889,15 @@ public void Should_Handle_PriorityNames_Which_Are_Empty()
public void Should_Handle_PriorityNames_Which_Are_WhiteSpace()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1209,14 +2907,20 @@ public void Should_Handle_PriorityNames_Which_Are_WhiteSpace()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1224,6 +2928,7 @@ public void Should_Handle_PriorityNames_Which_Are_WhiteSpace()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1236,10 +2941,15 @@ public void Should_Handle_PriorityNames_Which_Are_WhiteSpace()
public void Should_Set_Priority_Name(string priorityName)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1248,14 +2958,20 @@ public void Should_Set_Priority_Name(string priorityName)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1263,6 +2979,7 @@ public void Should_Set_Priority_Name(string priorityName)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1280,10 +2997,15 @@ public sealed class TheRuleArgument
public void Should_Set_Rule(string rule)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1292,14 +3014,20 @@ public void Should_Set_Rule(string rule)
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1307,6 +3035,7 @@ public void Should_Set_Rule(string rule)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1321,10 +3050,15 @@ public sealed class TheRuleUrlArgument
public void Should_Set_Rule_Url()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1334,14 +3068,20 @@ public void Should_Set_Rule_Url()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1349,6 +3089,7 @@ public void Should_Set_Rule_Url()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1360,10 +3101,15 @@ public void Should_Set_Rule_Url()
public void Should_Set_Rule_Url_If_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1373,14 +3119,20 @@ public void Should_Set_Rule_Url_If_Null()
Uri ruleUri = null;
var providerType = "ProviderType";
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1388,6 +3140,7 @@ public void Should_Set_Rule_Url_If_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1396,16 +3149,77 @@ public void Should_Set_Rule_Url_If_Null()
}
}
+ public sealed class TheRunArgument
+ {
+ [Theory]
+ [InlineData(null)]
+ [InlineData("")]
+ [InlineData("run")]
+ public void Should_Set_Run(string run)
+ {
+ // Given
+ var identifier = "identifier";
+ var projectPath = @"src\foo.csproj";
+ var projectName = "foo";
+ var filePath = @"src\foo.cs";
+ var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
+ var messageText = "MessageText";
+ var messageHtml = "MessageHtml";
+ var messageMarkdown = "MessageMarkdown";
+ var priority = 1;
+ var priorityName = "Warning";
+ var rule = "Rule";
+ var ruleUri = new Uri("https://google.com");
+ var providerType = "ProviderType";
+ var providerName = "ProviderName";
+
+ // When
+ var issue =
+ new Issue(
+ identifier,
+ projectPath,
+ projectName,
+ filePath,
+ line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
+ messageText,
+ messageHtml,
+ messageMarkdown,
+ priority,
+ priorityName,
+ rule,
+ ruleUri,
+ run,
+ providerType,
+ providerName);
+
+ // Then
+ issue.Run.ShouldBe(run);
+ }
+ }
+
public sealed class TheProviderTypeArgument
{
[Fact]
public void Should_Throw_If_Provider_Type_Is_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1415,14 +3229,20 @@ public void Should_Throw_If_Provider_Type_Is_Null()
var ruleUri = new Uri("https://google.com");
string providerType = null;
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1430,6 +3250,7 @@ public void Should_Throw_If_Provider_Type_Is_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -1441,10 +3262,15 @@ public void Should_Throw_If_Provider_Type_Is_Null()
public void Should_Throw_If_Provider_Type_Is_Empty()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1454,14 +3280,20 @@ public void Should_Throw_If_Provider_Type_Is_Empty()
var ruleUri = new Uri("https://google.com");
var providerType = string.Empty;
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1469,6 +3301,7 @@ public void Should_Throw_If_Provider_Type_Is_Empty()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -1480,10 +3313,15 @@ public void Should_Throw_If_Provider_Type_Is_Empty()
public void Should_Throw_If_Provider_Type_Is_WhiteSpace()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1493,14 +3331,20 @@ public void Should_Throw_If_Provider_Type_Is_WhiteSpace()
var ruleUri = new Uri("https://google.com");
var providerType = " ";
var providerName = "ProviderName";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1508,6 +3352,7 @@ public void Should_Throw_If_Provider_Type_Is_WhiteSpace()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -1520,10 +3365,15 @@ public void Should_Throw_If_Provider_Type_Is_WhiteSpace()
public void Should_Set_ProviderType(string providerType)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1532,14 +3382,20 @@ public void Should_Set_ProviderType(string providerType)
var rule = "Rule";
var ruleUri = new Uri("https://google.com");
var providerName = "ProviderName";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1547,6 +3403,7 @@ public void Should_Set_ProviderType(string providerType)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
@@ -1561,10 +3418,15 @@ public sealed class TheProviderNameArgument
public void Should_Throw_If_Provider_Name_Is_Null()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1574,14 +3436,20 @@ public void Should_Throw_If_Provider_Name_Is_Null()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
string providerName = null;
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1589,6 +3457,7 @@ public void Should_Throw_If_Provider_Name_Is_Null()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -1600,10 +3469,15 @@ public void Should_Throw_If_Provider_Name_Is_Null()
public void Should_Throw_If_Provider_Name_Is_Empty()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1613,14 +3487,20 @@ public void Should_Throw_If_Provider_Name_Is_Empty()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = string.Empty;
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1628,6 +3508,7 @@ public void Should_Throw_If_Provider_Name_Is_Empty()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -1639,10 +3520,15 @@ public void Should_Throw_If_Provider_Name_Is_Empty()
public void Should_Throw_If_Provider_Name_Is_WhiteSpace()
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1652,14 +3538,20 @@ public void Should_Throw_If_Provider_Name_Is_WhiteSpace()
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
var providerName = " ";
+ var run = "Run";
// When
var result = Record.Exception(() =>
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1667,6 +3559,7 @@ public void Should_Throw_If_Provider_Name_Is_WhiteSpace()
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName));
@@ -1679,10 +3572,15 @@ public void Should_Throw_If_Provider_Name_Is_WhiteSpace()
public void Should_Set_ProviderName(string providerName)
{
// Given
+ var identifier = "identifier";
var projectPath = @"src\foo.csproj";
var projectName = "foo";
var filePath = @"src\foo.cs";
var line = 10;
+ var endLine = 12;
+ var column = 50;
+ var endColumn = 55;
+ var fileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
var messageText = "MessageText";
var messageHtml = "MessageHtml";
var messageMarkdown = "MessageMarkdown";
@@ -1691,14 +3589,20 @@ public void Should_Set_ProviderName(string providerName)
var rule = "Rule";
var ruleUri = new Uri("https://google.com");
var providerType = "ProviderType";
+ var run = "Run";
// When
var issue =
new Issue(
+ identifier,
projectPath,
projectName,
filePath,
line,
+ endLine,
+ column,
+ endColumn,
+ fileLink,
messageText,
messageHtml,
messageMarkdown,
@@ -1706,6 +3610,7 @@ public void Should_Set_ProviderName(string providerName)
priorityName,
rule,
ruleUri,
+ run,
providerType,
providerName);
diff --git a/src/Cake.Issues.Tests/IssuesFixture.cs b/src/Cake.Issues.Tests/IssuesFixture.cs
index eecba2799..810ca5076 100644
--- a/src/Cake.Issues.Tests/IssuesFixture.cs
+++ b/src/Cake.Issues.Tests/IssuesFixture.cs
@@ -20,7 +20,7 @@ public IssuesFixture()
public IList IssueProviders { get; set; }
- public RepositorySettings Settings { get; set; }
+ public ReadIssuesSettings Settings { get; set; }
public IEnumerable ReadIssues()
{
diff --git a/src/Cake.Issues.Tests/Serialization/IssueDeserializationExtensionsTests.cs b/src/Cake.Issues.Tests/Serialization/IssueDeserializationExtensionsTests.cs
index f2ad8facb..2f24d8c0b 100644
--- a/src/Cake.Issues.Tests/Serialization/IssueDeserializationExtensionsTests.cs
+++ b/src/Cake.Issues.Tests/Serialization/IssueDeserializationExtensionsTests.cs
@@ -128,6 +128,32 @@ public void Should_Return_IssueV2()
.OfRule("Rule", new Uri("https://google.com"))
.WithPriority(IssuePriority.Warning));
}
+
+ [Fact]
+ public void Should_Return_IssueV3()
+ {
+ // Given
+ var filePath = new FilePath("Testfiles/issueV3.json");
+
+ // When
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ IssueChecker.Check(
+ result,
+ IssueBuilder.NewIssue(
+ "Identifier",
+ "Something went wrong.",
+ "TestProvider",
+ "Test Provider")
+ .ForRun("TestRun")
+ .WithMessageInHtmlFormat("Something went wrong.")
+ .WithMessageInMarkdownFormat("Something went **wrong**.")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar.cs", 42, 420, 23, 230)
+ .OfRule("Rule", new Uri("https://google.com"))
+ .WithPriority(IssuePriority.Warning));
+ }
}
public sealed class TheDeserializeToIssuesExtensionForAJsonFile
@@ -225,6 +251,44 @@ public void Should_Return_List_Of_IssuesV2()
.InFile(@"src\Foo\Bar2.cs")
.WithPriority(IssuePriority.Warning));
}
+
+ [Fact]
+ public void Should_Return_List_Of_IssuesV3()
+ {
+ // Given
+ var filePath = new FilePath("Testfiles/issuesV3.json");
+
+ // When
+ var result = filePath.DeserializeToIssues().ToList();
+
+ // Then
+ result.Count.ShouldBe(2);
+ IssueChecker.Check(
+ result[0],
+ IssueBuilder.NewIssue(
+ "Identifier1",
+ "Something went wrong.",
+ "TestProvider",
+ "Test Provider")
+ .WithMessageInHtmlFormat("Something went wrong.")
+ .WithMessageInMarkdownFormat("Something went **wrong**.")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar.cs", 42, 420, 23, 230)
+ .OfRule("Rule", new Uri("https://google.com"))
+ .WithPriority(IssuePriority.Warning));
+ IssueChecker.Check(
+ result[1],
+ IssueBuilder.NewIssue(
+ "Identifier2",
+ "Something went wrong again.",
+ "TestProvider",
+ "Test Provider")
+ .WithMessageInHtmlFormat("Something went wrong again.")
+ .WithMessageInMarkdownFormat("Something went **wrong** again.")
+ .InProject(@"src\Foo\Bar.csproj", "Bar")
+ .InFile(@"src\Foo\Bar2.cs")
+ .WithPriority(IssuePriority.Warning));
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Serialization/IssueSerializationExtensionsTests.cs b/src/Cake.Issues.Tests/Serialization/IssueSerializationExtensionsTests.cs
index a280ff2af..244117bb0 100644
--- a/src/Cake.Issues.Tests/Serialization/IssueSerializationExtensionsTests.cs
+++ b/src/Cake.Issues.Tests/Serialization/IssueSerializationExtensionsTests.cs
@@ -26,6 +26,23 @@ public void Should_Throw_If_Issue_Is_Null()
result.IsArgumentNullException("issue");
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_Identifier_After_Roundtrip()
+ {
+ // Given
+ var identifier = "identifier";
+ var issue =
+ IssueBuilder
+ .NewIssue(identifier, "message", "providerType", "providerName")
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.Identifier.ShouldBe(identifier);
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
{
@@ -113,6 +130,24 @@ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
result.ProviderName.ShouldBe(providerName);
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_Run_After_Roundtrip()
+ {
+ // Given
+ var run = "run";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .ForRun(run)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.Run.ShouldBe(run);
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
{
@@ -185,6 +220,78 @@ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
result.Line.ShouldBe(line);
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndLine_After_Roundtrip()
+ {
+ // Given
+ var endLine = 420;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", 42, endLine, null, null)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.EndLine.ShouldBe(endLine);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Column_After_Roundtrip()
+ {
+ // Given
+ var column = 23;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", 42, column)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.Column.ShouldBe(column);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndColumn_After_Roundtrip()
+ {
+ // Given
+ var endColumn = 230;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", 42, 420, 23, endColumn)
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.EndColumn.ShouldBe(endColumn);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_FileLink_After_Roundtrip()
+ {
+ // Given
+ var fileLink = "https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithFileLink(new Uri(fileLink))
+ .Create();
+
+ // When
+ var result = issue.SerializeToJsonString().DeserializeToIssue();
+
+ // Then
+ result.FileLink.ToString().ShouldBe(fileLink);
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
{
@@ -273,6 +380,32 @@ public void Should_Throw_If_Issue_Is_Null()
result.IsArgumentNullException("issues");
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_Identifier_After_Roundtrip()
+ {
+ // Given
+ var identifier1 = "identifier1";
+ var identifier2 = "identifier2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue(identifier1, "messageText1", "providerType1", "providerName1")
+ .Create(),
+ IssueBuilder
+ .NewIssue(identifier2, "messageText2", "providerType2", "providerName2")
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Identifier.ShouldBe(identifier1);
+ result.Last().Identifier.ShouldBe(identifier2);
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
{
@@ -407,6 +540,34 @@ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
result.Last().ProviderName.ShouldBe(providerName2);
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_Run_After_Roundtrip()
+ {
+ // Given
+ var run1 = "run1";
+ var run2 = "run2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .ForRun(run1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .ForRun(run2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Run.ShouldBe(run1);
+ result.Last().Run.ShouldBe(run2);
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
{
@@ -519,6 +680,118 @@ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
result.Last().Line.ShouldBe(line2);
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndLine_After_Roundtrip()
+ {
+ // Given
+ var endLine1 = 230;
+ var endLine2 = 420;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", 23, endLine1, null, null)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", 42, endLine2, null, null)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().EndLine.ShouldBe(endLine1);
+ result.Last().EndLine.ShouldBe(endLine2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Column_After_Roundtrip()
+ {
+ // Given
+ var column1 = 23;
+ var column2 = 42;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", 123, column1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", 123, column2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Column.ShouldBe(column1);
+ result.Last().Column.ShouldBe(column2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndColumn_After_Roundtrip()
+ {
+ // Given
+ var endColumn1 = 230;
+ var endColumn2 = 420;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", 5, 50, 23, endColumn1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", 5, 50, 42, endColumn2)
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().EndColumn.ShouldBe(endColumn1);
+ result.Last().EndColumn.ShouldBe(endColumn2);
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_FileLink_After_Roundtrip()
+ {
+ // Given
+ var fileLink1 = "https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12";
+ var fileLink2 = "https://github.com/myorg/myrepo/blob/develop/src/bar.cs#L23-L42";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .WithFileLink(new Uri(fileLink1))
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .WithFileLink(new Uri(fileLink2))
+ .Create(),
+ };
+
+ // When
+ var result = issues.SerializeToJsonString().DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().FileLink.ToString().ShouldBe(fileLink1);
+ result.Last().FileLink.ToString().ShouldBe(fileLink2);
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
{
@@ -665,6 +938,35 @@ public void Should_Throw_If_FilePath_Is_Null()
result.IsArgumentNullException("filePath");
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_Identifier_After_Roundtrip()
+ {
+ // Given
+ var identifier = "identifier";
+ var issue =
+ IssueBuilder
+ .NewIssue(identifier, "messageText", "providerType", "providerName")
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.Identifier.ShouldBe(identifier);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
{
@@ -813,14 +1115,14 @@ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
}
[Fact]
- public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
+ public void Should_Give_Correct_Result_For_Run_After_Roundtrip()
{
// Given
- var projectFileRelativePath = @"src/myproj.file";
+ var run = "run";
var issue =
IssueBuilder
.NewIssue("message", "providerType", "providerName")
- .InProjectFile(projectFileRelativePath)
+ .ForRun(run)
.Create();
var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
@@ -831,7 +1133,7 @@ public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtr
var result = filePath.DeserializeToIssue();
// Then
- result.ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath);
+ result.Run.ShouldBe(run);
}
finally
{
@@ -843,14 +1145,14 @@ public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtr
}
[Fact]
- public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
+ public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
{
// Given
- var projectName = "projectName";
+ var projectFileRelativePath = @"src/myproj.file";
var issue =
IssueBuilder
.NewIssue("message", "providerType", "providerName")
- .InProjectOfName(projectName)
+ .InProjectFile(projectFileRelativePath)
.Create();
var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
@@ -861,7 +1163,7 @@ public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
var result = filePath.DeserializeToIssue();
// Then
- result.ProjectName.ShouldBe(projectName);
+ result.ProjectFileRelativePath.FullPath.ShouldBe(projectFileRelativePath);
}
finally
{
@@ -873,14 +1175,14 @@ public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
}
[Fact]
- public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
+ public void Should_Give_Correct_Result_For_ProjectName_After_Roundtrip()
{
// Given
- var affectedFileRelativePath = @"src/foo.bar";
+ var projectName = "projectName";
var issue =
IssueBuilder
.NewIssue("message", "providerType", "providerName")
- .InFile(affectedFileRelativePath)
+ .InProjectOfName(projectName)
.Create();
var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
@@ -891,7 +1193,7 @@ public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundt
var result = filePath.DeserializeToIssue();
// Then
- result.AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath);
+ result.ProjectName.ShouldBe(projectName);
}
finally
{
@@ -903,10 +1205,40 @@ public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundt
}
[Fact]
- public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
+ public void Should_Give_Correct_Result_For_AffectedFileRelativePath_After_Roundtrip()
{
// Given
- var line = 42;
+ var affectedFileRelativePath = @"src/foo.bar";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(affectedFileRelativePath)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.AffectedFileRelativePath.FullPath.ShouldBe(affectedFileRelativePath);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
+ {
+ // Given
+ var line = 42;
var issue =
IssueBuilder
.NewIssue("message", "providerType", "providerName")
@@ -932,6 +1264,126 @@ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
}
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndLine_After_Roundtrip()
+ {
+ // Given
+ var endLine = 420;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", 42, endLine, null, null)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.EndLine.ShouldBe(endLine);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Column_After_Roundtrip()
+ {
+ // Given
+ var column = 23;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", 42, column)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.Column.ShouldBe(column);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndColumn_After_Roundtrip()
+ {
+ // Given
+ var endColumn = 230;
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .InFile(@"src/foo.bar", 42, 50, 1, endColumn)
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.EndColumn.ShouldBe(endColumn);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_FileLink_After_Roundtrip()
+ {
+ // Given
+ var fileLink = "https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12";
+ var issue =
+ IssueBuilder
+ .NewIssue("message", "providerType", "providerName")
+ .WithFileLink(new Uri(fileLink))
+ .Create();
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issue.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssue();
+
+ // Then
+ result.FileLink.ToString().ShouldBe(fileLink);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
{
@@ -1083,6 +1535,44 @@ public void Should_Throw_If_FilePath_Is_Null()
result.IsArgumentNullException("filePath");
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_Identifier_After_Roundtrip()
+ {
+ // Given
+ var identifier1 = "identifier1";
+ var identifier2 = "identifier2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue(identifier1, "messageText1", "providerType1", "providerName1")
+ .Create(),
+ IssueBuilder
+ .NewIssue(identifier2, "messageText2", "providerType2", "providerName2")
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Identifier.ShouldBe(identifier1);
+ result.Last().Identifier.ShouldBe(identifier2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_MessageText_After_Roundtrip()
{
@@ -1277,6 +1767,46 @@ public void Should_Give_Correct_Result_For_ProviderName_After_Roundtrip()
}
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_Run_After_Roundtrip()
+ {
+ // Given
+ var run1 = "run1";
+ var run2 = "run2";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .ForRun(run1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .ForRun(run2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Run.ShouldBe(run1);
+ result.Last().Run.ShouldBe(run2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_ProjectFileRelativePath_After_Roundtrip()
{
@@ -1437,6 +1967,166 @@ public void Should_Give_Correct_Result_For_Line_After_Roundtrip()
}
}
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndLine_After_Roundtrip()
+ {
+ // Given
+ var endLine1 = 230;
+ var endLine2 = 420;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", 23, endLine1, null, null)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", 42, endLine2, null, null)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().EndLine.ShouldBe(endLine1);
+ result.Last().EndLine.ShouldBe(endLine2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_Column_After_Roundtrip()
+ {
+ // Given
+ var column1 = 23;
+ var column2 = 42;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", 123, column1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", 123, column2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().Column.ShouldBe(column1);
+ result.Last().Column.ShouldBe(column2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_EndColumn_After_Roundtrip()
+ {
+ // Given
+ var endColumn1 = 23;
+ var endColumn2 = 42;
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .InFile(@"src/foo.bar", 5, 50, 1, endColumn1)
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .InFile(@"src/foo.bar", 5, 50, 1, endColumn2)
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().EndColumn.ShouldBe(endColumn1);
+ result.Last().EndColumn.ShouldBe(endColumn2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
+ [Fact]
+ public void Should_Give_Correct_Result_For_FileLink_After_Roundtrip()
+ {
+ // Given
+ var fileLink1 = "https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12";
+ var fileLink2 = "https://github.com/myorg/myrepo/blob/develop/src/bar.cs#L23-L42";
+ var issues =
+ new List
+ {
+ IssueBuilder
+ .NewIssue("message1", "providerType1", "providerName1")
+ .WithFileLink(new Uri(fileLink1))
+ .Create(),
+ IssueBuilder
+ .NewIssue("message2", "providerType2", "providerName2")
+ .WithFileLink(new Uri(fileLink2))
+ .Create(),
+ };
+ var filePath = new FilePath(System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".json");
+
+ try
+ {
+ // When
+ issues.SerializeToJsonFile(filePath);
+ var result = filePath.DeserializeToIssues();
+
+ // Then
+ result.Count().ShouldBe(2);
+ result.First().FileLink.ToString().ShouldBe(fileLink1);
+ result.Last().FileLink.ToString().ShouldBe(fileLink2);
+ }
+ finally
+ {
+ if (System.IO.File.Exists(filePath.FullPath))
+ {
+ System.IO.File.Delete(filePath.FullPath);
+ }
+ }
+ }
+
[Fact]
public void Should_Give_Correct_Result_For_Priority_After_Roundtrip()
{
diff --git a/src/Cake.Issues.Tests/Serialization/SerializableIssueV3ExtensionsTests.cs b/src/Cake.Issues.Tests/Serialization/SerializableIssueV3ExtensionsTests.cs
new file mode 100644
index 000000000..c223b55cb
--- /dev/null
+++ b/src/Cake.Issues.Tests/Serialization/SerializableIssueV3ExtensionsTests.cs
@@ -0,0 +1,25 @@
+namespace Cake.Issues.Tests.Serialization
+{
+ using Cake.Issues.Serialization;
+ using Cake.Issues.Testing;
+ using Xunit;
+
+ public sealed class SerializableIssueV3ExtensionsTests
+ {
+ public sealed class TheToIssueExtension
+ {
+ [Fact]
+ public void Should_Throw_If_SerializableIssue_Is_Null()
+ {
+ // Given
+ SerializableIssueV3 serializableIssue = null;
+
+ // When
+ var result = Record.Exception(() => serializableIssue.ToIssue());
+
+ // Then
+ result.IsArgumentNullException("serializableIssue");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Testfiles/issueV3.json b/src/Cake.Issues.Tests/Testfiles/issueV3.json
new file mode 100644
index 000000000..94191f89a
--- /dev/null
+++ b/src/Cake.Issues.Tests/Testfiles/issueV3.json
@@ -0,0 +1,21 @@
+{
+ "Version": 3,
+ "Identifier": "Identifier",
+ "AffectedFileRelativePath": "src\/Foo\/Bar.cs",
+ "Line": 42,
+ "EndLine": 420,
+ "Column": 23,
+ "EndColumn": 230,
+ "MessageText": "Something went wrong.",
+ "MessageHtml": "Something went wrong.",
+ "MessageMarkdown": "Something went **wrong**.",
+ "Priority": 300,
+ "PriorityName": "Warning",
+ "ProjectFileRelativePath": "src\/Foo\/Bar.csproj",
+ "ProjectName": "Bar",
+ "ProviderName": "Test Provider",
+ "ProviderType": "TestProvider",
+ "Run": "TestRun",
+ "Rule": "Rule",
+ "RuleUrl": "https://google.com"
+}
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Testfiles/issuesV3.json b/src/Cake.Issues.Tests/Testfiles/issuesV3.json
new file mode 100644
index 000000000..d3099e26e
--- /dev/null
+++ b/src/Cake.Issues.Tests/Testfiles/issuesV3.json
@@ -0,0 +1,42 @@
+[
+ {
+ "Version": 3,
+ "Identifier": "Identifier1",
+ "AffectedFileRelativePath": "src\/Foo\/Bar.cs",
+ "Line": 42,
+ "EndLine": 420,
+ "Column": 23,
+ "EndColumn": 230,
+ "MessageText": "Something went wrong.",
+ "MessageHtml": "Something went wrong.",
+ "MessageMarkdown": "Something went **wrong**.",
+ "Priority": 300,
+ "PriorityName": "Warning",
+ "ProjectFileRelativePath": "src\/Foo\/Bar.csproj",
+ "ProjectName": "Bar",
+ "ProviderName": "Test Provider",
+ "ProviderType": "TestProvider",
+ "Rule": "Rule",
+ "RuleUrl": "https://google.com"
+ },
+ {
+ "Version": 3,
+ "Identifier": "Identifier2",
+ "AffectedFileRelativePath": "src\/Foo\/Bar2.cs",
+ "Line": null,
+ "EndLine": null,
+ "Column": null,
+ "EndColumn": null,
+ "MessageText": "Something went wrong again.",
+ "MessageHtml": "Something went wrong again.",
+ "MessageMarkdown": "Something went **wrong** again.",
+ "Priority": 300,
+ "PriorityName": "Warning",
+ "ProjectFileRelativePath": "src\/Foo\/Bar.csproj",
+ "ProjectName": "Bar",
+ "ProviderName": "Test Provider",
+ "ProviderType": "TestProvider",
+ "Rule": null,
+ "RuleUrl": null
+ }
+]
\ No newline at end of file
diff --git a/src/Cake.Issues.Tests/Testing/BaseConfigurableIssueProviderFixtureTests.cs b/src/Cake.Issues.Tests/Testing/BaseConfigurableIssueProviderFixtureTests.cs
index 4d267d669..182507833 100644
--- a/src/Cake.Issues.Tests/Testing/BaseConfigurableIssueProviderFixtureTests.cs
+++ b/src/Cake.Issues.Tests/Testing/BaseConfigurableIssueProviderFixtureTests.cs
@@ -82,7 +82,7 @@ public void Should_Set_RepositorySettings()
var result = new FakeConfigurableIssueProviderFixture("Build.log");
// Then
- result.RepositorySettings.ShouldNotBeNull();
+ result.ReadIssuesSettings.ShouldNotBeNull();
}
[Fact]
@@ -136,14 +136,14 @@ public void Should_Throw_If_RepositorySettings_Are_Null()
// Given
var fixture = new FakeConfigurableIssueProviderFixture("Build.log")
{
- RepositorySettings = null,
+ ReadIssuesSettings = null,
};
// When
var result = Record.Exception(() => fixture.ReadIssues());
// Then
- result.IsInvalidOperationException("No repository settings set.");
+ result.IsInvalidOperationException("No settings for reading issues set.");
}
[Fact]
diff --git a/src/Cake.Issues.Tests/Testing/BaseIssueProviderFixtureTests.cs b/src/Cake.Issues.Tests/Testing/BaseIssueProviderFixtureTests.cs
index 5cb0d3268..5aa2d628b 100644
--- a/src/Cake.Issues.Tests/Testing/BaseIssueProviderFixtureTests.cs
+++ b/src/Cake.Issues.Tests/Testing/BaseIssueProviderFixtureTests.cs
@@ -31,7 +31,7 @@ public void Should_Set_RepositorySettings()
var result = new FakeIssueProviderFixture();
// Then
- result.RepositorySettings.ShouldNotBeNull();
+ result.ReadIssuesSettings.ShouldNotBeNull();
}
}
@@ -59,14 +59,14 @@ public void Should_Throw_If_RepositorySettings_Are_Null()
// Given
var fixture = new FakeIssueProviderFixture
{
- RepositorySettings = null,
+ ReadIssuesSettings = null,
};
// When
var result = Record.Exception(() => fixture.ReadIssues());
// Then
- result.IsInvalidOperationException("No repository settings set.");
+ result.IsInvalidOperationException("No settings for reading issues set.");
}
[Fact]
diff --git a/src/Cake.Issues.Tests/Testing/BaseMultiFormatIssueProviderFixtureTests.cs b/src/Cake.Issues.Tests/Testing/BaseMultiFormatIssueProviderFixtureTests.cs
index 540dcf176..be71cbfff 100644
--- a/src/Cake.Issues.Tests/Testing/BaseMultiFormatIssueProviderFixtureTests.cs
+++ b/src/Cake.Issues.Tests/Testing/BaseMultiFormatIssueProviderFixtureTests.cs
@@ -82,7 +82,7 @@ public void Should_Set_RepositorySettings()
var result = new FakeMultiFormatIssueProviderFixture("Build.log");
// Then
- result.RepositorySettings.ShouldNotBeNull();
+ result.ReadIssuesSettings.ShouldNotBeNull();
}
[Fact]
@@ -136,14 +136,14 @@ public void Should_Throw_If_RepositorySettings_Are_Null()
// Given
var fixture = new FakeMultiFormatIssueProviderFixture("Build.log")
{
- RepositorySettings = null,
+ ReadIssuesSettings = null,
};
// When
var result = Record.Exception(() => fixture.ReadIssues());
// Then
- result.IsInvalidOperationException("No repository settings set.");
+ result.IsInvalidOperationException("No settings for reading issues set.");
}
[Fact]
diff --git a/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs b/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs
index 918571a1d..09ba57b92 100644
--- a/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs
+++ b/src/Cake.Issues.Tests/Testing/IssueCheckerFixture.cs
@@ -5,19 +5,25 @@
internal class IssueCheckerFixture : IssueBuilderFixture
{
public IssueCheckerFixture()
- : this("Message", "ProviderType", "ProviderName")
+ : this("Identifier", "Message", "ProviderType", "ProviderName")
{
}
- public IssueCheckerFixture(string messageText, string providerType, string providerName)
- : base(messageText, providerType, providerName)
+ public IssueCheckerFixture(string identifier, string messageText, string providerType, string providerName)
+ : base(identifier, messageText, providerType, providerName)
{
this.ProviderType = providerType;
this.ProviderName = providerName;
+ this.Run = "Test Run";
+ this.Identifier = identifier;
this.ProjectFileRelativePath = @"src\project.file";
this.ProjectName = "ProjectName";
this.AffectedFileRelativePath = @"src\source.file";
this.Line = 42;
+ this.EndLine = 420;
+ this.Column = 23;
+ this.EndColumn = 230;
+ this.FileLink = new Uri("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12");
this.MessageText = messageText;
this.MessageHtml = "messageHtml";
this.MessageMarkdown = "messageMarkdown";
@@ -27,10 +33,12 @@ public IssueCheckerFixture(string messageText, string providerType, string provi
this.RuleUrl = new Uri("https://google.com");
this.IssueBuilder
+ .ForRun(this.Run)
.WithMessageInHtmlFormat(this.MessageHtml)
.WithMessageInMarkdownFormat(this.MessageMarkdown)
.InProject(this.ProjectFileRelativePath, this.ProjectName)
- .InFile(this.AffectedFileRelativePath, this.Line)
+ .InFile(this.AffectedFileRelativePath, this.Line, this.EndLine, this.Column, this.EndColumn)
+ .WithFileLink(this.FileLink)
.OfRule(this.Rule, this.RuleUrl)
.WithPriority(this.Priority, this.PriorityName);
@@ -44,6 +52,10 @@ public IssueCheckerFixture(string messageText, string providerType, string provi
public string ProviderName { get; private set; }
+ public string Run { get; private set; }
+
+ public string Identifier { get; private set; }
+
public string ProjectFileRelativePath { get; private set; }
public string ProjectName { get; private set; }
@@ -52,6 +64,14 @@ public IssueCheckerFixture(string messageText, string providerType, string provi
public int Line { get; private set; }
+ public int EndLine { get; private set; }
+
+ public int Column { get; private set; }
+
+ public int EndColumn { get; private set; }
+
+ public Uri FileLink { get; private set; }
+
public string MessageText { get; private set; }
public string MessageHtml { get; private set; }
diff --git a/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs b/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs
index 2b8c8fddf..d593d31eb 100644
--- a/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs
+++ b/src/Cake.Issues.Tests/Testing/IssueCheckerTests.cs
@@ -144,10 +144,16 @@ public void Should_Throw_If_Issue_Is_Null()
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -171,10 +177,16 @@ public void Should_Not_Throw_If_All_Values_Are_The_Same()
fixture.Issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -194,7 +206,7 @@ public void Should_Not_Throw_If_All_Values_Are_The_Same()
public void Should_Throw_If_ProviderType_Is_Different(string expectedValue, string actualValue)
{
// Given
- var fixture = new IssueCheckerFixture("Message", actualValue, "ProviderName");
+ var fixture = new IssueCheckerFixture("Identifier", "Message", actualValue, "ProviderName");
// When
var result = Record.Exception(() =>
@@ -202,10 +214,16 @@ public void Should_Throw_If_ProviderType_Is_Different(string expectedValue, stri
fixture.Issue,
expectedValue,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -227,7 +245,7 @@ public void Should_Throw_If_ProviderType_Is_Different(string expectedValue, stri
public void Should_Throw_If_ProviderName_Is_Different(string expectedValue, string actualValue)
{
// Given
- var fixture = new IssueCheckerFixture("Message", "ProviderType", actualValue);
+ var fixture = new IssueCheckerFixture("Identifier", "Message", "ProviderType", actualValue);
// When
var result = Record.Exception(() =>
@@ -235,10 +253,16 @@ public void Should_Throw_If_ProviderName_Is_Different(string expectedValue, stri
fixture.Issue,
fixture.ProviderType,
expectedValue,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -252,6 +276,88 @@ public void Should_Throw_If_ProviderName_Is_Different(string expectedValue, stri
result.Message.ShouldStartWith("Expected issue.ProviderName");
}
+ [Theory]
+ [InlineData("Run", "Foo")]
+ [InlineData(null, "Foo")]
+ [InlineData("", "Foo")]
+ [InlineData(" ", "Foo")]
+ public void Should_Throw_If_Run_Is_Different(string expectedValue, string actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture();
+ var issue =
+ fixture.IssueBuilder
+ .ForRun(actualValue)
+ .Create();
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ fixture.Issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ expectedValue,
+ fixture.Identifier,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.Run");
+ }
+
+ [Theory]
+ [InlineData("Message", "Foo")]
+ [InlineData(null, "Foo")]
+ [InlineData("", "Foo")]
+ [InlineData(" ", "Foo")]
+ public void Should_Throw_If_Identifier_Is_Different(string expectedValue, string actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture(actualValue, "Message", "ProviderType", "ProviderName");
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ fixture.Issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ fixture.Run,
+ expectedValue,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.Identifier");
+ }
+
[Theory]
[InlineData(@"src\project.file", @"src\foo")]
public void Should_Throw_If_ProjectFileRelativePath_Is_Different(string expectedValue, string actualValue)
@@ -269,10 +375,16 @@ public void Should_Throw_If_ProjectFileRelativePath_Is_Different(string expected
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
expectedValue,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -306,10 +418,16 @@ public void Should_Throw_If_ProjectName_Is_Different(string expectedValue, strin
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
expectedValue,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -340,10 +458,16 @@ public void Should_Throw_If_AffectedFileRelativePath_Is_Different(string expecte
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
expectedValue,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -376,10 +500,16 @@ public void Should_Throw_If_Line_Is_Different(int? expectedValue, int? actualVal
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
expectedValue,
+ null,
+ null,
+ null,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -393,6 +523,173 @@ public void Should_Throw_If_Line_Is_Different(int? expectedValue, int? actualVal
result.Message.ShouldStartWith("Expected issue.Line");
}
+ [Theory]
+ [InlineData(420, 230)]
+ [InlineData(null, 420)]
+ [InlineData(420, null)]
+ public void Should_Throw_If_EndLine_Is_Different(int? expectedValue, int? actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture();
+ var issue =
+ fixture.IssueBuilder
+ .InFile(fixture.AffectedFileRelativePath, fixture.Line, actualValue, fixture.Column, fixture.EndColumn)
+ .Create();
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ expectedValue,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.EndLine");
+ }
+
+ [Theory]
+ [InlineData(42, 23)]
+ [InlineData(null, 42)]
+ [InlineData(42, null)]
+ public void Should_Throw_If_Column_Is_Different(int? expectedValue, int? actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture();
+ var issue =
+ fixture.IssueBuilder
+ .InFile(fixture.AffectedFileRelativePath, fixture.Line, fixture.EndLine, actualValue, null)
+ .Create();
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ fixture.EndLine,
+ expectedValue,
+ null,
+ fixture.FileLink,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.Column");
+ }
+
+ [Theory]
+ [InlineData(42, 23)]
+ [InlineData(null, 42)]
+ [InlineData(42, null)]
+ public void Should_Throw_If_EndColumn_Is_Different(int? expectedValue, int? actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture();
+ var issue =
+ fixture.IssueBuilder
+ .InFile(fixture.AffectedFileRelativePath, fixture.Line, fixture.EndLine, fixture.Column, actualValue)
+ .Create();
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ expectedValue,
+ fixture.FileLink,
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.EndColumn");
+ }
+
+ [Theory]
+ [InlineData("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12", "https://github.com/foo/bar/blob/develop/src/bar.cs")]
+ [InlineData("https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L12", "https://github.com/myorg/myrepo/blob/develop/src/foo.cs#L10-L13")]
+ public void Should_Throw_If_FileLink_Is_Different(string expectedValue, string actualValue)
+ {
+ // Given
+ var fixture = new IssueCheckerFixture();
+ var issue =
+ fixture.IssueBuilder
+ .WithFileLink(new Uri(actualValue))
+ .Create();
+
+ // When
+ var result = Record.Exception(() =>
+ IssueChecker.Check(
+ issue,
+ fixture.ProviderType,
+ fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
+ fixture.ProjectFileRelativePath,
+ fixture.ProjectName,
+ fixture.AffectedFileRelativePath,
+ fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ new Uri(expectedValue),
+ fixture.MessageText,
+ fixture.MessageHtml,
+ fixture.MessageMarkdown,
+ fixture.Priority,
+ fixture.PriorityName,
+ fixture.Rule,
+ fixture.RuleUrl));
+
+ // Then
+ result.ShouldBeOfType();
+ result.Message.ShouldStartWith("Expected issue.FileLink");
+ }
+
[Theory]
[InlineData("Message", "Foo")]
[InlineData(null, "Foo")]
@@ -401,7 +698,7 @@ public void Should_Throw_If_Line_Is_Different(int? expectedValue, int? actualVal
public void Should_Throw_If_MessageText_Is_Different(string expectedValue, string actualValue)
{
// Given
- var fixture = new IssueCheckerFixture(actualValue, "ProviderType", "ProviderName");
+ var fixture = new IssueCheckerFixture("Identifier", actualValue, "ProviderType", "ProviderName");
// When
var result = Record.Exception(() =>
@@ -409,10 +706,16 @@ public void Should_Throw_If_MessageText_Is_Different(string expectedValue, strin
fixture.Issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
expectedValue,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -446,10 +749,16 @@ public void Should_Throw_If_MessageHtml_Is_Different(string expectedValue, strin
fixture.Issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
expectedValue,
fixture.MessageMarkdown,
@@ -483,10 +792,16 @@ public void Should_Throw_If_MessageMarkdown_Is_Different(string expectedValue, s
fixture.Issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
expectedValue,
@@ -517,10 +832,16 @@ public void Should_Throw_If_Priority_Is_Different(IssuePriority expectedValue, I
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -554,10 +875,16 @@ public void Should_Throw_If_PriorityName_Is_Different(string expectedValue, stri
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -591,10 +918,16 @@ public void Should_Throw_If_Rule_Is_Different(string expectedValue, string actua
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
@@ -625,10 +958,16 @@ public void Should_Throw_If_RuleUrl_Is_Different(string expectedValue, string ac
issue,
fixture.ProviderType,
fixture.ProviderName,
+ fixture.Run,
+ fixture.Identifier,
fixture.ProjectFileRelativePath,
fixture.ProjectName,
fixture.AffectedFileRelativePath,
fixture.Line,
+ fixture.EndLine,
+ fixture.Column,
+ fixture.EndColumn,
+ fixture.FileLink,
fixture.MessageText,
fixture.MessageHtml,
fixture.MessageMarkdown,
diff --git a/src/Cake.Issues.Tests/UriExtensionsTests.cs b/src/Cake.Issues.Tests/UriExtensionsTests.cs
new file mode 100644
index 000000000..6907df88e
--- /dev/null
+++ b/src/Cake.Issues.Tests/UriExtensionsTests.cs
@@ -0,0 +1,51 @@
+namespace Cake.Issues.Tests
+{
+ using System;
+ using Cake.Issues.Testing;
+ using Shouldly;
+ using Xunit;
+
+ public sealed class UriExtensionsTests
+ {
+ public sealed class TheAppendMethod
+ {
+ [Fact]
+ public void Should_Throw_If_Uri_Is_Null()
+ {
+ // Given
+ Uri uri = null;
+ var path = "foo";
+
+ // When
+ var result = Record.Exception(() =>
+ uri.Append(path));
+
+ // Then
+ result.IsArgumentNullException("uri");
+ }
+
+ [Theory]
+ [InlineData("https://google.com/foo/bar", "https://google.com", "foo", "bar")]
+ [InlineData("https://google.com/foo/bar", "https://google.com/", "foo", "bar")]
+ [InlineData("https://google.com/foo/bar", "https://google.com", "/foo", "bar")]
+ [InlineData("https://google.com/foo/bar", "https://google.com", "foo/", "bar")]
+ [InlineData("https://google.com/foo/bar", "https://google.com", "foo", "/bar")]
+ [InlineData("https://google.com/foo/bar/", "https://google.com", "foo", "bar/")]
+ [InlineData("https://google.com/foo/bar", "https://google.com", "foo/", "/bar")]
+ [InlineData("https://google.com/bar", "https://google.com", null, "bar")]
+ [InlineData("https://google.com/bar", "https://google.com", "", "bar")]
+ [InlineData("https://google.com/bar", "https://google.com", " ", "bar")]
+ [InlineData("https://google.com/bar", "https://google.com", "/", "/bar")]
+ public void Should_Append_Paths(string expectedPath, string uri, params string[] paths)
+ {
+ // Given
+
+ // When
+ var result = new Uri(uri).Append(paths);
+
+ // Then
+ result.ToString().ShouldBe(expectedPath);
+ }
+ }
+ }
+}
diff --git a/src/Cake.Issues/Aliases.FileLinking.cs b/src/Cake.Issues/Aliases.FileLinking.cs
new file mode 100644
index 000000000..ddb70f4f0
--- /dev/null
+++ b/src/Cake.Issues/Aliases.FileLinking.cs
@@ -0,0 +1,294 @@
+namespace Cake.Issues
+{
+ using System;
+ using Cake.Core;
+ using Cake.Core.Annotations;
+
+ ///
+ /// Contains functionality related to linking to files.
+ ///
+ public static partial class Aliases
+ {
+ ///
+ /// Gets an instance of the file link settings for linking to files
+ /// based on a custom pattern.
+ ///
+ /// The context.
+ /// Pattern of the file link.
+ /// See
+ /// for a list of tokens supported in the pattern.
+ /// Settings for linking files.
+ ///
+ /// Creates file link settings to an internal source hosting site:
+ ///
+ ///
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettings(
+ this ICakeContext context,
+ string pattern)
+ {
+ context.NotNull(nameof(context));
+ pattern.NotNullOrWhiteSpace(nameof(pattern));
+
+ return FileLinkSettings.ForPattern(pattern);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking to files
+ /// based on a custom action.
+ ///
+ /// The context.
+ /// Callback called for building the file link.
+ /// File link settings.
+ /// Settings for linking files.
+ ///
+ /// Creates file link settings to an internal source hosting site with
+ /// parameters set dynamically, based on values of the issue:
+ ///
+ ///
+ /// {
+ /// var result =
+ /// new Uri("https://awesomesource/")
+ /// .Append(issue.FilePath());
+ ///
+ /// if (issue.Line.HasValue)
+ /// {
+ /// result = result.Append("?line={issue.Line.Value}")
+ /// }
+ ///
+ /// return result;
+ /// });
+ /// ]]>
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettings(
+ this ICakeContext context,
+ Func builder)
+ {
+ context.NotNull(nameof(context));
+ builder.NotNull(nameof(builder));
+
+ return FileLinkSettings.ForAction(builder);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking files hosted on GitHub on a specific branch.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://github.com/cake-contrib/Cake.Issues.Reporting.Generic
.
+ /// Name of the branch on which the file linking will be based on.
+ /// Settings for linking to files hosted in GitHub.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForGitHubBranch(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string branch)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ branch.NotNullOrWhiteSpace(nameof(branch));
+
+ return context.IssueFileLinkSettingsForGitHubBranch(repositoryUrl, branch, null);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking files hosted on GitHub
+ /// in a sub-folder on a specific branch.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://github.com/cake-contrib/Cake.Issues.Reporting.Generic
.
+ /// Name of the branch on which the file linking will be based on.
+ /// Root path of the files.
+ /// null if files are in the root of the repository.
+ /// Settings for linking to files hosted in GitHub.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForGitHubBranch(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string branch,
+ string rootPath)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ branch.NotNullOrWhiteSpace(nameof(branch));
+
+ return
+ FileLinkSettings
+ .ForGitHub(repositoryUrl)
+ .Branch(branch)
+ .WithRootPath(rootPath);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking files hosted on GitHub fo a specific commit.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://github.com/cake-contrib/Cake.Issues.Reporting.Generic
.
+ /// The commit id on which the file linking will be based on.
+ /// Settings for linking to files hosted in GitHub.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForGitHubCommit(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string commitId)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ commitId.NotNullOrWhiteSpace(nameof(commitId));
+
+ return context.IssueFileLinkSettingsForGitHubCommit(repositoryUrl, commitId, null);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking files hosted on GitHub
+ /// in a sub-folder for a specific commit.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://github.com/cake-contrib/Cake.Issues.Reporting.Generic
.
+ /// The commit id on which the file linking will be based on.
+ /// Root path of the files.
+ /// null or if files are in the root of the repository.
+ /// Settings for linking to files hosted in GitHub.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForGitHubCommit(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string commitId,
+ string rootPath)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ commitId.NotNullOrWhiteSpace(nameof(commitId));
+
+ return
+ FileLinkSettings
+ .ForGitHub(repositoryUrl)
+ .Commit(commitId)
+ .WithRootPath(rootPath);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking to files hosted in Azure DevOps
+ /// on a specific branch.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://dev.azure.com/myorganization/_git/myrepo
.
+ /// Name of the branch on which the file linking will be based on.
+ /// Settings for linking files hosted on Azure DevOps or Azure DevOps Server.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForAzureDevOpsBranch(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string branch)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ branch.NotNullOrWhiteSpace(nameof(branch));
+
+ return context.IssueFileLinkSettingsForAzureDevOpsBranch(repositoryUrl, branch, null);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking to files hosted in Azure DevOps
+ /// in a sub-folder on a specific branch.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://dev.azure.com/myorganization/_git/myrepo
.
+ /// Name of the branch on which the file linking will be based on.
+ /// Root path of the files.
+ /// null if files are in the root of the repository.
+ /// Settings for linking files hosted on Azure DevOps.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForAzureDevOpsBranch(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string branch,
+ string rootPath)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ branch.NotNullOrWhiteSpace(nameof(branch));
+
+ return
+ FileLinkSettings
+ .ForAzureDevOps(repositoryUrl)
+ .Branch(branch)
+ .WithRootPath(rootPath);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking to files hosted in Azure DevOps
+ /// for a specific commit.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://dev.azure.com/myorganization/_git/myrepo
.
+ /// The commit id on which the file linking will be based on.
+ /// Settings for linking files hosted on Azure DevOps or Azure DevOps Server.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForAzureDevOpsCommit(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string commitId)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ commitId.NotNullOrWhiteSpace(nameof(commitId));
+
+ return context.IssueFileLinkSettingsForAzureDevOpsCommit(repositoryUrl, commitId, null);
+ }
+
+ ///
+ /// Gets an instance of the file link settings for linking to files hosted in Azure DevOps
+ /// in a sub-folder for a specific commit.
+ ///
+ /// The context.
+ /// Full URL of the Git repository,
+ /// eg. https://dev.azure.com/myorganization/_git/myrepo
.
+ /// The commit id on which the file linking will be based on.
+ /// Root path of the files.
+ /// null if files are in the root of the repository.
+ /// Settings for linking files hosted on Azure DevOps.
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.FileLinkingCakeAliasCategory)]
+ public static FileLinkSettings IssueFileLinkSettingsForAzureDevOpsCommit(
+ this ICakeContext context,
+ Uri repositoryUrl,
+ string commitId,
+ string rootPath)
+ {
+ context.NotNull(nameof(context));
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+ commitId.NotNullOrWhiteSpace(nameof(commitId));
+
+ return
+ FileLinkSettings
+ .ForAzureDevOps(repositoryUrl)
+ .Commit(commitId)
+ .WithRootPath(rootPath);
+ }
+ }
+}
diff --git a/src/Cake.Issues/Aliases.NewIssue.cs b/src/Cake.Issues/Aliases.NewIssue.cs
index a97ee1172..3e23ad827 100644
--- a/src/Cake.Issues/Aliases.NewIssue.cs
+++ b/src/Cake.Issues/Aliases.NewIssue.cs
@@ -9,7 +9,7 @@
public static partial class Aliases
{
///
- /// Initiates the creation of a new .
+ /// Initiates the creation of a new with as identifier.
///
/// The context.
/// The message of the issue.
@@ -46,5 +46,54 @@ public static IssueBuilder NewIssue(
return IssueBuilder.NewIssue(message, providerType, providerName);
}
+
+ ///
+ /// Initiates the creation of a new .
+ ///
+ /// The context.
+ /// The identifier of the issue.
+ /// The message of the issue.
+ /// The unique identifier of the issue provider.
+ /// The human friendly name of the issue provider.
+ /// Builder class for creating a new .
+ ///
+ /// Create a new warning for the myfile.txt file on line 42:
+ ///
+ ///
+ ///
+ ///
+ [CakeMethodAlias]
+ [CakeAliasCategory(IssuesAliasConstants.CreateCakeAliasCategory)]
+ public static IssueBuilder NewIssue(
+ this ICakeContext context,
+ string identifier,
+ string message,
+ string providerType,
+ string providerName)
+ {
+#pragma warning disable SA1123 // Do not place regions within elements
+ #region DupFinder Exclusion
+#pragma warning restore SA1123 // Do not place regions within elements
+
+ context.NotNull(nameof(context));
+ identifier.NotNullOrWhiteSpace(nameof(identifier));
+ message.NotNullOrWhiteSpace(nameof(message));
+ providerType.NotNullOrWhiteSpace(nameof(providerType));
+ providerName.NotNullOrWhiteSpace(nameof(providerName));
+
+ #endregion
+
+ return IssueBuilder.NewIssue(identifier, message, providerType, providerName);
+ }
}
}
diff --git a/src/Cake.Issues/Aliases.ReadIssues.cs b/src/Cake.Issues/Aliases.ReadIssues.cs
index 1abb5a8d6..e961eeed2 100644
--- a/src/Cake.Issues/Aliases.ReadIssues.cs
+++ b/src/Cake.Issues/Aliases.ReadIssues.cs
@@ -99,13 +99,13 @@ public static IEnumerable ReadIssues(
/// The settings.
/// Issues reported by issue provider.
///
- /// Read issues reported by JetBrains inspect code and format comments in Markdown:
+ /// Read issues reported by JetBrains inspect code and set run information:
///
/// ReadIssues(
public static IEnumerable ReadIssues(
this ICakeContext context,
IIssueProvider issueProvider,
- ReadIssuesSettings settings)
+ IReadIssuesSettings settings)
{
context.NotNull(nameof(context));
issueProvider.NotNull(nameof(issueProvider));
@@ -142,13 +142,13 @@ public static IEnumerable ReadIssues(
/// Issues reported by all issue providers.
///
/// Read issues reported as MsBuild warnings and issues reported by JetBrains inspect code
- /// with comments formatted as Markdown:
+ /// and set run information:
///
/// ReadIssues(
public static IEnumerable ReadIssues(
this ICakeContext context,
IEnumerable issueProviders,
- ReadIssuesSettings settings)
+ IReadIssuesSettings settings)
{
context.NotNull(nameof(context));
settings.NotNull(nameof(settings));
diff --git a/src/Cake.Issues/BaseIssueComponent.cs b/src/Cake.Issues/BaseIssueComponent.cs
index 049481873..e56c0f404 100644
--- a/src/Cake.Issues/BaseIssueComponent.cs
+++ b/src/Cake.Issues/BaseIssueComponent.cs
@@ -8,7 +8,7 @@
///
/// Type of settings.
public abstract class BaseIssueComponent : IBaseIssueComponent
- where T : RepositorySettings
+ where T : class, IRepositorySettings
{
///
/// Initializes a new instance of the class.
diff --git a/src/Cake.Issues/BaseIssueProvider.cs b/src/Cake.Issues/BaseIssueProvider.cs
index e3eeb928b..af26171bc 100644
--- a/src/Cake.Issues/BaseIssueProvider.cs
+++ b/src/Cake.Issues/BaseIssueProvider.cs
@@ -6,7 +6,7 @@
///
/// Base class for all issue provider implementations.
///
- public abstract class BaseIssueProvider : BaseIssueComponent, IIssueProvider
+ public abstract class BaseIssueProvider : BaseIssueComponent, IIssueProvider
{
///
/// Initializes a new instance of the class.
diff --git a/src/Cake.Issues/BaseLogFileFormat.cs b/src/Cake.Issues/BaseLogFileFormat.cs
index facf44245..5c70409e2 100644
--- a/src/Cake.Issues/BaseLogFileFormat.cs
+++ b/src/Cake.Issues/BaseLogFileFormat.cs
@@ -31,7 +31,7 @@ protected BaseLogFileFormat(ICakeLog log)
///
public abstract IEnumerable ReadIssues(
TIssueProvider issueProvider,
- RepositorySettings repositorySettings,
+ IRepositorySettings repositorySettings,
TSettings issueProviderSettings);
}
}
diff --git a/src/Cake.Issues/Cake.Issues.csproj b/src/Cake.Issues/Cake.Issues.csproj
index bafe543eb..0bbfc481a 100644
--- a/src/Cake.Issues/Cake.Issues.csproj
+++ b/src/Cake.Issues/Cake.Issues.csproj
@@ -24,7 +24,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Cake.Issues/FileLinkSettings.cs b/src/Cake.Issues/FileLinkSettings.cs
new file mode 100644
index 000000000..c1c54fcc3
--- /dev/null
+++ b/src/Cake.Issues/FileLinkSettings.cs
@@ -0,0 +1,95 @@
+namespace Cake.Issues
+{
+ using System;
+ using System.Collections.Generic;
+ using Cake.Issues.FileLinking;
+
+ ///
+ /// Settings how issues should be linked to files.
+ ///
+ public class FileLinkSettings
+ {
+ private readonly Func, Uri> builder;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Callback called for building the file link.
+ internal FileLinkSettings(Func, Uri> builder)
+ {
+ builder.NotNull(nameof(builder));
+
+ this.builder = builder;
+ }
+
+ ///
+ /// Returns settings to link files based on a custom pattern.
+ ///
+ /// Pattern of the file link.
+ /// See
+ /// for a list of tokens supported in the pattern.
+ /// File link settings.
+ public static FileLinkSettings ForPattern(string pattern)
+ {
+ pattern.NotNullOrWhiteSpace(nameof(pattern));
+
+ return
+ new FileLinkSettings(
+ (issue, values) =>
+ {
+ return new Uri(pattern.ReplaceIssuePattern(issue));
+ });
+ }
+
+ ///
+ /// Returns settings to link files based on a custom pattern.
+ ///
+ /// Callback called for building the file link.
+ /// File link settings.
+ public static FileLinkSettings ForAction(Func builder)
+ {
+ builder.NotNull(nameof(builder));
+
+ return new FileLinkSettings((issue, values) => builder(issue));
+ }
+
+ ///
+ /// Returns builder class for settings for linking to files hosted in GitHub.
+ ///
+ /// Full URL of the Git repository,
+ /// eg. https://github.com/cake-contrib/Cake.Issues
.
+ /// Builder class for the settings.
+ public static GitHubFileLinkSettingsBuilder ForGitHub(Uri repositoryUrl)
+ {
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+
+ return new GitHubFileLinkSettingsBuilder(repositoryUrl);
+ }
+
+ ///
+ /// Returns builder class for settings for linking to files hosted in Azure DevOps.
+ ///
+ /// Full URL of the Git repository,
+ /// e.g. https://dev.azure.com/myorganization/_git/myrepo
.
+ /// Builder class for the settings.
+ public static AzureDevOpsFileLinkSettingsBuilder ForAzureDevOps(Uri repositoryUrl)
+ {
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+
+ return new AzureDevOpsFileLinkSettingsBuilder(repositoryUrl);
+ }
+
+ ///
+ /// Returns the URL to the file on the source code hosting system
+ /// for the issue .
+ ///
+ /// Issue for which the link should be returned.
+ /// URL to the file on the source code hosting system.
+ public Uri GetFileLink(IIssue issue)
+ {
+ issue.NotNull(nameof(issue));
+
+ return this.builder(issue, new Dictionary());
+ }
+ }
+}
diff --git a/src/Cake.Issues/FileLinking/AzureDevOpsFileLinkSettingsBuilder.cs b/src/Cake.Issues/FileLinking/AzureDevOpsFileLinkSettingsBuilder.cs
new file mode 100644
index 000000000..1351a7f58
--- /dev/null
+++ b/src/Cake.Issues/FileLinking/AzureDevOpsFileLinkSettingsBuilder.cs
@@ -0,0 +1,97 @@
+namespace Cake.Issues.FileLinking
+{
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// Class for building settings for file links of files hosted on Azure DevOps.
+ ///
+ public class AzureDevOpsFileLinkSettingsBuilder
+ {
+ private readonly Uri repositoryUrl;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Full URL of the Git repository,
+ /// eg. https://github.com/cake-contrib/Cake.Issues
.
+ internal AzureDevOpsFileLinkSettingsBuilder(Uri repositoryUrl)
+ {
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+
+ this.repositoryUrl = repositoryUrl;
+ }
+
+ ///
+ /// Returns settings to files on AzureDevOps on a specific branch.
+ ///
+ /// Name of the branch.
+ /// Class for setting additional settings.
+ public FileLinkOptionalSettingsBuilder Branch(string branchName)
+ {
+ branchName.NotNullOrWhiteSpace(nameof(branchName));
+
+ return
+ new FileLinkOptionalSettingsBuilder(
+ (issue, values) =>
+ {
+ issue.NotNull(nameof(issue));
+ values.NotNull(nameof(values));
+
+ var fileLinkPattern =
+ this.GetFileLinkPattern(issue, values, "GB", branchName);
+ return new Uri(fileLinkPattern.ReplaceIssuePattern(issue));
+ });
+ }
+
+ ///
+ /// Returns settings to files on AzureDevOps on a specific commit.
+ ///
+ /// The commit id on which the file linking will be based on.
+ /// Class for setting additional settings.
+ public FileLinkOptionalSettingsBuilder Commit(string commitId)
+ {
+ commitId.NotNullOrWhiteSpace(nameof(commitId));
+
+ return
+ new FileLinkOptionalSettingsBuilder(
+ (issue, values) =>
+ {
+ issue.NotNull(nameof(issue));
+ values.NotNull(nameof(values));
+
+ var fileLinkPattern =
+ this.GetFileLinkPattern(issue, values, "GC", commitId);
+ return new Uri(fileLinkPattern.ReplaceIssuePattern(issue));
+ });
+ }
+
+ private string GetFileLinkPattern(
+ IIssue issue,
+ IDictionary values,
+ string versionType,
+ string version)
+ {
+ issue.NotNull(nameof(issue));
+ values.NotNull(nameof(values));
+ versionType.NotNullOrWhiteSpace(nameof(versionType));
+ version.NotNullOrWhiteSpace(nameof(version));
+
+ var result =
+ this.repositoryUrl.ToString().TrimEnd('/') +
+ "?path=/" + values.GetValueOrDefault("rootPath", null)?.TrimStart('/').WithEnding("/") + "{FilePath}" +
+ "&version=" + versionType + version;
+
+ if (issue.Line.HasValue)
+ {
+ result +=
+ "&line={Line}" +
+ "&lineEnd=" + (issue.EndLine.HasValue ? "{EndLine}" : "{Line}") +
+ "&lineStartColumn=" + (issue.Column.HasValue ? "{Column}" : "1") +
+ "&lineEndColumn=" + (issue.EndColumn.HasValue ? "{EndColumn}" : int.MaxValue.ToString());
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/Cake.Issues/FileLinking/FileLinkOptionalSettingsBuilder.cs b/src/Cake.Issues/FileLinking/FileLinkOptionalSettingsBuilder.cs
new file mode 100644
index 000000000..f8a776144
--- /dev/null
+++ b/src/Cake.Issues/FileLinking/FileLinkOptionalSettingsBuilder.cs
@@ -0,0 +1,53 @@
+namespace Cake.Issues.FileLinking
+{
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// Class containing builder for optional settings for linking to files.
+ ///
+ public class FileLinkOptionalSettingsBuilder : FileLinkSettings
+ {
+ private readonly Func, Uri> builder;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Callback called for building the file link.
+ internal FileLinkOptionalSettingsBuilder(Func, Uri> builder)
+ : base(builder)
+ {
+ builder.NotNull(nameof(builder));
+
+ this.builder = builder;
+ }
+
+ ///
+ /// Sets the root path for the files.
+ ///
+ /// Root path for the files.
+ /// null if files are in the root of the repository.
+ /// Object for creating the file link.
+ public FileLinkSettings WithRootPath(string rootPath)
+ {
+ if (rootPath != null)
+ {
+ rootPath.NotNullOrWhiteSpace(nameof(rootPath));
+
+ if (!rootPath.IsValidPath())
+ {
+ throw new ArgumentException($"Invalid path '{rootPath}'", nameof(rootPath));
+ }
+ }
+
+ return
+ new FileLinkSettings(
+ (issue, values) =>
+ {
+ values.Add("rootPath", rootPath);
+
+ return this.builder(issue, values);
+ });
+ }
+ }
+}
diff --git a/src/Cake.Issues/FileLinking/GitHubFileLinkSettingsBuilder.cs b/src/Cake.Issues/FileLinking/GitHubFileLinkSettingsBuilder.cs
new file mode 100644
index 000000000..c8a6f8ccc
--- /dev/null
+++ b/src/Cake.Issues/FileLinking/GitHubFileLinkSettingsBuilder.cs
@@ -0,0 +1,102 @@
+namespace Cake.Issues.FileLinking
+{
+ using System;
+
+ ///
+ /// Class for building settings for file links of files hosted on GitHub.
+ ///
+ public class GitHubFileLinkSettingsBuilder
+ {
+ private readonly Uri repositoryUrl;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Full URL of the Git repository,
+ /// eg. https://github.com/cake-contrib/Cake.Issues
.
+ internal GitHubFileLinkSettingsBuilder(Uri repositoryUrl)
+ {
+ repositoryUrl.NotNull(nameof(repositoryUrl));
+
+ this.repositoryUrl = repositoryUrl;
+ }
+
+ ///
+ /// Returns settings to files on GitHub on a specific branch.
+ ///
+ /// Name of the branch.
+ /// Class for setting additional settings.
+ public FileLinkOptionalSettingsBuilder Branch(string branchName)
+ {
+ branchName.NotNullOrWhiteSpace(nameof(branchName));
+
+ return
+ new FileLinkOptionalSettingsBuilder(
+ (issue, values) =>
+ {
+ issue.NotNull(nameof(issue));
+ values.NotNull(nameof(values));
+
+ var fileLinkPattern =
+ this.repositoryUrl.Append(
+ "blob",
+ branchName,
+ values.GetValueOrDefault("rootPath", null),
+ GetFilePathPattern(issue)).ToString();
+
+ return new Uri(fileLinkPattern.ReplaceIssuePattern(issue));
+ });
+ }
+
+ ///
+ /// Returns settings to files on GitHub on a specific commit.
+ ///
+ /// The commit id on which the file linking will be based on.
+ /// Class for setting additional settings.
+ public FileLinkOptionalSettingsBuilder Commit(string commitId)
+ {
+ commitId.NotNullOrWhiteSpace(nameof(commitId));
+
+ return
+ new FileLinkOptionalSettingsBuilder(
+ (issue, values) =>
+ {
+ issue.NotNull(nameof(issue));
+ values.NotNull(nameof(values));
+
+ var fileLinkPattern =
+ this.repositoryUrl.Append(
+ "blob",
+ commitId,
+ values.GetValueOrDefault("rootPath", null),
+ GetFilePathPattern(issue)).ToString();
+
+ return new Uri(fileLinkPattern.ReplaceIssuePattern(issue));
+ });
+ }
+
+ ///
+ /// Returns the pattern for the file path and line information.
+ ///
+ /// Issue for which the pattern should be returned.
+ /// Pattern.
+ private static string GetFilePathPattern(IIssue issue)
+ {
+ issue.NotNull(nameof(issue));
+
+ var filePathPattern = "{FilePath}";
+
+ if (issue.Line.HasValue)
+ {
+ filePathPattern += "#L{Line}";
+ }
+
+ if (issue.EndLine.HasValue)
+ {
+ filePathPattern += "-L{EndLine}";
+ }
+
+ return filePathPattern;
+ }
+ }
+}
diff --git a/src/Cake.Issues/FileLinking/IDictionaryExtensions.cs b/src/Cake.Issues/FileLinking/IDictionaryExtensions.cs
new file mode 100644
index 000000000..bc08a5638
--- /dev/null
+++ b/src/Cake.Issues/FileLinking/IDictionaryExtensions.cs
@@ -0,0 +1,29 @@
+namespace Cake.Issues.FileLinking
+{
+ using System.Collections.Generic;
+
+ ///
+ /// Extensions for .
+ ///
+ internal static class IDictionaryExtensions
+ {
+ ///
+ /// Gets the value associated with a key or the default value.
+ ///
+ /// Type of the key in the dictionary.
+ /// Type of the value in the dictionary.
+ /// Dictionary to read the key from.
+ /// The key whose value to get.
+ /// Value to return if key does not exist.
+ /// The value associated with the key if it exists or .
+ public static TValue GetValueOrDefault(
+ this IDictionary dictionary,
+ TKey key,
+ TValue defaultValue)
+ {
+ dictionary.NotNull(nameof(dictionary));
+
+ return dictionary.TryGetValue(key, out var value) ? value : defaultValue;
+ }
+ }
+}
diff --git a/src/Cake.Issues/IBaseIssueComponent.cs b/src/Cake.Issues/IBaseIssueComponent.cs
index 8d10ddc91..435418dac 100644
--- a/src/Cake.Issues/IBaseIssueComponent.cs
+++ b/src/Cake.Issues/IBaseIssueComponent.cs
@@ -7,7 +7,7 @@
///
/// Type of settings.
public interface IBaseIssueComponent
- where T : RepositorySettings
+ where T : IRepositorySettings
{
///
/// Initializes the component.
diff --git a/src/Cake.Issues/IIssue.cs b/src/Cake.Issues/IIssue.cs
index 0a90ff793..a0a32e262 100644
--- a/src/Cake.Issues/IIssue.cs
+++ b/src/Cake.Issues/IIssue.cs
@@ -8,6 +8,12 @@
///
public interface IIssue
{
+ ///
+ /// Gets the identifier for the message.
+ /// The identifier can be used to identify the same issue across multiple runs.
+ ///
+ string Identifier { get; }
+
///
/// Gets the path to the project to which the file affected by the issue belongs.
/// The path is relative to the repository root.
@@ -34,6 +40,30 @@ public interface IIssue
///
int? Line { get; }
+ ///
+ /// Gets the end of the line range in the file where the issues has occurred.
+ /// null if the issue affects the whole file, an asssembly or only a single line.
+ ///
+ int? EndLine { get; }
+
+ ///
+ /// Gets the column in the file where the issues has occurred.
+ /// null if the issue affects the whole file or an asssembly.
+ ///
+ int? Column { get; }
+
+ ///
+ /// Gets the end of the column range in the file where the issues has occurred.
+ /// null if the issue affects the whole file, an asssembly or only a single column.
+ ///
+ int? EndColumn { get; }
+
+ ///
+ /// Gets or sets a link to the position in the file where the issue ocurred.
+ /// null if was not set while reading issue.
+ ///
+ Uri FileLink { get; set; }
+
///
/// Gets the message of the issue in text format.
///
@@ -73,6 +103,12 @@ public interface IIssue
///
Uri RuleUrl { get; }
+ ///
+ /// Gets or sets the description of the run.
+ /// Can be null or if no run information is provided.
+ ///
+ string Run { get; set; }
+
///
/// Gets the type of the issue provider.
///
diff --git a/src/Cake.Issues/IIssueComparer.cs b/src/Cake.Issues/IIssueComparer.cs
index d7367fba3..dfb3e251e 100644
--- a/src/Cake.Issues/IIssueComparer.cs
+++ b/src/Cake.Issues/IIssueComparer.cs
@@ -38,6 +38,18 @@ public IIssueComparer()
/// -
///
///
+ /// -
+ ///
+ ///
+ /// -
+ ///
+ ///
+ /// -
+ ///
+ ///
+ /// -
+ ///
+ ///
///
///
public IIssueComparer(bool compareOnlyPersistentProperties)
@@ -59,10 +71,15 @@ public bool Equals(IIssue x, IIssue y)
}
return
+ (x.Identifier == y.Identifier) &&
(this.compareOnlyPersistentProperties || x.ProjectFileRelativePath?.FullPath == y.ProjectFileRelativePath?.FullPath) &&
(x.ProjectName == y.ProjectName) &&
(this.compareOnlyPersistentProperties || x.AffectedFileRelativePath?.FullPath == y.AffectedFileRelativePath?.FullPath) &&
(this.compareOnlyPersistentProperties || x.Line == y.Line) &&
+ (this.compareOnlyPersistentProperties || x.EndLine == y.EndLine) &&
+ (this.compareOnlyPersistentProperties || x.Column == y.Column) &&
+ (this.compareOnlyPersistentProperties || x.EndColumn == y.EndColumn) &&
+ (this.compareOnlyPersistentProperties || x.FileLink == y.FileLink) &&
(x.MessageText == y.MessageText) &&
(x.MessageHtml == y.MessageHtml) &&
(x.MessageMarkdown == y.MessageMarkdown) &&
@@ -70,6 +87,7 @@ public bool Equals(IIssue x, IIssue y)
(x.PriorityName == y.PriorityName) &&
(x.Rule == y.Rule) &&
(x.RuleUrl?.ToString() == y.RuleUrl?.ToString()) &&
+ (x.Run == y.Run) &&
(x.ProviderType == y.ProviderType) &&
(x.ProviderName == y.ProviderName);
}
@@ -86,6 +104,7 @@ public int GetHashCode(IIssue obj)
{
return
GetHashCode(
+ obj.Identifier,
obj.ProjectName,
obj.MessageText,
obj.MessageHtml,
@@ -94,6 +113,7 @@ public int GetHashCode(IIssue obj)
obj.PriorityName,
obj.Rule,
obj.RuleUrl,
+ obj.Run,
obj.ProviderType,
obj.ProviderName);
}
@@ -101,10 +121,15 @@ public int GetHashCode(IIssue obj)
{
return
GetHashCode(
+ obj.Identifier,
obj.ProjectFileRelativePath?.ToString(),
obj.ProjectName,
obj.AffectedFileRelativePath?.ToString(),
obj.Line,
+ obj.EndLine,
+ obj.Column,
+ obj.EndColumn,
+ obj.FileLink,
obj.MessageText,
obj.MessageHtml,
obj.MessageMarkdown,
@@ -112,6 +137,7 @@ public int GetHashCode(IIssue obj)
obj.PriorityName,
obj.Rule,
obj.RuleUrl,
+ obj.Run,
obj.ProviderType,
obj.ProviderName);
}
diff --git a/src/Cake.Issues/IIssueExtensions.cs b/src/Cake.Issues/IIssueExtensions.cs
index 4c3c604bc..efd1710b5 100644
--- a/src/Cake.Issues/IIssueExtensions.cs
+++ b/src/Cake.Issues/IIssueExtensions.cs
@@ -7,6 +7,53 @@
///
public static class IIssueExtensions
{
+ ///
+ /// Returns the line and column range in the format {Line}:{Column}-{EndLine}:{EndColumn}.
+ ///
+ /// Issue for which the line and column range should be returned.
+ /// Line and column range.
+ public static string LineRange(this IIssue issue)
+ {
+ issue.NotNull(nameof(issue));
+
+ return issue.LineRange(true);
+ }
+
+ ///
+ /// Returns the line range in the format {Line}:{Column}-{EndLine}:{EndColumn}.
+ ///
+ /// Issue for which the line range should be returned.
+ /// Flag if column information should also be returned.
+ /// Line and column range.
+ public static string LineRange(this IIssue issue, bool addColumn)
+ {
+ issue.NotNull(nameof(issue));
+
+ string result = string.Empty;
+
+ if (issue.Line.HasValue)
+ {
+ result += issue.Line.ToString();
+
+ if (addColumn && issue.Column.HasValue)
+ {
+ result += $":{issue.Column.Value}";
+ }
+
+ if (issue.EndLine.HasValue)
+ {
+ result += $"-{issue.EndLine.Value}";
+
+ if (addColumn && issue.EndColumn.HasValue)
+ {
+ result += $":{issue.EndColumn.Value}";
+ }
+ }
+ }
+
+ return result;
+ }
+
///
/// Gets the message of the issue in a specific format.
/// If the message is not available in the specific format, the message in
@@ -20,17 +67,13 @@ public static string Message(this IIssue issue, IssueCommentFormat format)
{
issue.NotNull(nameof(issue));
- switch (format)
+ return format switch
{
- case IssueCommentFormat.PlainText:
- return issue.MessageText;
- case IssueCommentFormat.Html:
- return !string.IsNullOrEmpty(issue.MessageHtml) ? issue.MessageHtml : issue.MessageText;
- case IssueCommentFormat.Markdown:
- return !string.IsNullOrEmpty(issue.MessageMarkdown) ? issue.MessageMarkdown : issue.MessageText;
- default:
- throw new ArgumentOutOfRangeException(nameof(format));
- }
+ IssueCommentFormat.PlainText => issue.MessageText,
+ IssueCommentFormat.Html => !string.IsNullOrEmpty(issue.MessageHtml) ? issue.MessageHtml : issue.MessageText,
+ IssueCommentFormat.Markdown => !string.IsNullOrEmpty(issue.MessageMarkdown) ? issue.MessageMarkdown : issue.MessageText,
+ _ => throw new ArgumentOutOfRangeException(nameof(format)),
+ };
}
///
@@ -97,10 +140,10 @@ public static string FileName(this IIssue issue)
/// Returns a string with all patterns replaced by the values of .
///
/// Pattern whose values should be replaced.
- /// The following patterns are supported:
+ /// The following tokens are supported:
///
///
- /// Pattern
+ /// Token
/// Description
///
/// -
@@ -112,6 +155,10 @@ public static string FileName(this IIssue issue)
/// The value of .
///
/// -
+ /// {Identifier}
+ /// The value of .
+ ///
+ /// -
/// {Priority}
/// The value of .
///
@@ -148,6 +195,22 @@ public static string FileName(this IIssue issue)
/// The value of .
///
/// -
+ /// {EndLine}
+ /// The value of .
+ ///
+ /// -
+ /// {Column}
+ /// The value of .
+ ///
+ /// -
+ /// {EndColumn}
+ /// The value of .
+ ///
+ /// -
+ /// {FileLink}
+ /// The value of .
+ ///
+ /// -
/// {Rule}
/// The value of .
///
@@ -156,6 +219,10 @@ public static string FileName(this IIssue issue)
/// The value of .
///
/// -
+ /// {Run}
+ /// The value of .
+ ///
+ /// -
/// {MessageText}
/// The value of .
///
@@ -182,6 +249,7 @@ public static string ReplaceIssuePattern(this string pattern, IIssue issue)
pattern
.Replace("{ProviderType}", issue.ProviderType)
.Replace("{ProviderName}", issue.ProviderName)
+ .Replace("{Identifier}", issue.Identifier)
.Replace("{Priority}", issue.Priority?.ToString())
.Replace("{PriorityName}", issue.PriorityName)
.Replace("{ProjectPath}", issue.ProjectPath())
@@ -191,8 +259,13 @@ public static string ReplaceIssuePattern(this string pattern, IIssue issue)
.Replace("{FileDirectory}", issue.FileDirectory())
.Replace("{FileName}", issue.FileName())
.Replace("{Line}", issue.Line?.ToString())
+ .Replace("{EndLine}", issue.EndLine?.ToString())
+ .Replace("{Column}", issue.Column?.ToString())
+ .Replace("{EndColumn}", issue.EndColumn?.ToString())
+ .Replace("{FileLink}", issue.FileLink?.ToString())
.Replace("{Rule}", issue.Rule)
.Replace("{RuleUrl}", issue.RuleUrl?.ToString())
+ .Replace("{Run}", issue.Run)
.Replace("{MessageText}", issue.Message(IssueCommentFormat.PlainText))
.Replace("{MessageHtml}", issue.Message(IssueCommentFormat.Html))
.Replace("{MessageMarkdown}", issue.Message(IssueCommentFormat.Markdown));
diff --git a/src/Cake.Issues/IIssueProvider.cs b/src/Cake.Issues/IIssueProvider.cs
index dd3231b46..63a6ccb62 100644
--- a/src/Cake.Issues/IIssueProvider.cs
+++ b/src/Cake.Issues/IIssueProvider.cs
@@ -5,7 +5,7 @@
///
/// Interface describing a provider for issues.
///
- public interface IIssueProvider : IBaseIssueComponent
+ public interface IIssueProvider : IBaseIssueComponent
{
///
/// Gets the human friendly name of the issue provider.
diff --git a/src/Cake.Issues/ILogFileFormat.cs b/src/Cake.Issues/ILogFileFormat.cs
index 457bc8f12..663536495 100644
--- a/src/Cake.Issues/ILogFileFormat.cs
+++ b/src/Cake.Issues/ILogFileFormat.cs
@@ -20,7 +20,7 @@ public interface ILogFileFormat
/// List of issues.
IEnumerable ReadIssues(
TIssueProvider issueProvider,
- RepositorySettings repositorySettings,
+ IRepositorySettings repositorySettings,
TSettings issueProviderSettings);
}
}
diff --git a/src/Cake.Issues/IReadIssuesSettings.cs b/src/Cake.Issues/IReadIssuesSettings.cs
new file mode 100644
index 000000000..8adb7ba94
--- /dev/null
+++ b/src/Cake.Issues/IReadIssuesSettings.cs
@@ -0,0 +1,18 @@
+namespace Cake.Issues
+{
+ ///
+ /// Interface for settings for reading issues.
+ ///
+ public interface IReadIssuesSettings : IRepositorySettings
+ {
+ ///
+ /// Gets or sets the name of the run.
+ ///
+ string Run { get; set; }
+
+ ///
+ /// Gets or sets settings which can be used for resolving links to source files.
+ ///
+ FileLinkSettings FileLinkSettings { get; set; }
+ }
+}
diff --git a/src/Cake.Issues/IRepositorySettings.cs b/src/Cake.Issues/IRepositorySettings.cs
new file mode 100644
index 000000000..0ce5a9e87
--- /dev/null
+++ b/src/Cake.Issues/IRepositorySettings.cs
@@ -0,0 +1,15 @@
+namespace Cake.Issues
+{
+ using Cake.Core.IO;
+
+ ///
+ /// Interface for settings containing a path to a repository.
+ ///
+ public interface IRepositorySettings
+ {
+ ///
+ /// Gets the Root path of the repository.
+ ///
+ DirectoryPath RepositoryRoot { get; }
+ }
+}
diff --git a/src/Cake.Issues/Issue.cs b/src/Cake.Issues/Issue.cs
index e699c512b..a7c7f958b 100644
--- a/src/Cake.Issues/Issue.cs
+++ b/src/Cake.Issues/Issue.cs
@@ -11,6 +11,8 @@ public class Issue : IIssue
///
/// Initializes a new instance of the class.
///
+ /// The identifier of the issue.
+ /// The identifier needs to be identical across multiple runs of an issue provider for the same issue.
/// The path to the project to which the file affected by the issue belongs.
/// The path needs to be relative to the repository root.
/// Can be null or if issue is not related to a project.
@@ -21,6 +23,14 @@ public class Issue : IIssue
/// null or if issue is not related to a change in a file.
/// The line in the file where the issues has occurred.
/// null if the issue affects the whole file or an asssembly.
+ /// The end of the line range in the file where the issues has occurred.
+ /// null if the issue affects the whole file, an asssembly or only a single line.
+ /// The column in the file where the issues has occurred.
+ /// null if the issue affects the whole file or an asssembly.
+ /// The end of the column range in the file where the issues has occurred.
+ /// null if the issue affects the whole file, an asssembly or only a single column.
+ /// Link to the position in the file where the issue ocurred.
+ /// null if no link is available.
/// The message of the issue in plain text format.
/// The message of the issue in Html format.
/// The message of the issue in Markdown format.
@@ -32,13 +42,19 @@ public class Issue : IIssue
/// null or if issue has no specific rule ID.
/// The URL containing information about the failing rule.
/// null if no URL is available.
+ /// Gets the description of the run.
/// The type of the issue provider.
/// The human friendly name of the issue provider.
public Issue(
+ string identifier,
string projectFileRelativePath,
string projectName,
string affectedFileRelativePath,
int? line,
+ int? endLine,
+ int? column,
+ int? endColumn,
+ Uri fileLink,
string messageText,
string messageHtml,
string messageMarkdown,
@@ -46,10 +62,15 @@ public Issue(
string priorityName,
string rule,
Uri ruleUrl,
+ string run,
string providerType,
string providerName)
{
+ identifier.NotNullOrWhiteSpace(nameof(identifier));
line?.NotNegativeOrZero(nameof(line));
+ endLine?.NotNegativeOrZero(nameof(endLine));
+ column?.NotNegativeOrZero(nameof(column));
+ endColumn?.NotNegativeOrZero(nameof(endColumn));
messageText.NotNullOrWhiteSpace(nameof(messageText));
providerType.NotNullOrWhiteSpace(nameof(providerType));
providerName.NotNullOrWhiteSpace(nameof(providerName));
@@ -95,8 +116,38 @@ public Issue(
throw new ArgumentOutOfRangeException(nameof(line), "Cannot specify a line while not specifying a file.");
}
+ if (!line.HasValue && (column.HasValue || endColumn.HasValue))
+ {
+ throw new ArgumentOutOfRangeException(nameof(column), $"Cannot specify a column while not specifying a line.");
+ }
+
+ if (!line.HasValue && endLine.HasValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(endLine), $"Cannot specify the end of line range while not specifying start of line range.");
+ }
+
+ if (line.HasValue && endLine.HasValue && line.Value > endLine.Value)
+ {
+ throw new ArgumentOutOfRangeException(nameof(endLine), $"Line range needs to end after start of range.");
+ }
+
+ if (!column.HasValue && endColumn.HasValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(endColumn), $"Cannot specify the end of column range while not specifying start of column range.");
+ }
+
+ if (column.HasValue && endColumn.HasValue && column.Value > endColumn.Value)
+ {
+ throw new ArgumentOutOfRangeException(nameof(endColumn), $"Column range needs to end after start of range.");
+ }
+
+ this.Identifier = identifier;
this.ProjectName = projectName;
this.Line = line;
+ this.EndLine = endLine;
+ this.Column = column;
+ this.EndColumn = endColumn;
+ this.FileLink = fileLink;
this.MessageText = messageText;
this.MessageHtml = messageHtml;
this.MessageMarkdown = messageMarkdown;
@@ -104,10 +155,14 @@ public Issue(
this.PriorityName = priorityName;
this.Rule = rule;
this.RuleUrl = ruleUrl;
+ this.Run = run;
this.ProviderType = providerType;
this.ProviderName = providerName;
}
+ ///
+ public string Identifier { get; }
+
///
public FilePath ProjectFileRelativePath { get; }
@@ -120,6 +175,18 @@ public Issue(
///
public int? Line { get; }
+ ///
+ public int? EndLine { get; }
+
+ ///
+ public int? Column { get; }
+
+ ///
+ public int? EndColumn { get; }
+
+ ///
+ public Uri FileLink { get; set; }
+
///
public string MessageText { get; }
@@ -141,6 +208,9 @@ public Issue(
///
public Uri RuleUrl { get; }
+ ///
+ public string Run { get; set; }
+
///
public string ProviderType { get; }
diff --git a/src/Cake.Issues/IssueBuilder.cs b/src/Cake.Issues/IssueBuilder.cs
index aee2041d6..5058deae7 100644
--- a/src/Cake.Issues/IssueBuilder.cs
+++ b/src/Cake.Issues/IssueBuilder.cs
@@ -7,6 +7,7 @@
///
public class IssueBuilder
{
+ private readonly string identifier;
private readonly string providerType;
private readonly string providerName;
private readonly string messageText;
@@ -16,58 +17,79 @@ public class IssueBuilder
private string projectName;
private string filePath;
private int? line;
+ private int? endLine;
+ private int? column;
+ private int? endColumn;
+ private Uri fileLink;
private int? priority;
private string priorityName;
private string rule;
private Uri ruleUrl;
+ private string run;
///
/// Initializes a new instance of the class.
///
+ /// The identifier of the message.
/// The message of the issue in plain text format.
/// The type of the issue provider.
/// The human friendly name of the issue provider.
private IssueBuilder(
+ string identifier,
string message,
string providerType,
string providerName)
{
+#pragma warning disable SA1123 // Do not place regions within elements
+ #region DupFinder Exclusion
+#pragma warning restore SA1123 // Do not place regions within elements
+
+ identifier.NotNullOrWhiteSpace(nameof(identifier));
message.NotNullOrWhiteSpace(nameof(message));
providerType.NotNullOrWhiteSpace(nameof(providerType));
providerName.NotNullOrWhiteSpace(nameof(providerName));
+ #endregion
+
+ this.identifier = identifier;
this.messageText = message;
this.providerType = providerType;
this.providerName = providerName;
}
///
- /// Initiates the creation of a new .
+ /// Initiates the creation of a new with
+ /// as identifier.
///
+ /// Type of the issue provider which has the issue created.
/// The message of the issue in plain text format.
- /// The type of the issue provider.
- /// The human friendly name of the issue provider.
+ /// Issue provider which has the issue created.
/// Builder class for creating a new issue.
- public static IssueBuilder NewIssue(
+ public static IssueBuilder NewIssue(
string message,
- string providerType,
- string providerName)
+ T issueProvider)
+ where T : IIssueProvider
{
+ if (issueProvider == null)
+ {
+ throw new ArgumentNullException(nameof(issueProvider));
+ }
+
message.NotNullOrWhiteSpace(nameof(message));
- providerType.NotNullOrWhiteSpace(nameof(providerType));
- providerName.NotNullOrWhiteSpace(nameof(providerName));
- return new IssueBuilder(message, providerType, providerName);
+ return NewIssue(message, message, issueProvider);
}
///
/// Initiates the creation of a new .
///
/// Type of the issue provider which has the issue created.
+ /// The identifier of the message.
/// The message of the issue in plain text format.
/// Issue provider which has the issue created.
/// Builder class for creating a new issue.
public static IssueBuilder NewIssue(
+ string identifier,
string message,
T issueProvider)
where T : IIssueProvider
@@ -79,7 +101,54 @@ public static IssueBuilder NewIssue(
message.NotNullOrWhiteSpace(nameof(message));
- return new IssueBuilder(message, typeof(T).FullName, issueProvider.ProviderName);
+ return NewIssue(identifier, message, typeof(T).FullName, issueProvider.ProviderName);
+ }
+
+ ///
+ /// Initiates the creation of a new with as identifier.
+ ///
+ /// The message of the issue in plain text format.
+ /// The type of the issue provider.
+ /// The human friendly name of the issue provider.
+ /// Builder class for creating a new issue.
+ public static IssueBuilder NewIssue(
+ string message,
+ string providerType,
+ string providerName)
+ {
+ message.NotNullOrWhiteSpace(nameof(message));
+ providerType.NotNullOrWhiteSpace(nameof(providerType));
+ providerName.NotNullOrWhiteSpace(nameof(providerName));
+
+ return NewIssue(message, message, providerType, providerName);
+ }
+
+ ///
+ /// Initiates the creation of a new .
+ ///
+ /// The identifier of the message.
+ /// The message of the issue in plain text format.
+ /// The type of the issue provider.
+ /// The human friendly name of the issue provider.
+ /// Builder class for creating a new issue.
+ public static IssueBuilder NewIssue(
+ string identifier,
+ string message,
+ string providerType,
+ string providerName)
+ {
+#pragma warning disable SA1123 // Do not place regions within elements
+ #region DupFinder Exclusion
+#pragma warning restore SA1123 // Do not place regions within elements
+
+ identifier.NotNullOrWhiteSpace(nameof(identifier));
+ message.NotNullOrWhiteSpace(nameof(message));
+ providerType.NotNullOrWhiteSpace(nameof(providerType));
+ providerName.NotNullOrWhiteSpace(nameof(providerName));
+
+ #endregion
+
+ return new IssueBuilder(identifier, message, providerType, providerName);
}
///
@@ -179,8 +248,73 @@ public IssueBuilder InFile(string filePath, int? line)
{
line?.NotNegativeOrZero(nameof(line));
+ this.InFile(filePath, line, null);
+
+ return this;
+ }
+
+ ///
+ /// Sets the path to the file affected by the issue and the line and column in the file where the issues has occurred.
+ ///
+ /// The path to the file affacted by the issue.
+ /// The path needs to be relative to the repository root.
+ /// null or if issue is not related to a change in a file.
+ /// The line in the file where the issues has occurred.
+ /// null if the issue affects the whole file or an asssembly.
+ /// The column in the file where the issues has occurred.
+ /// null if the issue affects the whole file or an asssembly.
+ /// Issue Builder instance.
+ public IssueBuilder InFile(string filePath, int? line, int? column)
+ {
+ line?.NotNegativeOrZero(nameof(line));
+ column?.NotNegativeOrZero(nameof(column));
+
+ this.InFile(filePath, line, null, column, null);
+
+ return this;
+ }
+
+ ///
+ /// Sets the path to the file affected by the issue and the line and column in the file where the issues has occurred.
+ ///
+ /// The path to the file affacted by the issue.
+ /// The path needs to be relative to the repository root.
+ /// null or if issue is not related to a change in a file.
+ /// The line in the file where the issues has occurred.
+ /// null if the issue affects the whole file or an asssembly.
+ /// The end of the line range in the file where the issues has occurred.
+ /// null if the issue affects the whole file, an asssembly or only a single line.
+ /// The column in the file where the issues has occurred.
+ /// null if the issue affects the whole file or an asssembly.
+ /// The end of the column range in the file where the issues has occurred.
+ /// null if the issue affects the whole file, an asssembly or only a single column.
+ /// Issue Builder instance.
+ public IssueBuilder InFile(string filePath, int? startLine, int? endLine, int? startColumn, int? endColumn)
+ {
+ startLine?.NotNegativeOrZero(nameof(startLine));
+ endLine?.NotNegativeOrZero(nameof(endLine));
+ startColumn?.NotNegativeOrZero(nameof(startColumn));
+ endColumn?.NotNegativeOrZero(nameof(endColumn));
+
this.filePath = filePath;
- this.line = line;
+ this.line = startLine;
+ this.endLine = endLine;
+ this.column = startColumn;
+ this.endColumn = endColumn;
+
+ return this;
+ }
+
+ ///
+ /// Sets the the link to the position in the file where the issue ocurred.
+ ///
+ /// Link to the position in the file where the issue ocurred.
+ /// Issue Builder instance.
+ public IssueBuilder WithFileLink(Uri fileLink)
+ {
+ fileLink.NotNull(nameof(fileLink));
+
+ this.fileLink = fileLink;
return this;
}
@@ -240,6 +374,20 @@ public IssueBuilder OfRule(string name, Uri uri)
return this;
}
+ ///
+ /// Sets the name of the run where the issue was reported.
+ ///
+ /// The name of the run where the issue was reported.
+ /// Issue Builder instance.
+ public IssueBuilder ForRun(string run)
+ {
+ run.NotNullOrWhiteSpace(nameof(run));
+
+ this.run = run;
+
+ return this;
+ }
+
///
/// Creates a new .
///
@@ -248,10 +396,15 @@ public IIssue Create()
{
return
new Issue(
+ this.identifier,
this.projectFileRelativePath,
this.projectName,
this.filePath,
this.line,
+ this.endLine,
+ this.column,
+ this.endColumn,
+ this.fileLink,
this.messageText,
this.messageHtml,
this.messageMarkdown,
@@ -259,6 +412,7 @@ public IIssue Create()
this.priorityName,
this.rule,
this.ruleUrl,
+ this.run,
this.providerType,
this.providerName);
}
diff --git a/src/Cake.Issues/IssuesAliasConstants.cs b/src/Cake.Issues/IssuesAliasConstants.cs
index 4ecf0d797..032efca2d 100644
--- a/src/Cake.Issues/IssuesAliasConstants.cs
+++ b/src/Cake.Issues/IssuesAliasConstants.cs
@@ -25,6 +25,11 @@ public static class IssuesAliasConstants
///
public const string SerializationCakeAliasCategory = "Issue Serialization";
+ ///
+ /// Category to use for all Cake aliases providing functionality for linking to files.
+ ///
+ public const string FileLinkingCakeAliasCategory = "File Linking";
+
///
/// Category to use for all Cake aliases creating issue providers.
///
diff --git a/src/Cake.Issues/IssuesReader.cs b/src/Cake.Issues/IssuesReader.cs
index 7751cbc34..d64e03af9 100644
--- a/src/Cake.Issues/IssuesReader.cs
+++ b/src/Cake.Issues/IssuesReader.cs
@@ -11,7 +11,7 @@ public class IssuesReader
{
private readonly ICakeLog log;
private readonly List issueProviders = new List();
- private readonly RepositorySettings settings;
+ private readonly IReadIssuesSettings settings;
///
/// Initializes a new instance of the class.
@@ -22,7 +22,7 @@ public class IssuesReader
public IssuesReader(
ICakeLog log,
IEnumerable issueProviders,
- RepositorySettings settings)
+ IReadIssuesSettings settings)
{
log.NotNull(nameof(log));
settings.NotNull(nameof(settings));
@@ -59,6 +59,16 @@ public IEnumerable ReadIssues()
currentIssues.Count,
providerName);
+ currentIssues.ForEach(x =>
+ {
+ x.Run = this.settings.Run;
+
+ if (this.settings.FileLinkSettings != null)
+ {
+ x.FileLink = this.settings.FileLinkSettings.GetFileLink(x);
+ }
+ });
+
issues.AddRange(currentIssues);
}
else
diff --git a/src/Cake.Issues/ReadIssuesSettings.cs b/src/Cake.Issues/ReadIssuesSettings.cs
index d3c52dcec..1a4c4e6b9 100644
--- a/src/Cake.Issues/ReadIssuesSettings.cs
+++ b/src/Cake.Issues/ReadIssuesSettings.cs
@@ -5,7 +5,7 @@
///
/// Settings for reading issues.
///
- public class ReadIssuesSettings : RepositorySettings
+ public class ReadIssuesSettings : RepositorySettings, IReadIssuesSettings
{
///
/// Initializes a new instance of the class.
@@ -15,5 +15,11 @@ public ReadIssuesSettings(DirectoryPath repositoryRoot)
: base(repositoryRoot)
{
}
+
+ ///
+ public string Run { get; set; }
+
+ ///
+ public FileLinkSettings FileLinkSettings { get; set; }
}
}
diff --git a/src/Cake.Issues/RepositorySettings.cs b/src/Cake.Issues/RepositorySettings.cs
index 24f7e9bb2..e045200fb 100644
--- a/src/Cake.Issues/RepositorySettings.cs
+++ b/src/Cake.Issues/RepositorySettings.cs
@@ -5,7 +5,7 @@
///
/// Settings containing a path to a repository.
///
- public class RepositorySettings
+ public class RepositorySettings : IRepositorySettings
{
///
/// Initializes a new instance of the class.
@@ -18,9 +18,7 @@ public RepositorySettings(DirectoryPath repositoryRoot)
this.RepositoryRoot = repositoryRoot;
}
- ///
- /// Gets the Root path of the repository.
- ///
+ ///
public DirectoryPath RepositoryRoot { get; }
}
}
diff --git a/src/Cake.Issues/Serialization/IssueDeserializationExtensions.cs b/src/Cake.Issues/Serialization/IssueDeserializationExtensions.cs
index 1179b260c..ced6f66cd 100644
--- a/src/Cake.Issues/Serialization/IssueDeserializationExtensions.cs
+++ b/src/Cake.Issues/Serialization/IssueDeserializationExtensions.cs
@@ -123,13 +123,12 @@ private static Issue DeserializeJsonDataToIssue(JsonData data)
if (data.ContainsKey("Version"))
{
var version = (int)data["Version"];
- switch (version)
+ return version switch
{
- case 2:
- return JsonMapper.ToObject(data.ToJson()).ToIssue();
- default:
- throw new Exception($"Not supported issue serialization format {version}");
- }
+ 2 => JsonMapper.ToObject(data.ToJson()).ToIssue(),
+ 3 => JsonMapper.ToObject(data.ToJson()).ToIssue(),
+ _ => throw new Exception($"Not supported issue serialization format {version}"),
+ };
}
else
{
diff --git a/src/Cake.Issues/Serialization/IssueSerializationExtensions.cs b/src/Cake.Issues/Serialization/IssueSerializationExtensions.cs
index b66a33a31..01901bdd0 100644
--- a/src/Cake.Issues/Serialization/IssueSerializationExtensions.cs
+++ b/src/Cake.Issues/Serialization/IssueSerializationExtensions.cs
@@ -70,20 +70,25 @@ public static void SerializeToJsonFile(this IEnumerable issues, FilePath
}
///
- /// Converts an to a .
+ /// Converts an to a .
///
/// Issue which should be converted.
/// Converted issue.
- internal static SerializableIssueV2 ToSerializableIssue(this IIssue issue)
+ internal static SerializableIssueV3 ToSerializableIssue(this IIssue issue)
{
issue.NotNull(nameof(issue));
- return new SerializableIssueV2
+ return new SerializableIssueV3
{
+ Identifier = issue.Identifier,
ProjectFileRelativePath = issue.ProjectFileRelativePath?.FullPath,
ProjectName = issue.ProjectName,
AffectedFileRelativePath = issue.AffectedFileRelativePath?.FullPath,
Line = issue.Line,
+ EndLine = issue.EndLine,
+ Column = issue.Column,
+ EndColumn = issue.EndColumn,
+ FileLink = issue.FileLink?.ToString(),
MessageText = issue.MessageText,
MessageMarkdown = issue.MessageMarkdown,
MessageHtml = issue.MessageHtml,
@@ -91,6 +96,7 @@ internal static SerializableIssueV2 ToSerializableIssue(this IIssue issue)
PriorityName = issue.PriorityName,
Rule = issue.Rule,
RuleUrl = issue.RuleUrl?.ToString(),
+ Run = issue.Run,
ProviderType = issue.ProviderType,
ProviderName = issue.ProviderName,
};
diff --git a/src/Cake.Issues/Serialization/SerializableIssueExtensions.cs b/src/Cake.Issues/Serialization/SerializableIssueExtensions.cs
index 9b722e83c..24b479dd9 100644
--- a/src/Cake.Issues/Serialization/SerializableIssueExtensions.cs
+++ b/src/Cake.Issues/Serialization/SerializableIssueExtensions.cs
@@ -27,10 +27,15 @@ internal static Issue ToIssue(this SerializableIssue serializableIssue)
}
return new Issue(
+ serializableIssue.Message,
serializableIssue.ProjectFileRelativePath,
serializableIssue.ProjectName,
serializableIssue.AffectedFileRelativePath,
serializableIssue.Line,
+ null,
+ null,
+ null,
+ null,
serializableIssue.Message,
null,
null,
@@ -38,6 +43,7 @@ internal static Issue ToIssue(this SerializableIssue serializableIssue)
serializableIssue.PriorityName,
serializableIssue.Rule,
ruleUrl,
+ null,
serializableIssue.ProviderType,
serializableIssue.ProviderName);
diff --git a/src/Cake.Issues/Serialization/SerializableIssueV2Extensions.cs b/src/Cake.Issues/Serialization/SerializableIssueV2Extensions.cs
index 4ab0491f8..3c661919b 100644
--- a/src/Cake.Issues/Serialization/SerializableIssueV2Extensions.cs
+++ b/src/Cake.Issues/Serialization/SerializableIssueV2Extensions.cs
@@ -27,10 +27,15 @@ internal static Issue ToIssue(this SerializableIssueV2 serializableIssue)
}
return new Issue(
+ serializableIssue.MessageText,
serializableIssue.ProjectFileRelativePath,
serializableIssue.ProjectName,
serializableIssue.AffectedFileRelativePath,
serializableIssue.Line,
+ null,
+ null,
+ null,
+ null,
serializableIssue.MessageText,
serializableIssue.MessageHtml,
serializableIssue.MessageMarkdown,
@@ -38,6 +43,7 @@ internal static Issue ToIssue(this SerializableIssueV2 serializableIssue)
serializableIssue.PriorityName,
serializableIssue.Rule,
ruleUrl,
+ null,
serializableIssue.ProviderType,
serializableIssue.ProviderName);
diff --git a/src/Cake.Issues/Serialization/SerializableIssueV3.cs b/src/Cake.Issues/Serialization/SerializableIssueV3.cs
new file mode 100644
index 000000000..5c9ac648a
--- /dev/null
+++ b/src/Cake.Issues/Serialization/SerializableIssueV3.cs
@@ -0,0 +1,99 @@
+namespace Cake.Issues.Serialization
+{
+ using System.Runtime.Serialization;
+
+ ///
+ /// Class for serializing and deserializing an instance.
+ ///
+ [DataContract]
+ internal class SerializableIssueV3
+ {
+ ///
+ /// Gets the version of the serialization format.
+ ///
+ [DataMember]
+ public int Version
+ {
+ get
+ {
+ return 3;
+ }
+ }
+
+ ///
+ [DataMember]
+ public string Identifier { get; set; }
+
+ ///
+ [DataMember]
+ public string ProjectFileRelativePath { get; set; }
+
+ ///
+ [DataMember]
+ public string ProjectName { get; set; }
+
+ ///
+ [DataMember]
+ public string AffectedFileRelativePath { get; set; }
+
+ ///
+ [DataMember]
+ public int? Line { get; set; }
+
+ ///
+ [DataMember]
+ public int? EndLine { get; set; }
+
+ ///
+ [DataMember]
+ public int? Column { get; set; }
+
+ ///
+ [DataMember]
+ public int? EndColumn { get; set; }
+
+ ///
+ [DataMember]
+ public string FileLink { get; set; }
+
+ ///
+ [DataMember]
+ public string MessageText { get; set; }
+
+ ///
+ [DataMember]
+ public string MessageMarkdown { get; set; }
+
+ ///
+ [DataMember]
+ public string MessageHtml { get; set; }
+
+ ///
+ [DataMember]
+ public int? Priority { get; set; }
+
+ ///
+ [DataMember]
+ public string PriorityName { get; set; }
+
+ ///
+ [DataMember]
+ public string Rule { get; set; }
+
+ ///
+ [DataMember]
+ public string RuleUrl { get; set; }
+
+ ///
+ [DataMember]
+ public string ProviderType { get; set; }
+
+ ///
+ [DataMember]
+ public string ProviderName { get; set; }
+
+ ///
+ [DataMember]
+ public string Run { get; set; }
+ }
+}
diff --git a/src/Cake.Issues/Serialization/SerializableIssueV3Extensions.cs b/src/Cake.Issues/Serialization/SerializableIssueV3Extensions.cs
new file mode 100644
index 000000000..e0ea7c239
--- /dev/null
+++ b/src/Cake.Issues/Serialization/SerializableIssueV3Extensions.cs
@@ -0,0 +1,59 @@
+namespace Cake.Issues.Serialization
+{
+ using System;
+
+ ///
+ /// Extensions for .
+ ///
+ internal static class SerializableIssueV3Extensions
+ {
+ ///
+ /// Converts a to an .
+ ///
+ /// Issue which should be converted.
+ /// Converted issue.
+ internal static Issue ToIssue(this SerializableIssueV3 serializableIssue)
+ {
+#pragma warning disable SA1123 // Do not place regions within elements
+ #region DupFinder Exclusion
+#pragma warning restore SA1123 // Do not place regions within elements
+
+ serializableIssue.NotNull(nameof(serializableIssue));
+
+ Uri ruleUrl = null;
+ if (!string.IsNullOrWhiteSpace(serializableIssue.RuleUrl))
+ {
+ ruleUrl = new Uri(serializableIssue.RuleUrl);
+ }
+
+ Uri fileLink = null;
+ if (!string.IsNullOrWhiteSpace(serializableIssue.FileLink))
+ {
+ fileLink = new Uri(serializableIssue.FileLink);
+ }
+
+ return new Issue(
+ serializableIssue.Identifier,
+ serializableIssue.ProjectFileRelativePath,
+ serializableIssue.ProjectName,
+ serializableIssue.AffectedFileRelativePath,
+ serializableIssue.Line,
+ serializableIssue.EndLine,
+ serializableIssue.Column,
+ serializableIssue.EndColumn,
+ fileLink,
+ serializableIssue.MessageText,
+ serializableIssue.MessageHtml,
+ serializableIssue.MessageMarkdown,
+ serializableIssue.Priority,
+ serializableIssue.PriorityName,
+ serializableIssue.Rule,
+ ruleUrl,
+ serializableIssue.Run,
+ serializableIssue.ProviderType,
+ serializableIssue.ProviderName);
+
+ #endregion
+ }
+ }
+}
diff --git a/src/Cake.Issues/StringPathExtensions.cs b/src/Cake.Issues/StringPathExtensions.cs
index fbb7990f0..07ea8ff20 100644
--- a/src/Cake.Issues/StringPathExtensions.cs
+++ b/src/Cake.Issues/StringPathExtensions.cs
@@ -103,7 +103,7 @@ public static string NormalizePath(this string path)
/// String to which should be added.
/// String which should be added to .
/// with the minimal concatenation of .
- internal static string WithEnding(this string value, string ending)
+ public static string WithEnding(this string value, string ending)
{
if (value == null)
{
diff --git a/src/Cake.Issues/UriExtensions.cs b/src/Cake.Issues/UriExtensions.cs
new file mode 100644
index 000000000..2d6287cea
--- /dev/null
+++ b/src/Cake.Issues/UriExtensions.cs
@@ -0,0 +1,36 @@
+namespace Cake.Issues
+{
+ using System;
+ using System.Globalization;
+ using System.Linq;
+
+ ///
+ /// Extensions for the class.
+ ///
+ internal static class UriExtensions
+ {
+ ///
+ /// Appends paths to an URI.
+ ///
+ /// URI to which the paths should be appended.
+ /// Paths to append.
+ /// URI with appended paths.
+ public static Uri Append(this Uri uri, params string[] paths)
+ {
+ uri.NotNull(nameof(uri));
+
+ return
+ new Uri(
+ paths
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .Aggregate(
+ uri.AbsoluteUri,
+ (current, path) =>
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "{0}/{1}",
+ current.TrimEnd('/'),
+ path.TrimStart('/'))));
+ }
+ }
+}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 000000000..a95ac958c
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,5 @@
+
+
+ latest
+
+
\ No newline at end of file