How to use MetricEventArgs class of PuppeteerSharp package

Best Puppeteer-sharp code snippet using PuppeteerSharp.MetricEventArgs

Page.cs

Source:Page.cs Github

copy

Full Screen

...83        public event EventHandler<ErrorEventArgs> Error;84        /// <summary>85        /// Raised when the JavaScript code makes a call to <c>console.timeStamp</c>. For the list of metrics see <see cref="Page.MetricsAsync"/>.86        /// </summary>87        public event EventHandler<MetricEventArgs> Metrics;88        /// <summary>89        /// Raised when a JavaScript dialog appears, such as <c>alert</c>, <c>prompt</c>, <c>confirm</c> or <c>beforeunload</c>. Puppeteer can respond to the dialog via <see cref="Dialog"/>'s <see cref="Dialog.Accept(string)"/> or <see cref="Dialog.Dismiss"/> methods.90        /// </summary>91        public event EventHandler<DialogEventArgs> Dialog;92        /// <summary>93        /// Raised when JavaScript within the page calls one of console API methods, e.g. <c>console.log</c> or <c>console.dir</c>. Also emitted if the page throws an error or a warning.94        /// The arguments passed into <c>console.log</c> appear as arguments on the event handler.95        /// </summary>96        /// <example>97        /// An example of handling <see cref="Console"/> event:98        /// <code>99        /// <![CDATA[100        /// page.Console += (sender, e) => 101        /// {102        ///     for (var i = 0; i < e.Message.Args.Count; ++i)103        ///     {104        ///         System.Console.WriteLine($"{i}: {e.Message.Args[i]}");105        ///     }106        /// }107        /// ]]>108        /// </code>109        /// </example>110        public event EventHandler<ConsoleEventArgs> Console;111        /// <summary>112        /// Raised when a frame is attached.113        /// </summary>114        public event EventHandler<FrameEventArgs> FrameAttached;115        /// <summary>116        /// Raised when a frame is detached.117        /// </summary>118        public event EventHandler<FrameEventArgs> FrameDetached;119        /// <summary>120        /// Raised when a frame is navigated to a new url.121        /// </summary>122        public event EventHandler<FrameEventArgs> FrameNavigated;123        /// <summary>124        /// Raised when a <see cref="Response"/> is received.125        /// </summary>126        public event EventHandler<ResponseCreatedEventArgs> Response;127        /// <summary>128        /// Raised when a page issues a request. The <see cref="Request"/> object is read-only.129        /// In order to intercept and mutate requests, see <see cref="SetRequestInterceptionAsync(bool)"/>130        /// </summary>131        public event EventHandler<RequestEventArgs> Request;132        /// <summary>133        /// Raised when a request finishes successfully.134        /// </summary>135        public event EventHandler<RequestEventArgs> RequestFinished;136        /// <summary>137        /// Raised when a request fails, for example by timing out.138        /// </summary>139        public event EventHandler<RequestEventArgs> RequestFailed;140        /// <summary>141        /// Raised when an uncaught exception happens within the page.142        /// </summary>143        public event EventHandler<PageErrorEventArgs> PageError;144        /// <summary>145        /// This setting will change the default maximum navigation time of 30 seconds for the following methods:146        /// - <see cref="GoToAsync(string, NavigationOptions)"/>147        /// - <see cref="GoBackAsync(NavigationOptions)"/>148        /// - <see cref="GoForwardAsync(NavigationOptions)"/>149        /// - <see cref="ReloadAsync(NavigationOptions)"/>150        /// - <see cref="WaitForNavigationAsync(NavigationOptions)"/>151        /// </summary>152        public int DefaultNavigationTimeout { get; set; } = 30000;153        /// <summary>154        /// Gets page's main frame155        /// </summary>156        /// <remarks>157        /// Page is guaranteed to have a main frame which persists during navigations.158        /// </remarks>159        public Frame MainFrame => _frameManager.MainFrame;160        /// <summary>161        /// Gets all frames attached to the page.162        /// </summary>163        /// <value>An array of all frames attached to the page.</value>164        public Frame[] Frames => _frameManager.Frames.Values.ToArray();165        /// <summary>166        /// Shortcut for <c>page.MainFrame.Url</c>167        /// </summary>168        public string Url => MainFrame.Url;169        /// <summary>170        /// Gets that target this page was created from.171        /// </summary>172        public Target Target { get; }173        /// <summary>174        /// Gets this page's keyboard175        /// </summary>176        public Keyboard Keyboard { get; }177        /// <summary>178        /// Gets this page's touchscreen179        /// </summary>180        public Touchscreen Touchscreen { get; }181        /// <summary>182        /// Gets this page's coverage183        /// </summary>184        public Coverage Coverage { get; }185        /// <summary>186        /// Gets this page's tracing187        /// </summary>188        public Tracing Tracing { get; }189        /// <summary>190        /// Gets this page's mouse191        /// </summary>192        public Mouse Mouse { get; }193        /// <summary>194        /// Gets this page's viewport195        /// </summary>196        public ViewPortOptions Viewport { get; private set; }197        /// <summary>198        /// List of suported metrics provided by the <see cref="Metrics"/> event.199        /// </summary>200        public static readonly IEnumerable<string> SupportedMetrics = new List<string>201        {202            "Timestamp",203            "Documents",204            "Frames",205            "JSEventListeners",206            "Nodes",207            "LayoutCount",208            "RecalcStyleCount",209            "LayoutDuration",210            "RecalcStyleDuration",211            "ScriptDuration",212            "TaskDuration",213            "JSHeapUsedSize",214            "JSHeapTotalSize"215        };216        #endregion217        #region Public Methods218        /// <summary>219        /// Returns metrics220        /// </summary>221        /// <returns>Task which resolves into a list of metrics</returns>222        /// <remarks>223        /// All timestamps are in monotonic time: monotonically increasing time in seconds since an arbitrary point in the past.224        /// </remarks>225        public async Task<Dictionary<string, decimal>> MetricsAsync()226        {227            var response = await Client.SendAsync<PerformanceGetMetricsResponse>("Performance.getMetrics");228            return BuildMetricsObject(response.Metrics);229        }230        /// <summary>231        /// Fetches an element with <paramref name="selector"/>, scrolls it into view if needed, and then uses <see cref="Touchscreen"/> to tap in the center of the element.232        /// </summary>233        /// <param name="selector">A selector to search for element to tap. If there are multiple elements satisfying the selector, the first will be clicked.</param>234        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>235        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully tapped</returns>236        public async Task TapAsync(string selector)237        {238            var handle = await QuerySelectorAsync(selector);239            if (handle == null)240            {241                throw new SelectorException($"No node found for selector: {selector}", selector);242            }243            await handle.TapAsync();244            await handle.DisposeAsync();245        }246        /// <summary>247        /// The method runs <c>document.querySelector</c> within the page. If no element matches the selector, the return value resolve to <c>null</c>.248        /// </summary>249        /// <param name="selector">A selector to query page for</param>250        /// <returns>Task which resolves to <see cref="ElementHandle"/> pointing to the frame element</returns>251        /// <remarks>252        /// Shortcut for <c>page.MainFrame.QuerySelectorAsync(selector)</c>253        /// </remarks>254        /// <seealso cref="Frame.QuerySelectorAsync(string)"/>255        public Task<ElementHandle> QuerySelectorAsync(string selector)256            => MainFrame.QuerySelectorAsync(selector);257        /// <summary>258        /// Runs <c>document.querySelectorAll</c> within the page. If no elements match the selector, the return value resolve to <see cref="Array.Empty{T}"/>.259        /// </summary>260        /// <param name="selector">A selector to query page for</param>261        /// <returns>Task which resolves to ElementHandles pointing to the frame elements</returns>262        /// <seealso cref="Frame.QuerySelectorAllAsync(string)"/>263        public Task<ElementHandle[]> QuerySelectorAllAsync(string selector)264            => MainFrame.QuerySelectorAllAsync(selector);265        /// <summary>266        /// A utility function to be used with <see cref="Extensions.EvaluateFunctionAsync{T}(Task{JSHandle}, string, object[])"/>267        /// </summary>268        /// <param name="selector">A selector to query page for</param>269        /// <returns>Task which resolves to a <see cref="JSHandle"/> of <c>document.querySelectorAll</c> result</returns>270        public Task<JSHandle> QuerySelectorAllHandleAsync(string selector)271            => EvaluateFunctionHandleAsync("selector => Array.from(document.querySelectorAll(selector))", selector);272        /// <summary>273        /// Evaluates the XPath expression274        /// </summary>275        /// <param name="expression">Expression to evaluate <see href="https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate"/></param>276        /// <returns>Task which resolves to an array of <see cref="ElementHandle"/></returns>277        /// <remarks>278        /// Shortcut for <c>page.MainFrame.XPathAsync(expression)</c>279        /// </remarks>280        /// <seealso cref="Frame.XPathAsync(string)"/>281        public Task<ElementHandle[]> XPathAsync(string expression) => MainFrame.XPathAsync(expression);282        /// <summary>283        /// Executes a script in browser context284        /// </summary>285        /// <param name="script">Script to be evaluated in browser context</param>286        /// <remarks>287        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.288        /// </remarks>289        /// <returns>Task which resolves to script return value</returns>290        public async Task<JSHandle> EvaluateExpressionHandleAsync(string script)291        {292            var context = await MainFrame.GetExecutionContextAsync();293            return await context.EvaluateExpressionHandleAsync(script);294        }295        /// <summary>296        /// Executes a script in browser context297        /// </summary>298        /// <param name="pageFunction">Script to be evaluated in browser context</param>299        /// <param name="args">Function arguments</param>300        /// <remarks>301        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.302        /// <see cref="JSHandle"/> instances can be passed as arguments303        /// </remarks>304        /// <returns>Task which resolves to script return value</returns>305        public async Task<JSHandle> EvaluateFunctionHandleAsync(string pageFunction, params object[] args)306        {307            var context = await MainFrame.GetExecutionContextAsync();308            return await context.EvaluateFunctionHandleAsync(pageFunction, args);309        }310        /// <summary>311        /// Adds a function which would be invoked in one of the following scenarios:312        /// - whenever the page is navigated313        /// - whenever the child frame is attached or navigated. In this case, the function is invoked in the context of the newly attached frame314        /// </summary>315        /// <param name="pageFunction">Function to be evaluated in browser context</param>316        /// <param name="args">Arguments to pass to <c>pageFunction</c></param>317        /// <remarks>318        /// The function is invoked after the document was created but before any of its scripts were run. This is useful to amend JavaScript environment, e.g. to seed <c>Math.random</c>.319        /// </remarks>320        /// <example>321        /// An example of overriding the navigator.languages property before the page loads:322        /// <code>323        /// var overrideNavigatorLanguages = @"Object.defineProperty(navigator, 'languages', {324        ///   get: function() {325        ///     return ['en-US', 'en', 'bn'];326        ///   };327        /// });";328        /// await page.EvaluateOnNewDocumentAsync(overrideNavigatorLanguages);329        /// </code>330        /// </example>331        /// <returns>Task</returns>332        public Task EvaluateOnNewDocumentAsync(string pageFunction, params object[] args)333        {334            var source = EvaluationString(pageFunction, args);335            return Client.SendAsync("Page.addScriptToEvaluateOnNewDocument", new { source });336        }337        /// <summary>338        /// The method iterates JavaScript heap and finds all the objects with the given prototype.339        /// Shortcut for <c>page.MainFrame.GetExecutionContextAsync().QueryObjectsAsync(prototypeHandle)</c>.340        /// </summary>341        /// <returns>A task which resolves to a handle to an array of objects with this prototype.</returns>342        /// <param name="prototypeHandle">A handle to the object prototype.</param>343        public async Task<JSHandle> QueryObjectsAsync(JSHandle prototypeHandle)344        {345            var context = await MainFrame.GetExecutionContextAsync();346            return await context.QueryObjectsAsync(prototypeHandle);347        }348        /// <summary>349        /// Activating request interception enables <see cref="Request.AbortAsync(RequestAbortErrorCode)">request.AbortAsync</see>, 350        /// <see cref="Request.ContinueAsync(Payload)">request.ContinueAsync</see> and <see cref="Request.RespondAsync(ResponseData)">request.RespondAsync</see> methods.351        /// </summary>352        /// <returns>The request interception task.</returns>353        /// <param name="value">Whether to enable request interception..</param>354        public Task SetRequestInterceptionAsync(bool value)355            => _networkManager.SetRequestInterceptionAsync(value);356        /// <summary>357        /// Set offline mode for the page.358        /// </summary>359        /// <returns>Result task</returns>360        /// <param name="value">When <c>true</c> enables offline mode for the page.</param>361        public Task SetOfflineModeAsync(bool value) => _networkManager.SetOfflineModeAsync(value);362        /// <summary>363        /// Returns the page's cookies364        /// </summary>365        /// <param name="urls">Url's to return cookies for</param>366        /// <returns>Array of cookies</returns>367        /// <remarks>368        /// If no URLs are specified, this method returns cookies for the current page URL.369        /// If URLs are specified, only cookies for those URLs are returned.370        /// </remarks>371        public async Task<CookieParam[]> GetCookiesAsync(params string[] urls)372        {373            var response = await Client.SendAsync("Network.getCookies", new Dictionary<string, object>374            {375                { "urls", urls.Length > 0 ? urls : new string[] { Url } }376            });377            return response.cookies.ToObject<CookieParam[]>();378        }379        /// <summary>380        /// Clears all of the current cookies and then sets the cookies for the page381        /// </summary>382        /// <param name="cookies">Cookies to set</param>383        /// <returns>Task</returns>384        public async Task SetCookieAsync(params CookieParam[] cookies)385        {386            foreach (var cookie in cookies)387            {388                if (string.IsNullOrEmpty(cookie.Url) && Url.StartsWith("http", StringComparison.Ordinal))389                {390                    cookie.Url = Url;391                }392                if (cookie.Url == "about:blank")393                {394                    throw new PuppeteerException($"Blank page can not have cookie \"{cookie.Name}\"");395                }396            }397            await DeleteCookieAsync(cookies);398            if (cookies.Length > 0)399            {400                await Client.SendAsync("Network.setCookies", new Dictionary<string, object>401                {402                    { "cookies", cookies}403                });404            }405        }406        /// <summary>407        /// Deletes cookies from the page408        /// </summary>409        /// <param name="cookies">Cookies to delete</param>410        /// <returns>Task</returns>411        public async Task DeleteCookieAsync(params CookieParam[] cookies)412        {413            var pageURL = Url;414            foreach (var cookie in cookies)415            {416                if (string.IsNullOrEmpty(cookie.Url) && pageURL.StartsWith("http", StringComparison.Ordinal))417                {418                    cookie.Url = pageURL;419                }420                await Client.SendAsync("Network.deleteCookies", cookie);421            }422        }423        /// <summary>424        /// Adds a <c><![CDATA[<script>]]></c> tag into the page with the desired url or content425        /// </summary>426        /// <param name="options">add script tag options</param>427        /// <remarks>428        /// Shortcut for <c>page.MainFrame.AddScriptTagAsync(options)</c>429        /// </remarks>430        /// <returns>Task which resolves to the added tag when the script's onload fires or when the script content was injected into frame</returns>431        /// <seealso cref="Frame.AddScriptTag(AddTagOptions)"/>432        public Task<ElementHandle> AddScriptTagAsync(AddTagOptions options) => MainFrame.AddScriptTag(options);433        /// <summary>434        /// Adds a <c><![CDATA[<script>]]></c> tag into the page with the desired url or content435        /// </summary>436        /// <param name="url">script url</param>437        /// <remarks>438        /// Shortcut for <c>page.MainFrame.AddScriptTagAsync(new AddTagOptions { Url = url })</c>439        /// </remarks>440        /// <returns>Task which resolves to the added tag when the script's onload fires or when the script content was injected into frame</returns>441        public Task<ElementHandle> AddScriptTagAsync(string url) => AddScriptTagAsync(new AddTagOptions { Url = url });442        /// <summary>443        /// Adds a <c><![CDATA[<link rel="stylesheet">]]></c> tag into the page with the desired url or a <c><![CDATA[<link rel="stylesheet">]]></c> tag with the content444        /// </summary>445        /// <param name="options">add style tag options</param>446        /// <remarks>447        /// Shortcut for <c>page.MainFrame.AddStyleTagAsync(options)</c>448        /// </remarks>449        /// <returns>Task which resolves to the added tag when the stylesheet's onload fires or when the CSS content was injected into frame</returns>450        /// <seealso cref="Frame.AddStyleTag(AddTagOptions)"/>451        public Task<ElementHandle> AddStyleTagAsync(AddTagOptions options) => MainFrame.AddStyleTag(options);452        /// <summary>453        /// Adds a <c><![CDATA[<link rel="stylesheet">]]></c> tag into the page with the desired url or a <c><![CDATA[<link rel="stylesheet">]]></c> tag with the content454        /// </summary>455        /// <param name="url">stylesheel url</param>456        /// <remarks>457        /// Shortcut for <c>page.MainFrame.AddStyleTagAsync(new AddTagOptions { Url = url })</c>458        /// </remarks>459        /// <returns>Task which resolves to the added tag when the stylesheet's onload fires or when the CSS content was injected into frame</returns>460        public Task<ElementHandle> AddStyleTagAsync(string url) => AddStyleTagAsync(new AddTagOptions { Url = url });461        /// <summary>462        /// Adds a function called <c>name</c> on the page's <c>window</c> object.463        /// When called, the function executes <paramref name="puppeteerFunction"/> in C# and returns a <see cref="Task"/> which resolves when <paramref name="puppeteerFunction"/> completes.464        /// </summary>465        /// <param name="name">Name of the function on the window object</param>466        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>467        /// <remarks>468        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.469        /// Functions installed via <see cref="ExposeFunctionAsync(string, Action)"/> survive navigations470        /// </remarks>471        /// <returns>Task</returns>472        public Task ExposeFunctionAsync(string name, Action puppeteerFunction)473            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);474        /// <summary>475        /// Adds a function called <c>name</c> on the page's <c>window</c> object.476        /// When called, the function executes <paramref name="puppeteerFunction"/> in C# and returns a <see cref="Task"/> which resolves to the return value of <paramref name="puppeteerFunction"/>.477        /// </summary>478        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>479        /// <param name="name">Name of the function on the window object</param>480        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>481        /// <remarks>482        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.483        /// Functions installed via <see cref="ExposeFunctionAsync{TResult}(string, Func{TResult})"/> survive navigations484        /// </remarks>485        /// <returns>Task</returns>486        public Task ExposeFunctionAsync<TResult>(string name, Func<TResult> puppeteerFunction)487            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);488        /// <summary>489        /// Adds a function called <c>name</c> on the page's <c>window</c> object.490        /// When called, the function executes <paramref name="puppeteerFunction"/> in C# and returns a <see cref="Task"/> which resolves to the return value of <paramref name="puppeteerFunction"/>.491        /// </summary>492        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>493        /// <typeparam name="T">The parameter of <paramref name="puppeteerFunction"/></typeparam>494        /// <param name="name">Name of the function on the window object</param>495        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>496        /// <remarks>497        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.498        /// Functions installed via <see cref="ExposeFunctionAsync{T, TResult}(string, Func{T, TResult})"/> survive navigations499        /// </remarks>500        /// <returns>Task</returns>501        public Task ExposeFunctionAsync<T, TResult>(string name, Func<T, TResult> puppeteerFunction)502            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);503        /// <summary>504        /// Adds a function called <c>name</c> on the page's <c>window</c> object.505        /// When called, the function executes <paramref name="puppeteerFunction"/> in C# and returns a <see cref="Task"/> which resolves to the return value of <paramref name="puppeteerFunction"/>.506        /// </summary>507        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>508        /// <typeparam name="T1">The first parameter of <paramref name="puppeteerFunction"/></typeparam>509        /// <typeparam name="T2">The second parameter of <paramref name="puppeteerFunction"/></typeparam>510        /// <param name="name">Name of the function on the window object</param>511        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>512        /// <remarks>513        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.514        /// Functions installed via <see cref="ExposeFunctionAsync{T1, T2, TResult}(string, Func{T1, T2, TResult})"/> survive navigations515        /// </remarks>516        /// <returns>Task</returns>517        public Task ExposeFunctionAsync<T1, T2, TResult>(string name, Func<T1, T2, TResult> puppeteerFunction)518            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);519        /// <summary>520        /// Adds a function called <c>name</c> on the page's <c>window</c> object.521        /// When called, the function executes <paramref name="puppeteerFunction"/> in C# and returns a <see cref="Task"/> which resolves to the return value of <paramref name="puppeteerFunction"/>.522        /// </summary>523        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>524        /// <typeparam name="T1">The first parameter of <paramref name="puppeteerFunction"/></typeparam>525        /// <typeparam name="T2">The second parameter of <paramref name="puppeteerFunction"/></typeparam>526        /// <typeparam name="T3">The third parameter of <paramref name="puppeteerFunction"/></typeparam>527        /// <param name="name">Name of the function on the window object</param>528        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>529        /// <remarks>530        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.531        /// Functions installed via <see cref="ExposeFunctionAsync{T1, T2, T3, TResult}(string, Func{TResult})"/> survive navigations532        /// </remarks>533        /// <returns>Task</returns>534        public Task ExposeFunctionAsync<T1, T2, T3, TResult>(string name, Func<TResult> puppeteerFunction)535            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);536        /// <summary>537        /// Adds a function called <c>name</c> on the page's <c>window</c> object.538        /// When called, the function executes <paramref name="puppeteerFunction"/> in C# and returns a <see cref="Task"/> which resolves to the return value of <paramref name="puppeteerFunction"/>.539        /// </summary>540        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>541        /// <typeparam name="T1">The first parameter of <paramref name="puppeteerFunction"/></typeparam>542        /// <typeparam name="T2">The second parameter of <paramref name="puppeteerFunction"/></typeparam>543        /// <typeparam name="T3">The third parameter of <paramref name="puppeteerFunction"/></typeparam>544        /// <typeparam name="T4">The fourth parameter of <paramref name="puppeteerFunction"/></typeparam>545        /// <param name="name">Name of the function on the window object</param>546        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>547        /// <remarks>548        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.549        /// Functions installed via <see cref="ExposeFunctionAsync{T1, T2, T3, T4, TResult}(string, Func{T1, T2, T3, T4, TResult})"/> survive navigations550        /// </remarks>551        /// <returns>Task</returns>552        public Task ExposeFunctionAsync<T1, T2, T3, T4, TResult>(string name, Func<T1, T2, T3, T4, TResult> puppeteerFunction)553            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);554        /// <summary>555        /// Gets the full HTML contents of the page, including the doctype.556        /// </summary>557        /// <returns>Task which resolves to the HTML content.</returns>558        /// <seealso cref="Frame.GetContentAsync"/>559        public Task<string> GetContentAsync() => _frameManager.MainFrame.GetContentAsync();560        /// <summary>561        /// Sets the HTML markup to the page562        /// </summary>563        /// <param name="html">HTML markup to assign to the page.</param>564        /// <returns>Task.</returns>565        /// <seealso cref="Frame.SetContentAsync(string)"/>566        public Task SetContentAsync(string html) => _frameManager.MainFrame.SetContentAsync(html);567        /// <summary>568        /// Navigates to an url569        /// </summary>570        /// <returns>Task which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.</returns>571        /// <param name="url">URL to navigate page to. The url should include scheme, e.g. https://.</param>572        /// <param name="options">Navigation parameters.</param>573        public async Task<Response> GoToAsync(string url, NavigationOptions options = null)574        {575            var referrer = _networkManager.ExtraHTTPHeaders?.GetValueOrDefault("referer");576            var requests = new Dictionary<string, Request>();577            EventHandler<RequestEventArgs> createRequestEventListener = (object sender, RequestEventArgs e) =>578            {579                if (!requests.ContainsKey(e.Request.Url))580                {581                    requests.Add(e.Request.Url, e.Request);582                }583            };584            _networkManager.Request += createRequestEventListener;585            var mainFrame = _frameManager.MainFrame;586            var timeout = options?.Timeout ?? DefaultNavigationTimeout;587            var watcher = new NavigatorWatcher(_frameManager, mainFrame, timeout, options);588            var navigateTask = Navigate(Client, url, referrer);589            await Task.WhenAny(590                watcher.NavigationTask,591                navigateTask);592            AggregateException exception = null;593            if (navigateTask.IsFaulted)594            {595                exception = navigateTask.Exception;596            }597            else if (watcher.NavigationTask.IsCompleted &&598                watcher.NavigationTask.Result.IsFaulted)599            {600                exception = watcher.NavigationTask.Result?.Exception;601            }602            if (exception == null)603            {604                await Task.WhenAll(605                    watcher.NavigationTask,606                    navigateTask);607                exception = navigateTask.Exception ?? watcher.NavigationTask.Result.Exception;608            }609            watcher.Cancel();610            _networkManager.Request -= createRequestEventListener;611            if (exception != null)612            {613                throw new NavigationException(exception.InnerException.Message, exception.InnerException);614            }615            requests.TryGetValue(MainFrame.Url, out var request);616            return request?.Response;617        }618        /// <summary>619        /// generates a pdf of the page with <see cref="MediaType.Print"/> css media. To generate a pdf with <see cref="MediaType.Screen"/> media call <see cref="EmulateMediaAsync(MediaType)"/> with <see cref="MediaType.Screen"/>620        /// </summary>621        /// <param name="file">The file path to save the PDF to. paths are resolved using <see cref="Path.GetFullPath(string)"/></param>622        /// <returns></returns>623        /// <remarks>624        /// Generating a pdf is currently only supported in Chrome headless625        /// </remarks>626        public Task PdfAsync(string file) => PdfAsync(file, new PdfOptions());627        /// <summary>628        ///  generates a pdf of the page with <see cref="MediaType.Print"/> css media. To generate a pdf with <see cref="MediaType.Screen"/> media call <see cref="EmulateMediaAsync(MediaType)"/> with <see cref="MediaType.Screen"/>629        /// </summary>630        /// <param name="file">The file path to save the PDF to. paths are resolved using <see cref="Path.GetFullPath(string)"/></param>631        /// <param name="options">pdf options</param>632        /// <returns></returns>633        /// <remarks>634        /// Generating a pdf is currently only supported in Chrome headless635        /// </remarks>636        public async Task PdfAsync(string file, PdfOptions options)637        {638            var data = await PdfDataAsync(options);639            using (var fs = File.OpenWrite(file))640            {641                await fs.WriteAsync(data, 0, data.Length);642            }643        }644        /// <summary>645        /// generates a pdf of the page with <see cref="MediaType.Print"/> css media. To generate a pdf with <see cref="MediaType.Screen"/> media call <see cref="EmulateMediaAsync(MediaType)"/> with <see cref="MediaType.Screen"/>646        /// </summary>647        /// <returns>Task which resolves to a <see cref="Stream"/> containing the PDF data.</returns>648        /// <remarks>649        /// Generating a pdf is currently only supported in Chrome headless650        /// </remarks>651        public Task<Stream> PdfStreamAsync() => PdfStreamAsync(new PdfOptions());652        /// <summary>653        /// Generates a pdf of the page with <see cref="MediaType.Print"/> css media. To generate a pdf with <see cref="MediaType.Screen"/> media call <see cref="EmulateMediaAsync(MediaType)"/> with <see cref="MediaType.Screen"/>654        /// </summary>655        /// <param name="options">pdf options</param>656        /// <returns>Task which resolves to a <see cref="Stream"/> containing the PDF data.</returns>657        /// <remarks>658        /// Generating a pdf is currently only supported in Chrome headless659        /// </remarks>660        public async Task<Stream> PdfStreamAsync(PdfOptions options)661            => new MemoryStream(await PdfDataAsync(options));662        /// <summary>663        /// Generates a pdf of the page with <see cref="MediaType.Print"/> css media. To generate a pdf with <see cref="MediaType.Screen"/> media call <see cref="EmulateMediaAsync(MediaType)"/> with <see cref="MediaType.Screen"/>664        /// </summary>665        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the PDF data.</returns>666        /// <remarks>667        /// Generating a pdf is currently only supported in Chrome headless668        /// </remarks>669        public Task<byte[]> PdfDataAsync() => PdfDataAsync(new PdfOptions());670        /// <summary>671        /// Generates a pdf of the page with <see cref="MediaType.Print"/> css media. To generate a pdf with <see cref="MediaType.Screen"/> media call <see cref="EmulateMediaAsync(MediaType)"/> with <see cref="MediaType.Screen"/>672        /// </summary>673        /// <param name="options">pdf options</param>674        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the PDF data.</returns>675        /// <remarks>676        /// Generating a pdf is currently only supported in Chrome headless677        /// </remarks>678        public async Task<byte[]> PdfDataAsync(PdfOptions options)679        {680            var paperWidth = PaperFormat.Letter.Width;681            var paperHeight = PaperFormat.Letter.Height;682            if (options.Format != null)683            {684                paperWidth = options.Format.Width;685                paperHeight = options.Format.Height;686            }687            else688            {689                if (options.Width != null)690                {691                    paperWidth = ConvertPrintParameterToInches(options.Width);692                }693                if (options.Height != null)694                {695                    paperHeight = ConvertPrintParameterToInches(options.Height);696                }697            }698            var marginTop = ConvertPrintParameterToInches(options.MarginOptions.Top);699            var marginLeft = ConvertPrintParameterToInches(options.MarginOptions.Left);700            var marginBottom = ConvertPrintParameterToInches(options.MarginOptions.Bottom);701            var marginRight = ConvertPrintParameterToInches(options.MarginOptions.Right);702            JObject result = await Client.SendAsync("Page.printToPDF", new703            {704                landscape = options.Landscape,705                displayHeaderFooter = options.DisplayHeaderFooter,706                headerTemplate = options.HeaderTemplate,707                footerTemplate = options.FooterTemplate,708                printBackground = options.PrintBackground,709                scale = options.Scale,710                paperWidth,711                paperHeight,712                marginTop,713                marginBottom,714                marginLeft,715                marginRight,716                pageRanges = options.PageRanges717            });718            var buffer = Convert.FromBase64String(result.GetValue("data").Value<string>());719            return buffer;720        }721        /// <summary>722        /// Enables/Disables Javascript on the page723        /// </summary>724        /// <returns>Task.</returns>725        /// <param name="enabled">Whether or not to enable JavaScript on the page.</param>726        public Task SetJavaScriptEnabledAsync(bool enabled)727            => Client.SendAsync("Emulation.setScriptExecutionDisabled", new { value = !enabled });728        /// <summary>729        /// Emulates a media such as screen or print.730        /// </summary>731        /// <returns>Task.</returns>732        /// <param name="media">Media to set.</param>733        public Task EmulateMediaAsync(MediaType media)734            => Client.SendAsync("Emulation.setEmulatedMedia", new { media });735        /// <summary>736        /// Sets the viewport.737        /// In the case of multiple pages in a single browser, each page can have its own viewport size.738        /// NOTE in certain cases, setting viewport will reload the page in order to set the isMobile or hasTouch properties.739        /// </summary>740        /// <returns>The viewport task.</returns>741        /// <param name="viewport">Viewport options.</param>742        public async Task SetViewportAsync(ViewPortOptions viewport)743        {744            var needsReload = await _emulationManager.EmulateViewport(Client, viewport);745            Viewport = viewport;746            if (needsReload)747            {748                await ReloadAsync();749            }750        }751        /// <summary>752        /// Emulates given device metrics and user agent. 753        /// </summary>754        /// <remarks>755        /// This method is a shortcut for calling two methods:756        /// page.SetViewportAsync(userAgent)757        /// page.SetUserAgentAsync(viewport)758        /// </remarks>759        /// <returns>Task.</returns>760        /// <param name="options">Emulation options.</param>761        public Task EmulateAsync(DeviceDescriptor options) => Task.WhenAll(762            SetViewportAsync(options.ViewPort),763            SetUserAgentAsync(options.UserAgent)764        );765        /// <summary>766        /// Takes a screenshot of the page767        /// </summary>768        /// <returns>The screenshot task.</returns>769        /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension. 770        /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided, 771        /// the image won't be saved to the disk.</param>772        public Task ScreenshotAsync(string file) => ScreenshotAsync(file, new ScreenshotOptions());773        /// <summary>774        /// Takes a screenshot of the page775        /// </summary>776        /// <returns>The screenshot task.</returns>777        /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension. 778        /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided, 779        /// the image won't be saved to the disk.</param>780        /// <param name="options">Screenshot options.</param>781        public async Task ScreenshotAsync(string file, ScreenshotOptions options)782        {783            var fileInfo = new FileInfo(file);784            options.Type = fileInfo.Extension.Replace(".", string.Empty);785            var data = await ScreenshotDataAsync(options);786            using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))787            {788                await fs.WriteAsync(data, 0, data.Length);789            }790        }791        /// <summary>792        /// Takes a screenshot of the page793        /// </summary>794        /// <returns>Task which resolves to a <see cref="Stream"/> containing the image data.</returns>795        public Task<Stream> ScreenshotStreamAsync() => ScreenshotStreamAsync(new ScreenshotOptions());796        /// <summary>797        /// Takes a screenshot of the page798        /// </summary>799        /// <returns>Task which resolves to a <see cref="Stream"/> containing the image data.</returns>800        /// <param name="options">Screenshot options.</param>801        public async Task<Stream> ScreenshotStreamAsync(ScreenshotOptions options)802            => new MemoryStream(await ScreenshotDataAsync(options));803        /// <summary>804        /// Takes a screenshot of the page805        /// </summary>806        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>807        public Task<byte[]> ScreenshotDataAsync() => ScreenshotDataAsync(new ScreenshotOptions());808        /// <summary>809        /// Takes a screenshot of the page810        /// </summary>811        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>812        /// <param name="options">Screenshot options.</param>813        public async Task<byte[]> ScreenshotDataAsync(ScreenshotOptions options)814        {815            string screenshotType = null;816            if (!string.IsNullOrEmpty(options.Type))817            {818                if (options.Type != "png" && options.Type != "jpeg")819                {820                    throw new ArgumentException($"Unknown options.type {options.Type}");821                }822                screenshotType = options.Type;823            }824            if (string.IsNullOrEmpty(screenshotType))825            {826                screenshotType = "png";827            }828            if (options.Quality.HasValue)829            {830                if (screenshotType == "jpeg")831                {832                    throw new ArgumentException($"options.Quality is unsupported for the {screenshotType} screenshots");833                }834                if (options.Quality < 0 || options.Quality > 100)835                {836                    throw new ArgumentException($"Expected options.quality to be between 0 and 100 (inclusive), got {options.Quality}");837                }838            }839            if (options.Clip != null && options.FullPage)840            {841                throw new ArgumentException("options.clip and options.fullPage are exclusive");842            }843            return await _screenshotTaskQueue.Enqueue(() => PerformScreenshot(screenshotType, options));844        }845        /// <summary>846        /// Returns page's title847        /// </summary>848        /// <returns>page's title</returns>849        /// <see cref="Frame.GetTitleAsync"/>850        public Task<string> GetTitleAsync() => MainFrame.GetTitleAsync();851        /// <summary>852        /// Closes the page.853        /// </summary>854        /// <returns>Task.</returns>855        public Task CloseAsync()856        {857            if (!(Client?.Connection?.IsClosed ?? true))858            {859                return Client.Connection.SendAsync("Target.closeTarget", new860                {861                    targetId = Target.TargetId862                });863            }864            return Task.CompletedTask;865        }866        /// <summary>867        /// Fetches an element with <paramref name="selector"/>, scrolls it into view if needed, and then uses <see cref="Page.Mouse"/> to click in the center of the element.868        /// </summary>869        /// <param name="selector">A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked.</param>870        /// <param name="options">click options</param>871        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>872        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully clicked</returns>873        public async Task ClickAsync(string selector, ClickOptions options = null)874        {875            var handle = await QuerySelectorAsync(selector);876            if (handle == null)877            {878                throw new SelectorException($"No node found for selector: {selector}", selector);879            }880            await handle.ClickAsync(options);881            await handle.DisposeAsync();882        }883        /// <summary>884        /// Fetches an element with <paramref name="selector"/>, scrolls it into view if needed, and then uses <see cref="Page.Mouse"/> to hover over the center of the element.885        /// </summary>886        /// <param name="selector">A selector to search for element to hover. If there are multiple elements satisfying the selector, the first will be hovered.</param>887        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>888        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully hovered</returns>889        public async Task HoverAsync(string selector)890        {891            var handle = await QuerySelectorAsync(selector);892            if (handle == null)893            {894                throw new SelectorException($"No node found for selector: {selector}", selector);895            }896            await handle.HoverAsync();897            await handle.DisposeAsync();898        }899        /// <summary>900        /// Fetches an element with <paramref name="selector"/> and focuses it901        /// </summary>902        /// <param name="selector">A selector to search for element to focus. If there are multiple elements satisfying the selector, the first will be focused.</param>903        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>904        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully focused</returns>905        public async Task FocusAsync(string selector)906        {907            var handle = await QuerySelectorAsync(selector);908            if (handle == null)909            {910                throw new SelectorException($"No node found for selector: {selector}", selector);911            }912            await handle.FocusAsync();913            await handle.DisposeAsync();914        }915        /// <summary>916        /// Executes a script in browser context917        /// </summary>918        /// <param name="script">Script to be evaluated in browser context</param>919        /// <remarks>920        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.921        /// </remarks>922        /// <seealso cref="EvaluateFunctionAsync(string, object[])"/>923        /// <returns>Task which resolves to script return value</returns>924        public Task<dynamic> EvaluateExpressionAsync(string script)925            => _frameManager.MainFrame.EvaluateExpressionAsync(script);926        /// <summary>927        /// Executes a script in browser context928        /// </summary>929        /// <typeparam name="T">The type to deserialize the result to</typeparam>930        /// <param name="script">Script to be evaluated in browser context</param>931        /// <remarks>932        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.933        /// </remarks>934        /// <seealso cref="EvaluateFunctionAsync{T}(string, object[])"/>935        /// <returns>Task which resolves to script return value</returns>936        public Task<T> EvaluateExpressionAsync<T>(string script)937            => _frameManager.MainFrame.EvaluateExpressionAsync<T>(script);938        /// <summary>939        /// Executes a function in browser context940        /// </summary>941        /// <param name="script">Script to be evaluated in browser context</param>942        /// <param name="args">Arguments to pass to script</param>943        /// <remarks>944        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.945        /// <see cref="JSHandle"/> instances can be passed as arguments946        /// </remarks>947        /// <seealso cref="EvaluateExpressionAsync(string)"/>948        /// <returns>Task which resolves to script return value</returns>949        public Task<dynamic> EvaluateFunctionAsync(string script, params object[] args)950            => _frameManager.MainFrame.EvaluateFunctionAsync(script, args);951        /// <summary>952        /// Executes a function in browser context953        /// </summary>954        /// <typeparam name="T">The type to deserialize the result to</typeparam>955        /// <param name="script">Script to be evaluated in browser context</param>956        /// <param name="args">Arguments to pass to script</param>957        /// <remarks>958        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.959        /// <see cref="JSHandle"/> instances can be passed as arguments960        /// </remarks>961        /// <seealso cref="EvaluateExpressionAsync{T}(string)"/>962        /// <returns>Task which resolves to script return value</returns>963        public Task<T> EvaluateFunctionAsync<T>(string script, params object[] args)964            => _frameManager.MainFrame.EvaluateFunctionAsync<T>(script, args);965        /// <summary>966        /// Sets the user agent to be used in this page967        /// </summary>968        /// <param name="userAgent">Specific user agent to use in this page</param>969        /// <returns>Task</returns>970        public Task SetUserAgentAsync(string userAgent)971            => _networkManager.SetUserAgentAsync(userAgent);972        /// <summary>973        /// Sets extra HTTP headers that will be sent with every request the page initiates974        /// </summary>975        /// <param name="headers">Additional http headers to be sent with every request</param>976        /// <returns>Task</returns>977        public Task SetExtraHttpHeadersAsync(Dictionary<string, string> headers)978            => _networkManager.SetExtraHTTPHeadersAsync(headers);979        /// <summary>980        /// Provide credentials for http authentication <see href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication"/>981        /// </summary>982        /// <param name="credentials">The credentials</param>983        /// <returns></returns>984        /// <remarks>985        /// To disable authentication, pass <c>null</c>986        /// </remarks>987        public Task AuthenticateAsync(Credentials credentials) => _networkManager.AuthenticateAsync(credentials);988        /// <summary>989        /// Reloads the page990        /// </summary>991        /// <param name="options">Navigation options</param>992        /// <returns>Task which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect</returns>993        public async Task<Response> ReloadAsync(NavigationOptions options = null)994        {995            var navigationTask = WaitForNavigationAsync(options);996            await Task.WhenAll(997              navigationTask,998              Client.SendAsync("Page.reload")999            );1000            return navigationTask.Result;1001        }1002        /// <summary>1003        /// Triggers a change and input event once all the provided options have been selected. 1004        /// If there's no <![CDATA[<select>]]> element matching selector, the method throws an error.1005        /// </summary>1006        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>1007        /// <param name="selector">A selector to query page for</param>1008        /// <param name="values">Values of options to select. If the <![CDATA[<select>]]> has the multiple attribute, 1009        /// all values are considered, otherwise only the first one is taken into account.</param>1010        /// <returns>Returns an array of option values that have been successfully selected.</returns>1011        /// <seealso cref="Frame.SelectAsync(string, string[])"/>1012        public Task<string[]> SelectAsync(string selector, params string[] values)1013            => MainFrame.SelectAsync(selector, values);1014        /// <summary>1015        /// Sends a <c>keydown</c>, <c>keypress</c>/<c>input</c>, and <c>keyup</c> event for each character in the text.1016        /// </summary>1017        /// <param name="selector">A selector of an element to type into. If there are multiple elements satisfying the selector, the first will be used.</param>1018        /// <param name="text">A text to type into a focused element</param>1019        /// <param name="options"></param>1020        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>1021        /// <remarks>1022        /// To press a special key, like <c>Control</c> or <c>ArrowDown</c> use <see cref="Keyboard.PressAsync(string, PressOptions)"/>1023        /// </remarks>1024        /// <example>1025        /// <code>1026        /// page.TypeAsync("#mytextarea", "Hello"); // Types instantly1027        /// page.TypeAsync("#mytextarea", "World", new TypeOptions { Delay = 100 }); // Types slower, like a user1028        /// </code>1029        /// </example>1030        /// <returns>Task</returns>1031        public async Task TypeAsync(string selector, string text, TypeOptions options = null)1032        {1033            var handle = await QuerySelectorAsync(selector);1034            if (handle == null)1035            {1036                throw new SelectorException($"No node found for selector: {selector}", selector);1037            }1038            await handle.TypeAsync(text, options);1039            await handle.DisposeAsync();1040        }1041        /// <summary>1042        /// Waits for a timeout1043        /// </summary>1044        /// <param name="milliseconds"></param>1045        /// <returns>A task that resolves when after the timeout</returns>1046        /// <seealso cref="Frame.WaitForTimeoutAsync(int)"/>1047        public Task WaitForTimeoutAsync(int milliseconds)1048            => MainFrame.WaitForTimeoutAsync(milliseconds);1049        /// <summary>1050        /// Waits for a script to be evaluated to a truthy value1051        /// </summary>1052        /// <param name="script">Function to be evaluated in browser context</param>1053        /// <param name="options">Optional waiting parameters</param>1054        /// <param name="args">Arguments to pass to <c>script</c></param>1055        /// <returns>A task that resolves when the <c>script</c> returns a truthy value</returns>1056        /// <seealso cref="Frame.WaitForFunctionAsync(string, WaitForFunctionOptions, object[])"/>1057        public Task<JSHandle> WaitForFunctionAsync(string script, WaitForFunctionOptions options = null, params object[] args)1058            => MainFrame.WaitForFunctionAsync(script, options ?? new WaitForFunctionOptions(), args);1059        /// <summary>1060        /// Waits for a script to be evaluated to a truthy value1061        /// </summary>1062        /// <param name="script">Function to be evaluated in browser context</param>1063        /// <param name="args">Arguments to pass to <c>script</c></param>1064        /// <returns>A task that resolves when the <c>script</c> returns a truthy value</returns>1065        public Task<JSHandle> WaitForFunctionAsync(string script, params object[] args) => WaitForFunctionAsync(script, null, args);1066        /// <summary>1067        /// Waits for a selector to be added to the DOM1068        /// </summary>1069        /// <param name="selector">A selector of an element to wait for</param>1070        /// <param name="options">Optional waiting parameters</param>1071        /// <returns>A task that resolves when element specified by selector string is added to DOM</returns>1072        public Task<ElementHandle> WaitForSelectorAsync(string selector, WaitForSelectorOptions options = null)1073            => MainFrame.WaitForSelectorAsync(selector, options ?? new WaitForSelectorOptions());1074        /// <summary>1075        /// Waits for navigation1076        /// </summary>1077        /// <param name="options">navigation options</param>1078        /// <returns>Task which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect</returns>1079        public async Task<Response> WaitForNavigationAsync(NavigationOptions options = null)1080        {1081            var mainFrame = _frameManager.MainFrame;1082            var timeout = options?.Timeout ?? DefaultNavigationTimeout;1083            var watcher = new NavigatorWatcher(_frameManager, mainFrame, timeout, options);1084            var responses = new Dictionary<string, Response>();1085            EventHandler<ResponseCreatedEventArgs> createResponseEventListener = (object sender, ResponseCreatedEventArgs e) =>1086                responses.Add(e.Response.Url, e.Response);1087            _networkManager.Response += createResponseEventListener;1088            await watcher.NavigationTask;1089            _networkManager.Response -= createResponseEventListener;1090            var exception = watcher.NavigationTask.Exception;1091            if (exception != null)1092            {1093                throw new NavigationException(exception.Message, exception);1094            }1095            return responses.GetValueOrDefault(_frameManager.MainFrame.Url);1096        }1097        /// <summary>1098        /// Navigate to the previous page in history.1099        /// </summary>1100        /// <returns>Task which which resolves to the main resource response. In case of multiple redirects, 1101        /// the navigation will resolve with the response of the last redirect. If can not go back, resolves to null.</returns>1102        /// <param name="options">Navigation parameters.</param>1103        public Task<Response> GoBackAsync(NavigationOptions options = null) => GoAsync(-1, null);1104        /// <summary>1105        /// Navigate to the next page in history.1106        /// </summary>1107        /// <returns>Task which which resolves to the main resource response. In case of multiple redirects, 1108        /// the navigation will resolve with the response of the last redirect. If can not go forward, resolves to null.</returns>1109        /// <param name="options">Navigation parameters.</param>1110        public Task<Response> GoForwardAsync(NavigationOptions options = null) => GoAsync(1, null);1111        #endregion1112        #region Private Method1113        internal static async Task<Page> CreateAsync(CDPSession client, Target target, bool ignoreHTTPSErrors, bool appMode,1114                                                   TaskQueue screenshotTaskQueue)1115        {1116            await client.SendAsync("Page.enable", null);1117            dynamic result = await client.SendAsync("Page.getFrameTree");1118            var page = new Page(client, target, new FrameTree(result.frameTree), ignoreHTTPSErrors, screenshotTaskQueue);1119            await Task.WhenAll(1120                client.SendAsync("Page.setLifecycleEventsEnabled", new Dictionary<string, object>1121                {1122                    {"enabled", true }1123                }),1124                client.SendAsync("Network.enable", null),1125                client.SendAsync("Runtime.enable", null),1126                client.SendAsync("Security.enable", null),1127                client.SendAsync("Performance.enable", null)1128            );1129            if (ignoreHTTPSErrors)1130            {1131                await client.SendAsync("Security.setOverrideCertificateErrors", new Dictionary<string, object>1132                {1133                    {"override", true}1134                });1135            }1136            // Initialize default page size.1137            if (!appMode)1138            {1139                await page.SetViewportAsync(new ViewPortOptions1140                {1141                    Width = 800,1142                    Height = 6001143                });1144            }1145            return page;1146        }1147        private async Task<Response> GoAsync(int delta, NavigationOptions options)1148        {1149            var history = await Client.SendAsync<PageGetNavigationHistoryResponse>("Page.getNavigationHistory");1150            if (history.Entries.Count <= history.CurrentIndex + delta)1151            {1152                return null;1153            }1154            var entry = history.Entries[history.CurrentIndex + delta];1155            var waitTask = WaitForNavigationAsync(options);1156            await Task.WhenAll(1157                waitTask,1158                Client.SendAsync("Page.navigateToHistoryEntry", new1159                {1160                    entryId = entry.Id1161                })1162            );1163            return waitTask.Result;1164        }1165        private Dictionary<string, decimal> BuildMetricsObject(List<Metric> metrics)1166        {1167            var result = new Dictionary<string, decimal>();1168            foreach (var item in metrics)1169            {1170                if (SupportedMetrics.Contains(item.Name))1171                {1172                    result.Add(item.Name, item.Value);1173                }1174            }1175            return result;1176        }1177        private async Task<byte[]> PerformScreenshot(string format, ScreenshotOptions options)1178        {1179            await Client.SendAsync("Target.activateTarget", new1180            {1181                targetId = Target.TargetId1182            });1183            var clip = options.Clip != null ? options.Clip.Clone() : null;1184            if (clip != null)1185            {1186                clip.Scale = 1;1187            }1188            if (options != null && options.FullPage)1189            {1190                dynamic metrics = await Client.SendAsync("Page.getLayoutMetrics");1191                var width = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(metrics.contentSize.width.Value)));1192                var height = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(metrics.contentSize.height.Value)));1193                // Overwrite clip for full page at all times.1194                clip = new Clip1195                {1196                    X = 0,1197                    Y = 0,1198                    Width = width,1199                    Height = height,1200                    Scale = 11201                };1202                var mobile = Viewport.IsMobile;1203                var deviceScaleFactor = Viewport.DeviceScaleFactor;1204                var landscape = Viewport.IsLandscape;1205                var screenOrientation = landscape ?1206                    new ScreenOrientation1207                    {1208                        Angle = 90,1209                        Type = ScreenOrientationType.LandscapePrimary1210                    } :1211                    new ScreenOrientation1212                    {1213                        Angle = 0,1214                        Type = ScreenOrientationType.PortraitPrimary1215                    };1216                await Client.SendAsync("Emulation.setDeviceMetricsOverride", new1217                {1218                    mobile,1219                    width,1220                    height,1221                    deviceScaleFactor,1222                    screenOrientation1223                });1224            }1225            if (options != null && options.OmitBackground)1226            {1227                await Client.SendAsync("Emulation.setDefaultBackgroundColorOverride", new1228                {1229                    color = new1230                    {1231                        r = 0,1232                        g = 0,1233                        b = 0,1234                        a = 01235                    }1236                });1237            }1238            dynamic screenMessage = new ExpandoObject();1239            screenMessage.format = format;1240            if (options.Quality.HasValue)1241            {1242                screenMessage.quality = options.Quality.Value;1243            }1244            if (clip != null)1245            {1246                screenMessage.clip = clip;1247            }1248            JObject result = await Client.SendAsync("Page.captureScreenshot", screenMessage);1249            if (options != null && options.OmitBackground)1250            {1251                await Client.SendAsync("Emulation.setDefaultBackgroundColorOverride");1252            }1253            if (options != null && options.FullPage)1254            {1255                await SetViewportAsync(Viewport);1256            }1257            var buffer = Convert.FromBase64String(result.GetValue("data").Value<string>());1258            return buffer;1259        }1260        private decimal ConvertPrintParameterToInches(object parameter)1261        {1262            if (parameter == null)1263            {1264                return 0;1265            }1266            var pixels = 0m;1267            if (parameter is decimal || parameter is int)1268            {1269                pixels = Convert.ToDecimal(parameter);1270            }1271            else1272            {1273                var text = parameter.ToString();1274                var unit = text.Substring(text.Length - 2).ToLower();1275                var valueText = "";1276                if (_unitToPixels.ContainsKey(unit))1277                {1278                    valueText = text.Substring(0, text.Length - 2);1279                }1280                else1281                {1282                    // In case of unknown unit try to parse the whole parameter as number of pixels.1283                    // This is consistent with phantom's paperSize behavior.1284                    unit = "px";1285                    valueText = text;1286                }1287                if (Decimal.TryParse(valueText, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out var number))1288                {1289                    pixels = number * _unitToPixels[unit];1290                }1291                else1292                {1293                    throw new ArgumentException($"Failed to parse parameter value: '{text}'", nameof(parameter));1294                }1295            }1296            return pixels / 96;1297        }1298        private async void client_MessageReceived(object sender, MessageEventArgs e)1299        {1300            switch (e.MessageID)1301            {1302                case "Page.loadEventFired":1303                    Load?.Invoke(this, new EventArgs());1304                    break;1305                case "Runtime.consoleAPICalled":1306                    await OnConsoleAPI(e.MessageData.ToObject<PageConsoleResponse>());1307                    break;1308                case "Page.javascriptDialogOpening":1309                    OnDialog(e.MessageData.ToObject<PageJavascriptDialogOpeningResponse>());1310                    break;1311                case "Runtime.exceptionThrown":1312                    HandleException(e.MessageData.exceptionDetails);1313                    break;1314                case "Security.certificateError":1315                    await OnCertificateError(e);1316                    break;1317                case "Inspector.targetCrashed":1318                    OnTargetCrashed();1319                    break;1320                case "Performance.metrics":1321                    EmitMetrics(e.MessageData.ToObject<PerformanceMetricsResponse>());1322                    break;1323            }1324        }1325        private void OnTargetCrashed()1326        {1327            if (Error == null)1328            {1329                throw new TargetCrashedException();1330            }1331            Error.Invoke(this, new ErrorEventArgs("Page crashed!"));1332        }1333        private void EmitMetrics(PerformanceMetricsResponse metrics)1334            => Metrics?.Invoke(this, new MetricEventArgs(metrics.Title, BuildMetricsObject(metrics.Metrics)));1335        private async Task OnCertificateError(MessageEventArgs e)1336        {1337            if (_ignoreHTTPSErrors)1338            {1339                try1340                {1341                    await Client.SendAsync("Security.handleCertificateError", new Dictionary<string, object>1342                    {1343                        {"eventId", e.MessageData.eventId },1344                        {"action", "continue"}1345                    });1346                }1347                catch (PuppeteerException ex)1348                {...

Full Screen

Full Screen

BrowserContext.cs

Source:BrowserContext.cs Github

copy

Full Screen

...212		{213			Console.WriteLine("Page_Load");214		}215	}216	private void Page_Metrics(object sender, MetricEventArgs e)217	{218		if (DebugInfo)219		{220			Console.WriteLine($"Page_Metrics: {e.Title}, {e.Metrics.Count}");221		}222	}223	private void Page_PageError(object sender, PageErrorEventArgs e)224	{225		if (DebugInfo)226		{227			Console.WriteLine($"Page_PageError: {e.Message}");228		}229	}230	private void Page_Popup(object sender, PopupEventArgs e)...

Full Screen

Full Screen

MetricsTests.cs

Source:MetricsTests.cs Github

copy

Full Screen

...21        }22        [Fact]23        public async Task MetricsEventFiredOnConsoleTimespan()24        {25            var metricsTaskWrapper = new TaskCompletionSource<MetricEventArgs>();26            Page.Metrics += (sender, e) => metricsTaskWrapper.SetResult(e);27            await Page.EvaluateExpressionAsync("console.timeStamp('test42')");28            var result = await metricsTaskWrapper.Task;29            Assert.Equal("test42", result.Title);30            CheckMetrics(result.Metrics);31        }32        private void CheckMetrics(Dictionary<string, decimal> metrics)33        {34            var metricsToCheck = Page.SupportedMetrics.ToList();35            foreach (var name in metrics.Keys)36            {37                Assert.Contains(name, metricsToCheck);38                Assert.True(metrics[name] >= 0);39                metricsToCheck.Remove(name);...

Full Screen

Full Screen

MetricEventArgs.cs

Source:MetricEventArgs.cs Github

copy

Full Screen

...4{5    /// <summary>6    /// <seealso cref="Page.Metrics"/> arguments.7    /// </summary>8    public class MetricEventArgs : EventArgs9    {10        /// <summary>11        /// Gets the title.12        /// </summary>13        /// <value>The title.</value>14        public string Title { get; }15        /// <summary>16        /// Gets the metrics.17        /// </summary>18        /// <value>The metrics.</value>19        public Dictionary<string, decimal> Metrics { get; }20        /// <summary>21        /// Initializes a new instance of the <see cref="MetricEventArgs"/> class.22        /// </summary>23        /// <param name="title">Title.</param>24        /// <param name="metrics">Metrics.</param>25        public MetricEventArgs(string title, Dictionary<string, decimal> metrics)26        {27            Title = title;28            Metrics = metrics;29        }30    }31}...

Full Screen

Full Screen

MetricEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5    {6        static async Task Main(string[] args)7        {8            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);9            var browser = await Puppeteer.LaunchAsync(new LaunchOptions10            {11                Args = new string[] { "--window-size=800,600" }12            });13            var page = await browser.NewPageAsync();14            await page.SetViewportAsync(new ViewPortOptions { Width = 800, Height = 600 });15            page.MetricsChanged += Page_MetricsChanged;16            Console.ReadLine();17        }18        private static void Page_MetricsChanged(object sender, MetricEventArgs e)19        {20            Console.WriteLine(e.Metrics);21        }22    }23}24{ Timestamp = 1610035789835, Documents = 11, Frames = 2, JSEventListeners = 2, Nodes = 12, LayoutCount = 1, RecalcStyleCount = 1, LayoutDuration = 0.000000, RecalcStyleDuration = 0.000000, ScriptDuration = 0.000000, TaskDuration = 0.000000, JSHeapUsedSize = 0, JSHeapTotalSize = 0 }25{ Timestamp = 1610035790012, Documents = 11, Frames = 2, JSEventListeners = 2, Nodes = 12, LayoutCount = 1, RecalcStyleCount = 1, LayoutDuration = 0.000000, RecalcStyleDuration = 0.000000, ScriptDuration = 0.000000, TaskDuration = 0.000000, JSHeapUsedSize = 0, JSHeapTotalSize = 0 }26{ Timestamp = 1610035790185, Documents = 11, Frames = 2, JSEventListeners = 2, Nodes = 12, LayoutCount = 1, RecalcStyleCount = 1, LayoutDuration = 0.000000, RecalcStyleDuration = 0.000000, ScriptDuration = 0.000000, TaskDuration = 0.000000, JSHeapUsedSize = 0, JSHeapTotalSize = 0 }27{ Timestamp = 161003

Full Screen

Full Screen

MetricEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5    {6        static async Task Main(string[] args)7        {8            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);9            var options = new LaunchOptions { Headless = false };10            using (var browser = await Puppeteer.LaunchAsync(options))11            using (var page = await browser.NewPageAsync())12            {13                page.Metrics += (sender, e) =>14                {15                    Console.WriteLine("Metrics event fired");16                    Console.WriteLine("Timestamp: " + e.Timestamp);17                    Console.WriteLine("Title: " + e.Title);18                    Console.WriteLine("URL: " + e.Url);19                    Console.WriteLine("Frames: " + e.Frames);20                    Console.WriteLine("JSEventListeners: " + e.JSEventListeners);21                    Console.WriteLine("Documents: " + e.Documents);22                    Console.WriteLine("Nodes: " + e.Nodes);23                    Console.WriteLine("LayoutCount: " + e.LayoutCount);24                    Console.WriteLine("RecalcStyleCount: " + e.RecalcStyleCount);25                    Console.WriteLine("LayoutDuration: " + e.LayoutDuration);26                    Console.WriteLine("RecalcStyleDuration: " + e.RecalcStyleDuration);27                    Console.WriteLine("ScriptDuration: " + e.ScriptDuration);28                    Console.WriteLine("TaskDuration: " + e.TaskDuration);29                    Console.WriteLine("JSHeapUsedSize: " + e.JSHeapUsedSize);30                    Console.WriteLine("JSHeapTotalSize: " + e.JSHeapTotalSize);31                };32            }33        }34    }35}

Full Screen

Full Screen

MetricEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5    {6        static void Main(string[] args)7        {8            MainAsync().GetAwaiter().GetResult();9        }10        static async Task MainAsync()11        {12            using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions13            {14            }))15            {16                var page = await browser.NewPageAsync();17                await page.SetViewportAsync(new ViewPortOptions18                {19                });20                await page.ScreenshotAsync("screenshot.png");21                await page.WaitForSelectorAsync(".gLFyf");22                await page.TypeAsync(".gLFyf", "PuppeteerSharp");23                await page.ClickAsync(".FPdoLc > center > input[type=submit]:nth-child(1)");24                await page.WaitForSelectorAsync(".LC20lb");25                await page.ClickAsync(".LC20lb");26                await page.WaitForSelectorAsync("#firstHeading");27                var title = await page.GetTitleAsync();28                Console.WriteLine(title);29                await page.WaitForSelectorAsync("#firstHeading");30                var title = await page.GetTitleAsync();31                Console.WriteLine(title);32            }33        }34    }35}36using PuppeteerSharp;37using System;38using System.Threading.Tasks;39{40    {41        static void Main(string[] args)42        {43            MainAsync().GetAwaiter().GetResult();44        }45        static async Task MainAsync()46        {

Full Screen

Full Screen

MetricEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5    {6        static async Task Main(string[] args)7        {8            var options = new LaunchOptions { Headless = false };9            using (var browser = await Puppeteer.LaunchAsync(options))10            using (var page = await browser.NewPageAsync())11            {12                page.Metrics += Page_Metrics;13            }14        }15        private static void Page_Metrics(object sender, MetricEventArgs e)16        {17            Console.WriteLine(e.Metrics);18        }19    }20}21{Timestamp=1594155736644, Documents=2, Frames=2, JSEventListeners=0, Nodes=9, LayoutCount=1, RecalcStyleCount=0, LayoutDuration=0.16199999999999998, RecalcStyleDuration=0, ScriptDuration=0.002, TaskDuration=0.001, JSHeapUsedSize=2705928, JSHeapTotalSize=4276736}

Full Screen

Full Screen

MetricEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5    {6        static async Task Main(string[] args)7        {8            var browserFetcher = new BrowserFetcher();9            var revisionInfo = await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision);10            var browser = await Puppeteer.LaunchAsync(new LaunchOptions11            {12            });13            var page = await browser.NewPageAsync();14            await page.GoToAsync("ht

Full Screen

Full Screen

MetricEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.IO;4using System.Threading.Tasks;5{6    {7        static void Main(string[] args)8        {9            Console.WriteLine("Hello World!");10            MainAsync().GetAwaiter().GetResult();11        }12        static async Task MainAsync()13        {14            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });15            var page = await browser.NewPageAsync();16            page.Metrics += Page_Metrics;17            await page.PdfAsync("google.pdf");18            await browser.CloseAsync();19        }20        private static void Page_Metrics(object sender, MetricEventArgs e)21        {22            Console.WriteLine(e.Metrics.Title);23        }24    }25}

Full Screen

Full Screen

MetricEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5    {6        public string Title { get; set; }7        public string Metric { get; set; }8        public double Value { get; set; }9    }10}11using PuppeteerSharp;12using System;13using System.Threading.Tasks;14{15    {16        public async Task Run()17        {18            var browser = await Puppeteer.LaunchAsync(new LaunchOptions19            {20                Args = new string[] { "--disable-infobars" }21            });22            var page = await browser.NewPageAsync();23            page.Metrics += Page_Metrics;24            await browser.CloseAsync();25        }26        private void Page_Metrics(object sender, MetricEventArgs e)27        {28            Console.WriteLine($"{e.Title} {e.Metric} {e.Value}");29        }30    }31}32using PuppeteerSharp;33using System;34using System.Threading.Tasks;35{36    {37        public static async Task Main(string[] args)38        {39            var puppeteerSharp = new PuppeteerSharp();40            await puppeteerSharp.Run();41        }42    }43}44using PuppeteerSharp;45using System;46using System.Threading.Tasks;47{48    {49        public async Task Run()50        {51            var browser = await Puppeteer.LaunchAsync(new LaunchOptions52            {53                Args = new string[] { "--disable-infobars" }54            });55            var page = await browser.NewPageAsync();56            page.Metrics += Page_Metrics;57            await browser.CloseAsync();58        }59        private void Page_Metrics(object sender, MetricEventArgs e)60        {61            Console.WriteLine($"{e.Title} {e.Metric} {e.Value}");62        }63    }64}65using PuppeteerSharp;66using System;

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Puppeteer-sharp automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used methods in MetricEventArgs

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful