From 636dad437862512090159c1ee8af0436ed449586 Mon Sep 17 00:00:00 2001 From: RussKie Date: Tue, 9 Apr 2019 20:30:14 +1000 Subject: [PATCH] Submit issue to GitHub GitHub allows submitting issues by navigating a dedicated URL supplying issue data via query string parameters. More info: https://help.github.com/en/articles/about-automation-for-issues-and-pull-requests-with-query-parameters Whenever Git Extensions experiences an issue that is handled by NBug, a user is presented with an option to submit an issue to our GitHub repo. By clicking "Send and quit" button the following occurs: * an issue payload is generated, * the payload gets encoded into a url, and * the user is navigated to the generated url in a browser of their choice Relates to gitextensions/gitextensions#5064 --- .gitignore | 1 + NBug.Tests/NBug.Tests.csproj | 35 ++++-- NBug.Tests/Properties/AssemblyInfo.cs | 4 + NBug.Tests/Unit/BugReportTests.cs | 21 ---- ...th_system_and_additional_info.approved.txt | 26 ++++ ...ystem_without_additional_info.approved.txt | 25 ++++ ...out_system_or_additional_info.approved.txt | 18 +++ .../ErrorReportMarkDownBodyBuilderTests.cs | 88 +++++++++++++ ....Build_should_return_full_url.approved.txt | 1 + ...rim_subject_if_longer_70_char.approved.txt | 1 + ...turn_preserve_url_querystring.approved.txt | 1 + NBug.Tests/Unit/Util/GitHubUrlBuilderTests.cs | 117 ++++++++++++++++++ NBug.Tests/Unit/Util/Mock.cs | 20 +++ NBug.Tests/packages.config | 8 +- NBug/Core/UI/WinForms/Full.Designer.cs | 21 +++- NBug/Core/UI/WinForms/Full.cs | 67 ++++------ .../Util/ErrorReportMarkDownBodyBuilder.cs | 72 +++++++++++ NBug/Core/Util/GitHubUrlBuilder.cs | 51 ++++++++ NBug/NBug.csproj | 2 + 19 files changed, 505 insertions(+), 74 deletions(-) delete mode 100644 NBug.Tests/Unit/BugReportTests.cs create mode 100644 NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_and_additional_info.approved.txt create mode 100644 NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_without_additional_info.approved.txt create mode 100644 NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_without_system_or_additional_info.approved.txt create mode 100644 NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.cs create mode 100644 NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url.approved.txt create mode 100644 NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url_trim_subject_if_longer_70_char.approved.txt create mode 100644 NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_preserve_url_querystring.approved.txt create mode 100644 NBug.Tests/Unit/Util/GitHubUrlBuilderTests.cs create mode 100644 NBug.Tests/Unit/Util/Mock.cs create mode 100644 NBug/Core/Util/ErrorReportMarkDownBodyBuilder.cs create mode 100644 NBug/Core/Util/GitHubUrlBuilder.cs diff --git a/.gitignore b/.gitignore index bef8764..423083e 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,4 @@ UpgradeLog*.XML # NuGet packages/ .vs/ +*.received.* diff --git a/NBug.Tests/NBug.Tests.csproj b/NBug.Tests/NBug.Tests.csproj index 3aa08b1..6a15184 100644 --- a/NBug.Tests/NBug.Tests.csproj +++ b/NBug.Tests/NBug.Tests.csproj @@ -46,17 +46,36 @@ ..\Signing.snk - - ..\packages\Moq.4.0.10827\lib\NET40\Moq.dll - True + + ..\packages\ApprovalTests.3.0.13\lib\net40\ApprovalTests.dll + + + ..\packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.dll + + + ..\packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.Net45.dll + + + ..\packages\Castle.Core.4.2.0\lib\net45\Castle.Core.dll + + + ..\packages\FluentAssertions.5.2.0\lib\net45\FluentAssertions.dll + + + + ..\packages\NSubstitute.3.1.0\lib\net46\NSubstitute.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + + ..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll + - - - ..\packages\xunit.1.9.0.1566\lib\xunit.dll @@ -84,9 +103,11 @@ - + + + diff --git a/NBug.Tests/Properties/AssemblyInfo.cs b/NBug.Tests/Properties/AssemblyInfo.cs index e749b77..ef70fa6 100644 --- a/NBug.Tests/Properties/AssemblyInfo.cs +++ b/NBug.Tests/Properties/AssemblyInfo.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Runtime.InteropServices; +using ApprovalTests.Reporters; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information @@ -24,6 +25,9 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("2063af3c-6402-4000-b41e-b0e14cc10ec0")] +[assembly: UseReporter(typeof(NUnitReporter), typeof(AppVeyorReporter), typeof(DiffReporter))] + + // Version information for an assembly consists of the following four values: // Major Version // Minor Version diff --git a/NBug.Tests/Unit/BugReportTests.cs b/NBug.Tests/Unit/BugReportTests.cs deleted file mode 100644 index 639fc07..0000000 --- a/NBug.Tests/Unit/BugReportTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2011 - 2013 Teoman Soygul. Licensed under MIT license. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace NBug.Tests.Unit -{ - public class BugReportTests - { - // "Setup", "Returns", "Verify", and "Assert.xxx" - - /*[Fact] - public void Test() - { - var report = new Mock(); - report.SetupProperty(x => x.General.UserDescription, "test"); - Assert.True(report.Object.General.UserDescription == "test"); - }*/ - } -} \ No newline at end of file diff --git a/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_and_additional_info.approved.txt b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_and_additional_info.approved.txt new file mode 100644 index 0000000..38091da --- /dev/null +++ b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_and_additional_info.approved.txt @@ -0,0 +1,26 @@ +## Current behaviour + +``` +System.ApplicationException: Failed ---> System.ArgumentOutOfRangeException: Opps ---> System.DivideByZeroException: Boom! + --- End of inner exception stack trace --- + --- End of inner exception stack trace --- + at NBug.Tests.Unit.Util.Mock.Method1() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 13 + at NBug.Tests.Unit.Util.Mock.Method2() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 16 + at NBug.Tests.Unit.Util.Mock.Method3() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 17 + at NBug.Tests.Unit.Util.Mock.Method4() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 18 + at NBug.Tests.Unit.Util.Mock.DoWork() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 7 + at NBug.Tests.Unit.Util.ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_and_additional_info() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\ErrorReportMarkDownBodyBuilderTests.cs:line 77 +``` + + +## Additional information + +It happened when I was arguing with someone on the Internet. +I was right and they were absolutely wrong! +I win! But the app crashed! +PLEASE HELP!!! + + +## Environment + +System information is not supplied diff --git a/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_without_additional_info.approved.txt b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_without_additional_info.approved.txt new file mode 100644 index 0000000..e0f0914 --- /dev/null +++ b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_without_additional_info.approved.txt @@ -0,0 +1,25 @@ +## Current behaviour + +``` +System.ApplicationException: Failed ---> System.ArgumentOutOfRangeException: Opps ---> System.DivideByZeroException: Boom! + --- End of inner exception stack trace --- + --- End of inner exception stack trace --- + at NBug.Tests.Unit.Util.Mock.Method1() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 13 + at NBug.Tests.Unit.Util.Mock.Method2() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 16 + at NBug.Tests.Unit.Util.Mock.Method3() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 17 + at NBug.Tests.Unit.Util.Mock.Method4() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 18 + at NBug.Tests.Unit.Util.Mock.DoWork() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 7 + at NBug.Tests.Unit.Util.ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_with_system_without_additional_info() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\ErrorReportMarkDownBodyBuilderTests.cs:line 61 +``` + + +## Environment + + +- Git Extensions 0.0.2.5232 +- Build 23b6f51905006ccdde8701591df706284b4155dc +- Git 2.19.0.windows.1 +- Microsoft Windows NT 10.0.17134.0 +- .NET Framework 4.7.3324.0 +- DPI 144dpi (150% scaling) + diff --git a/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_without_system_or_additional_info.approved.txt b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_without_system_or_additional_info.approved.txt new file mode 100644 index 0000000..c20755e --- /dev/null +++ b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_without_system_or_additional_info.approved.txt @@ -0,0 +1,18 @@ +## Current behaviour + +``` +System.ApplicationException: Failed ---> System.ArgumentOutOfRangeException: Opps ---> System.DivideByZeroException: Boom! + --- End of inner exception stack trace --- + --- End of inner exception stack trace --- + at NBug.Tests.Unit.Util.Mock.Method1() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 13 + at NBug.Tests.Unit.Util.Mock.Method2() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 16 + at NBug.Tests.Unit.Util.Mock.Method3() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 17 + at NBug.Tests.Unit.Util.Mock.Method4() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 18 + at NBug.Tests.Unit.Util.Mock.DoWork() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 7 + at NBug.Tests.Unit.Util.ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_without_system_or_additional_info() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\ErrorReportMarkDownBodyBuilderTests.cs:line 36 +``` + + +## Environment + +System information is not supplied diff --git a/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.cs b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.cs new file mode 100644 index 0000000..add9dbb --- /dev/null +++ b/NBug.Tests/Unit/Util/ErrorReportMarkDownBodyBuilderTests.cs @@ -0,0 +1,88 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2019 Igor Velikorossov. Licensed under MIT license. +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using ApprovalTests; +using FluentAssertions; +using NBug.Core.Util; +using Xunit; + +namespace NBug.Tests.Unit.Util +{ + public class ErrorReportMarkDownBodyBuilderTests + { + private readonly ErrorReportMarkDownBodyBuilder _errorReportMarkDownBodyBuilder; + + public ErrorReportMarkDownBodyBuilderTests() + { + Settings.GetSystemInfo = null; + _errorReportMarkDownBodyBuilder = new ErrorReportMarkDownBodyBuilder(); + } + + [Fact] + public void Build_should_throw_ArgumentNullException_if_exception_null() + { + ((Action)(() => _errorReportMarkDownBodyBuilder.Build(null, null))).Should().Throw(); + } + + [Fact] + public void Build_should_build_report_without_system_or_additional_info() + { + try + { + Mock.DoWork(); + + Assert.True(false, "Expected an exception to be thrown"); + } + catch (Exception ex) + { + var report = _errorReportMarkDownBodyBuilder.Build(ex, null); + Approvals.Verify(report); + } + } + + [Fact] + public void Build_should_build_report_with_system_without_additional_info() + { + Settings.GetSystemInfo = () => @" +- Git Extensions 0.0.2.5232 +- Build 23b6f51905006ccdde8701591df706284b4155dc +- Git 2.19.0.windows.1 +- Microsoft Windows NT 10.0.17134.0 +- .NET Framework 4.7.3324.0 +- DPI 144dpi (150% scaling) +"; + + try + { + Mock.DoWork(); + + Assert.True(false, "Expected an exception to be thrown"); + } + catch (Exception ex) + { + var report = _errorReportMarkDownBodyBuilder.Build(ex, null); + Approvals.Verify(report); + } + } + + [Fact] + public void Build_should_build_report_with_system_and_additional_info() + { + try + { + Mock.DoWork(); + + Assert.True(false, "Expected an exception to be thrown"); + } + catch (Exception ex) + { + var report = _errorReportMarkDownBodyBuilder.Build(ex, "It happened when I was arguing with someone on the Internet.\r\nI was right and they were absolutely wrong!\r\nI win! But the app crashed!\r\nPLEASE HELP!!!"); + Approvals.Verify(report); + } + } + } +} \ No newline at end of file diff --git a/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url.approved.txt b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url.approved.txt new file mode 100644 index 0000000..8b517c9 --- /dev/null +++ b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url.approved.txt @@ -0,0 +1 @@ +http://localhost/issues/new?title=%5BNBug%5D%20BAU-863%20adding%20settings%20and%20organisations%20if%20they%20are%20not%20a...&body=%23%23%20Current%20behaviour%0D%0A%0D%0A%60%60%60%0D%0ASystem.ApplicationException%3A%20Failed%20---%3E%20System.ArgumentOutOfRangeException%3A%20Opps%20---%3E%20System.DivideByZeroException%3A%20Boom%21%0D%0A%20%20%20---%20End%20of%20inner%20exception%20stack%20trace%20---%0D%0A%20%20%20---%20End%20of%20inner%20exception%20stack%20trace%20---%0D%0A%20%20%20at%20NBug.Tests.Unit.Util.Mock.Method1%28%29%20in%20C%3A%5CDevelopment%5Cgitextensions%5CExternals%5CNBug%5CNBug.Tests%5CUnit%5CUtil%5CMock.cs%3Aline%2013%0D%0A%20%20%20at%20NBug.Tests.Unit.Util.Mock.Method2%28%29%20in%20C%3A%5CDevelopment%5Cgitextensions%5CExternals%5CNBug%5CNBug.Tests%5CUnit%5CUtil%5CMock.cs%3Aline%2016%0D%0A%20%20%20at%20NBug.Tests.Unit.Util.Mock.Method3%28%29%20in%20C%3A%5CDevelopment%5Cgitextensions%5CExternals%5CNBug%5CNBug.Tests%5CUnit%5CUtil%5CMock.cs%3Aline%2017%0D%0A%20%20%20at%20NBug.Tests.Unit.Util.Mock.Method4%28%29%20in%20C%3A%5CDevelopment%5Cgitextensions%5CExternals%5CNBug%5CNBug.Tests%5CUnit%5CUtil%5CMock.cs%3Aline%2018%0D%0A%20%20%20at%20NBug.Tests.Unit.Util.Mock.DoWork%28%29%20in%20C%3A%5CDevelopment%5Cgitextensions%5CExternals%5CNBug%5CNBug.Tests%5CUnit%5CUtil%5CMock.cs%3Aline%207%0D%0A%20%20%20at%20NBug.Tests.Unit.Util.ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_without_system_or_additional_info%28%29%20in%20C%3A%5CDevelopment%5Cgitextensions%5CExternals%5CNBug%5CNBug.Tests%5CUnit%5CUtil%5CErrorReportMarkDownBodyBuilderTests.cs%3Aline%2036%0D%0A%60%60%60%0D%0A%0D%0A%23%23%20Additional%20information%0D%0A%0D%0AIt%20happened%20when%20I%20was%20arguing%20with%20someone%20on%20the%20Internet.%0D%0AI%20was%20right%20and%20they%20were%20absolutely%20wrong%21%0D%0AI%20win%21But%20the%20app%20crashed%21%0D%0APLEASE%20HELP%21%21%21%0D%0A%0D%0A%0D%0A%23%23%20Environment%0D%0A%0D%0A-%20Git%20Extensions%200.0.2.5232%0D%0A-%20Build%2023b6f51905006ccdde8701591df706284b4155dc%0D%0A-%20Git%202.19.0.windows.1%0D%0A-%20Microsoft%20Windows%20NT%2010.0.17134.0%0D%0A-%20.NET%20Framework%204.7.3324.0%0D%0A-%20DPI%20144dpi%20%28150%25%20scaling%29%0D%0A \ No newline at end of file diff --git a/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url_trim_subject_if_longer_70_char.approved.txt b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url_trim_subject_if_longer_70_char.approved.txt new file mode 100644 index 0000000..19a76f1 --- /dev/null +++ b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_full_url_trim_subject_if_longer_70_char.approved.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_preserve_url_querystring.approved.txt b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_preserve_url_querystring.approved.txt new file mode 100644 index 0000000..04dede9 --- /dev/null +++ b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.Build_should_return_preserve_url_querystring.approved.txt @@ -0,0 +1 @@ +http://localhost/issues/new?foo=bar&title=%5BNBug%5D%20BAU-863%20adding%20settings%20and%20organisations%20if%20they%20are%20not%20a...&body=%23%23%20Current%20behaviour \ No newline at end of file diff --git a/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.cs b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.cs new file mode 100644 index 0000000..74c7996 --- /dev/null +++ b/NBug.Tests/Unit/Util/GitHubUrlBuilderTests.cs @@ -0,0 +1,117 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2019 Igor Velikorossov. Licensed under MIT license. +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Linq; +using ApprovalTests; +using FluentAssertions; +using NBug.Core.Util; +using NSubstitute; +using Xunit; +using Xunit.Extensions; + +namespace NBug.Tests.Unit.Util +{ + public class GitHubUrlBuilderTests + { + private readonly IErrorReportMarkDownBodyBuilder _errorReportMarkDownBodyBuilder; + private readonly GitHubUrlBuilder _gitHubUrlBuilder; + + public GitHubUrlBuilderTests() + { + _errorReportMarkDownBodyBuilder = Substitute.For(); + _gitHubUrlBuilder = new GitHubUrlBuilder(_errorReportMarkDownBodyBuilder); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("\t")] + public void Build_should_return_null_if_url_unset(string url) + { + _gitHubUrlBuilder.Build(url, null, null).Should().BeNull(); + } + + [Fact] + public void Build_should_return_null_if_exception_unset() + { + _gitHubUrlBuilder.Build("http://", null, null).Should().BeNull(); + } + + [Theory] + [InlineData("./page/new")] + [InlineData("ftp://api.github.com/issues/new")] + [InlineData("file:////c:/development/file.txt")] + public void Build_should_return_null_if_url_not_absolute_or_http_https(string url) + { + _gitHubUrlBuilder.Build(url, null, null).Should().BeNull(); + } + + [Fact] + public void Build_should_trim_subject_if_longer_70_char() + { + _errorReportMarkDownBodyBuilder.Build(Arg.Any(), Arg.Any()).Returns(x => @"## Current behaviour"); + var ex = new ApplicationException("BAU-863 adding settings and organisations if they are not already exist in the set"); + + var url = _gitHubUrlBuilder.Build("http://localhost/issues/new?foo=bar", ex, null); + + var subject = url.Split('&', '?').First(x => x.StartsWith("title=")).Substring("title=".Length); + subject.Should().Be(Uri.EscapeDataString("[NBug] BAU-863 adding settings and organisations if they are not a...")); + } + + [Fact] + public void Build_should_return_preserve_url_querystring() + { + _errorReportMarkDownBodyBuilder.Build(Arg.Any(), Arg.Any()).Returns(x => @"## Current behaviour"); + var ex = new ApplicationException("BAU-863 adding settings and organisations if they are not already exist in the set"); + + var url = _gitHubUrlBuilder.Build("http://localhost/issues/new?foo=bar", ex, null); + + Approvals.Verify(url); + } + + [Fact] + public void Build_should_return_full_url() + { + _errorReportMarkDownBodyBuilder.Build(Arg.Any(), Arg.Any()).Returns(x => @"## Current behaviour + +``` +System.ApplicationException: Failed ---> System.ArgumentOutOfRangeException: Opps ---> System.DivideByZeroException: Boom! + --- End of inner exception stack trace --- + --- End of inner exception stack trace --- + at NBug.Tests.Unit.Util.Mock.Method1() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 13 + at NBug.Tests.Unit.Util.Mock.Method2() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 16 + at NBug.Tests.Unit.Util.Mock.Method3() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 17 + at NBug.Tests.Unit.Util.Mock.Method4() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 18 + at NBug.Tests.Unit.Util.Mock.DoWork() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\Mock.cs:line 7 + at NBug.Tests.Unit.Util.ErrorReportMarkDownBodyBuilderTests.Build_should_build_report_without_system_or_additional_info() in C:\Development\gitextensions\Externals\NBug\NBug.Tests\Unit\Util\ErrorReportMarkDownBodyBuilderTests.cs:line 36 +``` + +## Additional information + +It happened when I was arguing with someone on the Internet. +I was right and they were absolutely wrong! +I win!But the app crashed! +PLEASE HELP!!! + + +## Environment + +- Git Extensions 0.0.2.5232 +- Build 23b6f51905006ccdde8701591df706284b4155dc +- Git 2.19.0.windows.1 +- Microsoft Windows NT 10.0.17134.0 +- .NET Framework 4.7.3324.0 +- DPI 144dpi (150% scaling) +"); + var ex = new ApplicationException("BAU-863 adding settings and organisations if they are not already exist in the set"); + + var url = _gitHubUrlBuilder.Build("http://localhost/issues/new", ex, null); + + Approvals.Verify(url); + } + } +} \ No newline at end of file diff --git a/NBug.Tests/Unit/Util/Mock.cs b/NBug.Tests/Unit/Util/Mock.cs new file mode 100644 index 0000000..982b811 --- /dev/null +++ b/NBug.Tests/Unit/Util/Mock.cs @@ -0,0 +1,20 @@ +using System; + +namespace NBug.Tests.Unit.Util +{ + internal static class Mock + { + public static void DoWork() => Method4(); + + private static void Method1() + { + var ex = new DivideByZeroException("Boom!"); + var ex1 = new ArgumentOutOfRangeException("Opps", ex); + throw new ApplicationException("Failed", ex1); + } + + private static void Method2() => Method1(); + private static void Method3() => Method2(); + private static void Method4() => Method3(); + } +} \ No newline at end of file diff --git a/NBug.Tests/packages.config b/NBug.Tests/packages.config index ec1acf2..14f68fc 100644 --- a/NBug.Tests/packages.config +++ b/NBug.Tests/packages.config @@ -1,6 +1,12 @@  - + + + + + + + \ No newline at end of file diff --git a/NBug/Core/UI/WinForms/Full.Designer.cs b/NBug/Core/UI/WinForms/Full.Designer.cs index e38e7b5..177e8c9 100644 --- a/NBug/Core/UI/WinForms/Full.Designer.cs +++ b/NBug/Core/UI/WinForms/Full.Designer.cs @@ -34,6 +34,7 @@ private void InitializeComponent() System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Full)); this.mainTabs = new System.Windows.Forms.TabControl(); this.generalTabPage = new System.Windows.Forms.TabPage(); + this.sendAndQuitButton = new System.Windows.Forms.Button(); this.quitButton = new System.Windows.Forms.Button(); this.btnCopy = new System.Windows.Forms.Button(); this.warningLabel = new System.Windows.Forms.Label(); @@ -86,6 +87,7 @@ private void InitializeComponent() // // generalTabPage // + this.generalTabPage.Controls.Add(this.sendAndQuitButton); this.generalTabPage.Controls.Add(this.quitButton); this.generalTabPage.Controls.Add(this.btnCopy); this.generalTabPage.Controls.Add(this.warningLabel); @@ -113,14 +115,26 @@ private void InitializeComponent() this.generalTabPage.Text = "General"; this.generalTabPage.UseVisualStyleBackColor = true; // + // sendAndQuitButton + // + this.sendAndQuitButton.Image = global::NBug.Properties.Resources.Send; + this.sendAndQuitButton.Location = new System.Drawing.Point(252, 322); + this.sendAndQuitButton.Name = "sendAndQuitButton"; + this.sendAndQuitButton.Size = new System.Drawing.Size(118, 24); + this.sendAndQuitButton.TabIndex = 17; + this.sendAndQuitButton.Text = "&Send and Quit"; + this.sendAndQuitButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; + this.sendAndQuitButton.UseVisualStyleBackColor = true; + this.sendAndQuitButton.Click += new System.EventHandler(this.SendAndQuitButton_Click); + // // quitButton // this.quitButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.quitButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.quitButton.Location = new System.Drawing.Point(376, 324); + this.quitButton.Location = new System.Drawing.Point(376, 322); this.quitButton.Name = "quitButton"; - this.quitButton.Size = new System.Drawing.Size(75, 22); - this.quitButton.TabIndex = 17; + this.quitButton.Size = new System.Drawing.Size(75, 24); + this.quitButton.TabIndex = 18; this.quitButton.Text = "&Quit"; this.quitButton.UseVisualStyleBackColor = true; this.quitButton.Click += new System.EventHandler(this.QuitButton_Click); @@ -453,5 +467,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolTip toolTip; private System.Windows.Forms.Label warningLabel; private ExceptionDetails exceptionDetails; + private System.Windows.Forms.Button sendAndQuitButton; } } \ No newline at end of file diff --git a/NBug/Core/UI/WinForms/Full.cs b/NBug/Core/UI/WinForms/Full.cs index ccf2843..23b17f6 100644 --- a/NBug/Core/UI/WinForms/Full.cs +++ b/NBug/Core/UI/WinForms/Full.cs @@ -8,11 +8,12 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Diagnostics; using System.Drawing; -using System.Text; using System.Windows.Forms; using GitExtUtils.GitUI; using NBug.Core.Reporting.Info; +using NBug.Core.Util; using NBug.Core.Util.Serialization; using NBug.Properties; @@ -20,9 +21,17 @@ namespace NBug.Core.UI.WinForms { internal partial class Full : Form { + private static readonly IErrorReportMarkDownBodyBuilder ErrorReportBodyBuilder; + private static readonly GitHubUrlBuilder UrlBuilder; private UIDialogResult _uiDialogResult; private SerializableException _lastException; + static Full() + { + ErrorReportBodyBuilder = new ErrorReportMarkDownBodyBuilder(); + UrlBuilder = new GitHubUrlBuilder(ErrorReportBodyBuilder); + } + internal Full() { InitializeComponent(); @@ -33,6 +42,7 @@ internal Full() reportContentsTabPage.Text = Settings.Resources.UI_Dialog_Full_Report_Contents_Tab; errorDescriptionLabel.Text = Settings.Resources.UI_Dialog_Full_How_to_Reproduce_the_Error_Notification; quitButton.Text = Settings.Resources.UI_Dialog_Full_Quit_Button; + sendAndQuitButton.Text = Settings.Resources.UI_Dialog_Full_Send_and_Quit_Button; // ToDo: Displaying report contents properly requires some more work. mainTabs.TabPages.Remove(mainTabs.TabPages["reportContentsTabPage"]); @@ -45,6 +55,7 @@ internal UIDialogResult ShowDialog(SerializableException exception, Report repor _lastException = exception; // Scaling + sendAndQuitButton.Image = DpiUtil.Scale(Resources.Send); btnCopy.Image = DpiUtil.Scale(Resources.CopyToClipboard); exceptionTypeLabel.Image = DpiUtil.Scale(Resources.NBug_Icon_PNG_16); exceptionDetails.InformationColumnWidth = DpiUtil.Scale(350); @@ -66,7 +77,7 @@ internal UIDialogResult ShowDialog(SerializableException exception, Report repor // ToDo: Fill in the 'Report Contents' tab); ShowDialog(); - // Write back the user description (as we passed 'report' as a reference since it is a refence object anyway) + // Write back the user description (as we passed 'report' as a reference since it is a reference object anyway) report.GeneralInfo.UserDescription = descriptionTextBox.Text; return _uiDialogResult; } @@ -77,52 +88,24 @@ private void QuitButton_Click(object sender, EventArgs e) Close(); } - private void btnCopy_Click(object sender, EventArgs e) + private void SendAndQuitButton_Click(object sender, EventArgs e) { - StringBuilder sb = new StringBuilder(); + string url = UrlBuilder.Build("https://github.com/gitextensions/gitextensions/issues/new", _lastException.OriginalException, descriptionTextBox.Text); + Process.Start(url); - sb.AppendLine("## Current behaviour"); - sb.AppendLine(); - sb.AppendLine("```"); - sb.AppendLine(_lastException.OriginalException.ToString()); - sb.AppendLine("```"); - sb.AppendLine(); - sb.AppendLine(); - - if (!string.IsNullOrWhiteSpace(descriptionTextBox.Text)) - { - sb.AppendLine("## Additional information"); - sb.AppendLine(); - sb.AppendLine(descriptionTextBox.Text.Trim()); - sb.AppendLine(); - sb.AppendLine(); - } + _uiDialogResult = new UIDialogResult(ExecutionFlow.BreakExecution, SendReport.DoNotSend); + Close(); + } - try - { - sb.AppendLine("## Environment"); - sb.AppendLine(); - - var systemInfo = Settings.GetSystemInfo?.Invoke(); - if (!string.IsNullOrWhiteSpace(systemInfo)) - { - sb.AppendLine(systemInfo); - } - else - { - sb.AppendLine("System information is not supplied"); - } - } - catch (Exception ex) + private void btnCopy_Click(object sender, EventArgs e) + { + var report = ErrorReportBodyBuilder.Build(_lastException.OriginalException, descriptionTextBox.Text); + if (string.IsNullOrWhiteSpace(report)) { - sb.AppendLine("Failed to retrieve system information."); - sb.AppendLine("Exception:"); - sb.AppendLine("```"); - sb.AppendLine(ex.ToString()); - sb.AppendLine("```"); + return; } - Clipboard.SetDataObject(sb.ToString(), true, 5, 100); + Clipboard.SetDataObject(report, true, 5, 100); } } } \ No newline at end of file diff --git a/NBug/Core/Util/ErrorReportMarkDownBodyBuilder.cs b/NBug/Core/Util/ErrorReportMarkDownBodyBuilder.cs new file mode 100644 index 0000000..1435dd9 --- /dev/null +++ b/NBug/Core/Util/ErrorReportMarkDownBodyBuilder.cs @@ -0,0 +1,72 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2019 Igor Velikorossov. Licensed under MIT license. +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Text; + +namespace NBug.Core.Util +{ + public interface IErrorReportMarkDownBodyBuilder + { + string Build(Exception exception, string additionalInfo); + } + + public sealed class ErrorReportMarkDownBodyBuilder : IErrorReportMarkDownBodyBuilder + { + public string Build(Exception exception, string additionalInfo) + { + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + + var sb = new StringBuilder(); + + sb.AppendLine("## Current behaviour"); + sb.AppendLine(); + sb.AppendLine("```"); + sb.AppendLine(exception.ToString()); + sb.AppendLine("```"); + sb.AppendLine(); + sb.AppendLine(); + + if (!string.IsNullOrWhiteSpace(additionalInfo)) + { + sb.AppendLine("## Additional information"); + sb.AppendLine(); + sb.AppendLine(additionalInfo.Trim()); + sb.AppendLine(); + sb.AppendLine(); + } + + try + { + sb.AppendLine("## Environment"); + sb.AppendLine(); + + var systemInfo = Settings.GetSystemInfo?.Invoke(); + if (!string.IsNullOrWhiteSpace(systemInfo)) + { + sb.AppendLine(systemInfo); + } + else + { + sb.AppendLine("System information is not supplied"); + } + } + catch (Exception ex) + { + sb.AppendLine("Failed to retrieve system information."); + sb.AppendLine("Exception:"); + sb.AppendLine("```"); + sb.AppendLine(ex.ToString()); + sb.AppendLine("```"); + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/NBug/Core/Util/GitHubUrlBuilder.cs b/NBug/Core/Util/GitHubUrlBuilder.cs new file mode 100644 index 0000000..66dd20b --- /dev/null +++ b/NBug/Core/Util/GitHubUrlBuilder.cs @@ -0,0 +1,51 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2019 Igor Velikorossov. Licensed under MIT license. +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; + +namespace NBug.Core.Util +{ + public sealed class GitHubUrlBuilder + { + private readonly IErrorReportMarkDownBodyBuilder _errorReportMarkDownBodyBuilder; + + public GitHubUrlBuilder(IErrorReportMarkDownBodyBuilder errorReportMarkDownBodyBuilder) + { + _errorReportMarkDownBodyBuilder = errorReportMarkDownBodyBuilder; + } + + /// + /// Generates a URL to create a new issue on GitHub. + /// + /// + public string Build(string url, Exception exception, string additionalInfo) + { + if (string.IsNullOrWhiteSpace(url) || exception == null) + { + return null; + } + + if (!Uri.TryCreate(url, UriKind.Absolute, out Uri validatedUri) || + !(validatedUri.Scheme == Uri.UriSchemeHttp || validatedUri.Scheme == Uri.UriSchemeHttps)) + { + return null; + } + + string separator = !string.IsNullOrWhiteSpace(validatedUri.Query) ? "&" : "?"; + + string subject = $"[NBug] {exception.Message}"; + if (subject.Length > 69) + { + // if the subject is longer than 70 characters, trim it + subject = subject.Substring(0, 66) + "..."; + } + + string body = Uri.EscapeDataString(_errorReportMarkDownBodyBuilder.Build(exception, additionalInfo)); + + return $"{validatedUri}{separator}title={Uri.EscapeDataString(subject)}&body={body}"; + } + } +} \ No newline at end of file diff --git a/NBug/NBug.csproj b/NBug/NBug.csproj index 4161b71..a40424b 100644 --- a/NBug/NBug.csproj +++ b/NBug/NBug.csproj @@ -67,6 +67,8 @@ + +