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 @@
+
+