public void Add_Tags_Correctly() { var tagMethod = new TagMethod(); var dbg = new DebugEngineProxyBuilder(); tagMethod.TimeTravelFacade = new TimeTravelFacadeBuilder(dbg) .WithPositions(new PositionsResult(new[] { new PositionsRecord(1, new Position(0, 0), true), new PositionsRecord(2, new Position(0, 0), false) })).Build(); var serverClientBuilder = new ServerClientBuilder(); tagMethod.ServerClient = serverClientBuilder .WithAddTag(new Position(0, 0), new[] { 1 }, "This is a note") .WithAddTag(new Position(0, 0), new[] { 1, 2 }, "This is a note") .Build(); tagMethod.Settings = new Settings { ProjectName = "test" }; var options = new AddTagOptions { Text = "This is a note", IsAllThreadsAtPosition = false }; var options2 = new AddTagOptions { Text = "This is a note", IsAllThreadsAtPosition = true }; tagMethod.AddTag(options); tagMethod.AddTag(options2); serverClientBuilder.Mock.Verify(client => client.AddTag(new Position(0, 0), new[] { 1 }, "This is a note"), Times.Once); serverClientBuilder.Mock.Verify( client => client.AddTag(new Position(0, 0), new[] { 1, 2 }, "This is a note"), Times.Once); }
/// <summary> /// Prints as PDF asynchronously. /// </summary> /// <param name="input">The input.</param> /// <param name="options">The options.</param> /// <param name="variables">The variables.</param> /// <param name="createLinksForHeadings">if set to <c>true</c> creates links for headings.</param> /// <returns> /// A task with the PDF file path as a result. /// </returns> /// <exception cref="System.IO.FileNotFoundException">File not found: {fullPath}.</exception> internal async Task <string> PrintAsPdfAsync( string input, HtmlToPdfOptions options, Dictionary <string, string> variables, bool createLinksForHeadings = true) { string fullPath = Path.GetFullPath(input); if (!File.Exists(fullPath)) { throw new FileNotFoundException($"File not found: {fullPath}", fullPath); } string tempPdfFilePath = TempPdfFile.Create(); NavigationOptions navigationOptions = new NavigationOptions { WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }, Timeout = 0, }; AddTagOptions addTagOptions = null; if (!string.IsNullOrEmpty(options.StyleSheet)) { if (File.Exists(options.StyleSheet)) { addTagOptions = new AddTagOptions { Type = "text/css", Path = options.StyleSheet, }; } else { this.logger.LogWarning($"File not found: {options.StyleSheet}"); } } // the paper format takes priority over width and height // if a page width or height is set, unset the paper format PaperFormat paperFormat = options.PaperFormat; string width = options.Width; string height = options.Height; if ((!string.IsNullOrEmpty(width)) || (!string.IsNullOrEmpty(height))) { paperFormat = null; } using (TempCopyHtmlFile tempHtmlFile = new TempCopyHtmlFile(fullPath)) { this.PrependEmptyPages(tempHtmlFile.FilePath, options.PageOffset + options.PageNumberOffset); // TODO: do not create links for headings if not generating an outline if (createLinksForHeadings) { this.CreateLinksForHeadings(tempHtmlFile.FilePath); } string pageRanges = string.Empty; if ((options.PageOffset + options.PageNumberOffset) > 0) { int fromPage = options.PageOffset + options.PageNumberOffset + 1; int toPage = options.PageOffset + options.PageNumberOffset + options.NumberOfPages; pageRanges = $"{fromPage}-"; if (options.NumberOfPages != 0) { pageRanges += $"{toPage}"; } this.logger.LogDebug($"Printing pages {pageRanges} of page '{fullPath}'."); } // page variables Dictionary <string, string> pageVariables = new Dictionary <string, string>(); if (variables != null) { foreach (KeyValuePair <string, string> keyValuePair in variables) { pageVariables.Add(keyValuePair.Key, keyValuePair.Value); } } pageVariables.Add("webpage", fullPath); string footerTemplate = string.Empty; bool displayFooter = options.FooterTemplateBuilder.DisplayTemplate; if (displayFooter) { footerTemplate = options.FooterTemplateBuilder.Build(pageVariables); } string headerTemplate = string.Empty; bool displayHeader = options.HeaderTemplateBuilder.DisplayTemplate; if (displayHeader) { headerTemplate = options.HeaderTemplateBuilder.Build(pageVariables); } PdfOptions pdfOptions = new PdfOptions { DisplayHeaderFooter = displayHeader || displayFooter, FooterTemplate = footerTemplate, Format = paperFormat, HeaderTemplate = headerTemplate, Height = height, Landscape = options.Landscape, MarginOptions = options.MarginOptions, PreferCSSPageSize = false, PageRanges = pageRanges, PrintBackground = options.PrintBackground, Scale = 1, Width = width, }; PolicyResult policyResult = await Policy .Handle <TargetClosedException>() .Or <Exception>() .RetryAsync(2, onRetry: (ex, retryCount, context) => { // executed before each retry // ex. PuppeteerSharp.TargetClosedException: Protocol error(IO.read): Target closed. (Page failed to process Inspector.targetCrashed. Exception of type 'PuppeteerSharp.TargetCrashedException' was thrown.. at PuppeteerSharp.Page.OnTargetCrashed() // at PuppeteerSharp.Page.<Client_MessageReceived>d__230.MoveNext()) // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // at PuppeteerSharp.CDPSession.<SendAsync>d__30.MoveNext() // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // at PuppeteerSharp.CDPSession.<SendAsync>d__29`1.MoveNext() // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at PuppeteerSharp.Helpers.ProtocolStreamReader.<ReadProtocolStreamByteAsync>d__1.MoveNext() // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // at PuppeteerSharp.Page.<PdfInternalAsync>d__171.MoveNext() // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // at PuppeteerSharp.Page.<PdfAsync>d__166.MoveNext() // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // at HtmlToPdf.PdfPrinter.<PrintAsPdfAsync>d__3.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\PdfPrinter.cs:line 167 // --- End of inner exception stack trace --- // at HtmlToPdf.PdfPrinter.<PrintAsPdfAsync>d__3.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\PdfPrinter.cs:line 171 // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // at HtmlToPdf.HtmlToPdfProcessor.<>c__DisplayClass0_1.<<ProcessAsync>b__6>d.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\HtmlToPdfProcessor.cs:line 183 // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at HtmlToPdf.HtmlToPdfProcessor.<ProcessAsync>d__0.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\HtmlToPdfProcessor.cs:line 206 // --- End of stack trace from previous location where exception was thrown --- // Verbose:[PdfCommand.PDF.wkhtmltopdf]got ... HtmlToPdf.Console.exe output 0Bytes // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at HtmlToPdf.HtmlToPdfProcessor.<ProcessAsync>d__0.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf\HtmlToPdfProcessor.cs:line 294 // --- End of stack trace from previous location where exception was thrown --- // at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() // at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // at HtmlToPdf.Console.Program.<RunAsync>d__7.MoveNext() in D:\a\HtmlToPdf\HtmlToPdf\src\HtmlToPdf.Console\Program.cs:line 216 // Error:[PdfCommand.PDF]Error happen when converting articles/toc.json to Pdf. Details: iTextSharp.text.exceptions.InvalidPdfException: PDF header signature not found. // at iTextSharp.text.pdf.PdfReader..ctor(ReaderProperties properties, IRandomAccessSource byteSource) // at Microsoft.DocAsCode.HtmlToPdf.HtmlToPdfConverter.SaveCore(Stream stream) // at Microsoft.DocAsCode.HtmlToPdf.HtmlToPdfConverter.Save(String outputFileName) // at Microsoft.DocAsCode.HtmlToPdf.ConvertWrapper.<>c__DisplayClass7_0.<ConvertCore>b__1(ManifestItem tocFile) this.logger.LogWarning(ex.ToString()); Thread.Sleep(1000); }) .ExecuteAndCaptureAsync(async() => { using (Page page = await this.browser.NewPageAsync()) { // disable navigation timeout // otherwise, the following exception occurs: // PuppeteerSharp.NavigationException: Timeout of 30000 ms exceeded ---> System.TimeoutException: Timeout of 30000 ms exceeded page.DefaultNavigationTimeout = 0; page.DefaultTimeout = 0; await page.GoToAsync(tempHtmlFile.FilePath, navigationOptions); if (addTagOptions != null) { await page.AddStyleTagAsync(addTagOptions); } await page.WaitForTimeoutAsync(options.JavascriptDelayInMilliseconds); try { await page.PdfAsync(tempPdfFilePath, pdfOptions); } finally { await page.CloseAsync(); } } }); if (policyResult.Outcome == OutcomeType.Failure) { if (policyResult.FinalException is TargetClosedException) { throw policyResult.FinalException; } else { throw new PrintToPdfException(fullPath, policyResult.FinalException); } } } return(tempPdfFilePath); }