public void CanSubmitToYouTrack() { var tempfile1 = Path.GetTempFileName(); string tempfile2 = null; try { var submitter = new YouTrackIssueSubmitter("AUT"); // Create a file to be attached to the issue as it it created. File.WriteAllLines(tempfile1, new[] { @"This is a test. This is only a test." }); var filename1 = Path.GetFileName(tempfile1); var info1 = new FileInfo(tempfile1); submitter.AddAttachmentWhenWeHaveAnIssue(tempfile1); var issueId = submitter.SubmitToYouTrack("Test submission to YouTrack", kLongDescription); Assert.That(issueId, Does.StartWith("AUT-")); var initialFiles = submitter.GetAttachmentDataForIssue(issueId); Assert.That(initialFiles, Is.Not.Null, "attachment data successfully fetched after creation"); Assert.That(initialFiles.Count, Is.EqualTo(1), "unit test issue starts up with one file attached"); Assert.That(initialFiles.ContainsKey(filename1), Is.True, "Initial file is attached"); Assert.That(initialFiles[filename1], Is.EqualTo(info1.Length), "first attached file has right size to begin"); // Create file named after the issue and attach it to the issue. var filename2 = issueId + ".tmp"; tempfile2 = Path.Combine(Path.GetTempPath(), filename2); File.WriteAllLines(tempfile2, new[] { @"This is the second test file, named after the issue.", issueId }); var info2 = new FileInfo(tempfile2); var added = submitter.AttachFileToExistingIssue(issueId, tempfile2); Assert.That(added, Is.True, "file added to issue"); var finalFiles = submitter.GetAttachmentDataForIssue(issueId); Assert.That(finalFiles, Is.Not.Null, "attachment data successfully fetched at the end"); Assert.That(finalFiles.Count, Is.EqualTo(2), "unit test issue ends up with two files attached"); Assert.That(finalFiles.ContainsKey(filename1), Is.True, "Initial file is still attached"); Assert.That(finalFiles[filename1], Is.EqualTo(info1.Length), "first attached file has right size at end"); Assert.That(finalFiles.ContainsKey(filename2), Is.True, "Second file was attached"); Assert.That(finalFiles[filename2], Is.EqualTo(info2.Length), "second attached file has right size at end"); // no need to keep adding test issues indefinitely: clean up after ourselves by deleting the new issue. var deleted = submitter.DeleteIssue(issueId); Assert.That(deleted, Is.True, "unit test issue deleted"); } finally { // clean up the disk after ourselves. File.Delete(tempfile1); if (tempfile2 != null) { File.Delete(tempfile2); } } }
public void CanSubmitToYouTrackASecondTime() { // This test is much simpler: we just want to verify that the static HttpClient works for the // second submission. var submitter = new YouTrackIssueSubmitter("AUT"); var issueId = submitter.SubmitToYouTrack("Another test submission to YouTrack", kLongDescription); Assert.That(issueId, Does.StartWith("AUT-")); var initialFiles = submitter.GetAttachmentDataForIssue(issueId); Assert.That(initialFiles, Is.Not.Null, "attachment data successfully fetched after creation"); Assert.That(initialFiles.Count, Is.EqualTo(0), "unit test issue starts up with one file attached"); // no need to keep adding test issues indefinitely: clean up after ourselves by deleting the new issue. var deleted = submitter.DeleteIssue(issueId); Assert.That(deleted, Is.True, "unit test issue deleted"); }
public void RegisterWithApiHandler(BloomApiHandler apiHandler) { // ProblemDialog.tsx uses this endpoint to get the screenshot image. apiHandler.RegisterEndpointHandler("problemReport/screenshot", (ApiRequest request) => { if (_screenshotTempFile == null) { request.Failed(); } else { request.ReplyWithImage(_screenshotTempFile.Path); } }, true); // ProblemDialog.tsx uses this endpoint to get the name of the book. apiHandler.RegisterEndpointHandler("problemReport/bookName", (ApiRequest request) => { var bestBookName = _bookSelection.CurrentSelection?.TitleBestForUserDisplay; request.ReplyWithText(bestBookName ?? "??"); }, true); // ProblemDialog.tsx uses this endpoint to get the registered user's email address. apiHandler.RegisterEndpointHandler("problemReport/emailAddress", (ApiRequest request) => { request.ReplyWithText(SIL.Windows.Forms.Registration.Registration.Default.Email); }, true); // PrivacyScreen.tsx uses this endpoint to show the user what info will be included in the report. apiHandler.RegisterEndpointHandler("problemReport/diagnosticInfo", (ApiRequest request) => { var userWantsToIncludeBook = request.RequiredParam("includeBook") == "true"; var userInput = request.RequiredParam("userInput"); var userEmail = request.RequiredParam("email"); request.ReplyWithText(GetDiagnosticInfo(userWantsToIncludeBook, userInput, userEmail)); }, true); // ProblemDialog.tsx uses this endpoint in its AttemptSubmit method; // it expects a response that it will use to show the issue link to the user. apiHandler.RegisterEndpointHandler("problemReport/submit", (ApiRequest request) => { var report = DynamicJson.Parse(request.RequiredPostJson()); var subject = report.kind == "User" ? "User Problem" : report.kind == "Fatal" ? "Crash Report" : "Error Report"; var issueSubmission = new YouTrackIssueSubmitter(YouTrackProjectKey); var userDesc = report.userInput as string; var userEmail = report.email as string; if (report.includeScreenshot && _screenshotTempFile != null && RobustFile.Exists(_screenshotTempFile.Path)) { issueSubmission.AddAttachmentWhenWeHaveAnIssue(_screenshotTempFile.Path); } var diagnosticInfo = GetDiagnosticInfo(report.includeBook, userDesc, userEmail); if (!string.IsNullOrWhiteSpace(userEmail)) { // remember their email SIL.Windows.Forms.Registration.Registration.Default.Email = userEmail; } const string failureResult = "failed"; string issueId; try { issueId = issueSubmission.SubmitToYouTrack(subject, diagnosticInfo); } catch (Exception e) { Debug.Fail("Submitting problem report to YouTrack failed with '" + e.Message + "'."); issueId = failureResult; } object linkToNewIssue; if (issueId == failureResult) { var zipPath = MakeEmailableReportFile(report.includeBook, report.includeScreenshot, userDesc, diagnosticInfo); linkToNewIssue = new { issueLink = failureResult + ":" + zipPath }; } else { linkToNewIssue = new { issueLink = "https://issues.bloomlibrary.org/youtrack/issue/" + issueId }; if (report.includeBook) { try { string zipPath = CreateBookZipFile(issueId, userDesc); if (zipPath != null) { issueSubmission.AttachFileToExistingIssue(issueId, zipPath); } } catch (Exception error) { Debug.WriteLine($"Attaching book to new YouTrack issue failed with '{error.Message}'."); var msg = "***Error as ProblemReportApi attempted to upload the zipped book: " + error.Message; userDesc += Environment.NewLine + msg; Logger.WriteEvent(userDesc); _bookZipFileTemp.Detach(); } } } request.ReplyWithJson(linkToNewIssue); }, true); }
internal string SubmitToYouTrack(string reportKind, string userDesc, string userEmail, bool includeBook, bool includeScreenshot, IEnumerable <string> additionalPathsToInclude) { var subject = reportKind == "User" ? "User Problem" : reportKind == "Fatal" ? "Crash Report" : "Error Report"; var issueSubmission = new YouTrackIssueSubmitter(YouTrackProjectKey); if (includeScreenshot && _reportInfo?.ScreenshotTempFile != null && RobustFile.Exists(_reportInfo.ScreenshotTempFile.Path)) { issueSubmission.AddAttachmentWhenWeHaveAnIssue(_reportInfo.ScreenshotTempFile.Path); } if (additionalPathsToInclude != null) { foreach (var path in additionalPathsToInclude) { issueSubmission.AddAttachmentWhenWeHaveAnIssue(path); } } string diagnosticInfo = GetDiagnosticInfo(includeBook, userDesc, userEmail); if (!string.IsNullOrWhiteSpace(userEmail)) { // remember their email SIL.Windows.Forms.Registration.Registration.Default.Email = userEmail; } string issueId; try { issueId = issueSubmission.SubmitToYouTrack(subject, diagnosticInfo); } catch (Exception e) { Debug.Fail("Submitting problem report to YouTrack failed with '" + e.Message + "'."); issueId = kFailureResult; } string issueLink; if (issueId == kFailureResult) { var zipPath = MakeEmailableReportFile(includeBook, includeScreenshot, userDesc, diagnosticInfo); issueLink = kFailureResult + ":" + zipPath; } else { issueLink = "https://issues.bloomlibrary.org/youtrack/issue/" + issueId; if (includeBook || _additionalPathsToInclude?.Any() == true) { try { string zipPath = CreateReportZipFile(issueId, userDesc, includeBook); if (zipPath != null) { // This could be used provided the file is not too large (about 10M as of July 2020), // but it seems simpler to do the same thing every time. //issueSubmission.AttachFileToExistingIssue(issueId, zipPath); var uploadUrl = ProblemBookUploader.UploadBook( BloomS3Client.ProblemBookUploadsBucketName, zipPath, new NullProgress()); diagnosticInfo += Environment.NewLine + "Problem book uploaded to " + uploadUrl; // We don't want to change the summary, but currently the YouTrack API requires us to set both together. issueSubmission.UpdateSummaryAndDescription(issueId, subject, diagnosticInfo); } } catch (Exception error) { Debug.WriteLine($"Attaching book to new YouTrack issue failed with '{error.Message}'."); var msg = "***Error as ProblemReportApi attempted to upload the zipped book: " + error.Message; userDesc += Environment.NewLine + msg; Logger.WriteEvent(userDesc); diagnosticInfo += Environment.NewLine + "Uploading the problem book failed with exception " + error.Message; // We don't want to change the summary, but currently the YouTrack API requires us to set both together. issueSubmission.UpdateSummaryAndDescription(issueId, subject, diagnosticInfo); } finally { _reportZipFileTemp.Detach(); } } } return(issueLink); }