Best Puppeteer-sharp code snippet using PuppeteerSharp.WorkerEventArgs.WorkerEventArgs
Page.cs
Source:Page.cs  
...163        public event EventHandler<PageErrorEventArgs> PageError;164        /// <summary>165        /// Emitted when a dedicated WebWorker (<see href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API"/>) is spawned by the page.166        /// </summary>167        public event EventHandler<WorkerEventArgs> WorkerCreated;168        /// <summary>169        /// Emitted when a dedicated WebWorker (<see href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API"/>) is terminated.170        /// </summary>171        public event EventHandler<WorkerEventArgs> WorkerDestroyed;172        /// <summary>173        /// Raised when the page closes.174        /// </summary>175        public event EventHandler Close;176        /// <summary>177        /// This setting will change the default maximum navigation time of 30 seconds for the following methods:178        /// - <see cref="GoToAsync(string, NavigationOptions)"/>179        /// - <see cref="GoBackAsync(NavigationOptions)"/>180        /// - <see cref="GoForwardAsync(NavigationOptions)"/>181        /// - <see cref="ReloadAsync(NavigationOptions)"/>182        /// - <see cref="WaitForNavigationAsync(NavigationOptions)"/>183        /// </summary>184        public int DefaultNavigationTimeout185        {186            get => _frameManager.DefaultNavigationTimeout;187            set => _frameManager.DefaultNavigationTimeout = value;188        }189        /// <summary>190        /// This setting will change the default maximum navigation time of 30 seconds for the following methods:191        /// - <see cref="WaitForOptions"/>192        /// </summary>193        public int DefaultWaitForTimeout { get; set; } = 30000;194        /// <summary>195        /// Gets page's main frame196        /// </summary>197        /// <remarks>198        /// Page is guaranteed to have a main frame which persists during navigations.199        /// </remarks>200        public Frame MainFrame => _frameManager.MainFrame;201        /// <summary>202        /// Gets all frames attached to the page.203        /// </summary>204        /// <value>An array of all frames attached to the page.</value>205        public Frame[] Frames => _frameManager.Frames.Values.ToArray();206        /// <summary>207        /// Gets all workers in the page.208        /// </summary>209        public Worker[] Workers => _workers.Values.ToArray();210        /// <summary>211        /// Shortcut for <c>page.MainFrame.Url</c>212        /// </summary>213        public string Url => MainFrame.Url;214        /// <summary>215        /// Gets that target this page was created from.216        /// </summary>217        public Target Target { get; }218        /// <summary>219        /// Gets this page's keyboard220        /// </summary>221        public Keyboard Keyboard { get; }222        /// <summary>223        /// Gets this page's touchscreen224        /// </summary>225        public Touchscreen Touchscreen { get; }226        /// <summary>227        /// Gets this page's coverage228        /// </summary>229        public Coverage Coverage { get; }230        /// <summary>231        /// Gets this page's tracing232        /// </summary>233        public Tracing Tracing { get; }234        /// <summary>235        /// Gets this page's mouse236        /// </summary>237        public Mouse Mouse { get; }238        /// <summary>239        /// Gets this page's viewport240        /// </summary>241        public ViewPortOptions Viewport { get; private set; }242        /// <summary>243        /// List of supported metrics provided by the <see cref="Metrics"/> event.244        /// </summary>245        public static readonly IEnumerable<string> SupportedMetrics = new List<string>246        {247            "Timestamp",248            "Documents",249            "Frames",250            "JSEventListeners",251            "Nodes",252            "LayoutCount",253            "RecalcStyleCount",254            "LayoutDuration",255            "RecalcStyleDuration",256            "ScriptDuration",257            "TaskDuration",258            "JSHeapUsedSize",259            "JSHeapTotalSize"260        };261        /// <summary>262        /// Get the browser the page belongs to.263        /// </summary>264        public Browser Browser => Target.Browser;265        /// <summary>266        /// Get an indication that the page has been closed.267        /// </summary>268        public bool IsClosed { get; private set; }269        internal bool JavascriptEnabled { get; set; } = true;270        #endregion271        #region Public Methods272        /// <summary>273        /// Sets the page's geolocation.274        /// </summary>275        /// <returns>The task.</returns>276        /// <param name="options">Geolocation options.</param>277        /// <remarks>278        /// Consider using <seealso cref="BrowserContext.OverridePermissionsAsync(string, IEnumerable{OverridePermission})"/> to grant permissions for the page to read its geolocation.279        /// </remarks>280        public Task SetGeolocationAsync(GeolocationOption options)281        {282            if (options.Longitude < -180 || options.Longitude > 180)283            {284                throw new ArgumentException($"Invalid longitude '{ options.Longitude }': precondition - 180 <= LONGITUDE <= 180 failed.");285            }286            if (options.Latitude < -90 || options.Latitude > 90)287            {288                throw new ArgumentException($"Invalid latitude '{ options.Latitude }': precondition - 90 <= LATITUDE <= 90 failed.");289            }290            if (options.Accuracy < 0)291            {292                throw new ArgumentException($"Invalid accuracy '{options.Accuracy}': precondition 0 <= ACCURACY failed.");293            }294            return Client.SendAsync("Emulation.setGeolocationOverride", options);295        }296        /// <summary>297        /// Returns metrics298        /// </summary>299        /// <returns>Task which resolves into a list of metrics</returns>300        /// <remarks>301        /// All timestamps are in monotonic time: monotonically increasing time in seconds since an arbitrary point in the past.302        /// </remarks>303        public async Task<Dictionary<string, decimal>> MetricsAsync()304        {305            var response = await Client.SendAsync<PerformanceGetMetricsResponse>("Performance.getMetrics").ConfigureAwait(false);306            return BuildMetricsObject(response.Metrics);307        }308        /// <summary>309        /// 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.310        /// </summary>311        /// <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>312        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>313        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully tapped</returns>314        public async Task TapAsync(string selector)315        {316            var handle = await QuerySelectorAsync(selector).ConfigureAwait(false);317            if (handle == null)318            {319                throw new SelectorException($"No node found for selector: {selector}", selector);320            }321            await handle.TapAsync().ConfigureAwait(false);322            await handle.DisposeAsync().ConfigureAwait(false);323        }324        /// <summary>325        /// The method runs <c>document.querySelector</c> within the page. If no element matches the selector, the return value resolve to <c>null</c>.326        /// </summary>327        /// <param name="selector">A selector to query page for</param>328        /// <returns>Task which resolves to <see cref="ElementHandle"/> pointing to the frame element</returns>329        /// <remarks>330        /// Shortcut for <c>page.MainFrame.QuerySelectorAsync(selector)</c>331        /// </remarks>332        /// <seealso cref="Frame.QuerySelectorAsync(string)"/>333        public Task<ElementHandle> QuerySelectorAsync(string selector)334            => MainFrame.QuerySelectorAsync(selector);335        /// <summary>336        /// Runs <c>document.querySelectorAll</c> within the page. If no elements match the selector, the return value resolve to <see cref="Array.Empty{T}"/>.337        /// </summary>338        /// <param name="selector">A selector to query page for</param>339        /// <returns>Task which resolves to ElementHandles pointing to the frame elements</returns>340        /// <seealso cref="Frame.QuerySelectorAllAsync(string)"/>341        public Task<ElementHandle[]> QuerySelectorAllAsync(string selector)342            => MainFrame.QuerySelectorAllAsync(selector);343        /// <summary>344        /// A utility function to be used with <see cref="Extensions.EvaluateFunctionAsync{T}(Task{JSHandle}, string, object[])"/>345        /// </summary>346        /// <param name="selector">A selector to query page for</param>347        /// <returns>Task which resolves to a <see cref="JSHandle"/> of <c>document.querySelectorAll</c> result</returns>348        public Task<JSHandle> QuerySelectorAllHandleAsync(string selector)349            => EvaluateFunctionHandleAsync("selector => Array.from(document.querySelectorAll(selector))", selector);350        /// <summary>351        /// Evaluates the XPath expression352        /// </summary>353        /// <param name="expression">Expression to evaluate <see href="https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate"/></param>354        /// <returns>Task which resolves to an array of <see cref="ElementHandle"/></returns>355        /// <remarks>356        /// Shortcut for <c>page.MainFrame.XPathAsync(expression)</c>357        /// </remarks>358        /// <seealso cref="Frame.XPathAsync(string)"/>359        public Task<ElementHandle[]> XPathAsync(string expression) => MainFrame.XPathAsync(expression);360        /// <summary>361        /// Executes a script in browser context362        /// </summary>363        /// <param name="script">Script to be evaluated in browser context</param>364        /// <remarks>365        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.366        /// </remarks>367        /// <returns>Task which resolves to script return value</returns>368        public async Task<JSHandle> EvaluateExpressionHandleAsync(string script)369        {370            var context = await MainFrame.GetExecutionContextAsync().ConfigureAwait(false);371            return await context.EvaluateExpressionHandleAsync(script).ConfigureAwait(false);372        }373        /// <summary>374        /// Executes a script in browser context375        /// </summary>376        /// <param name="pageFunction">Script to be evaluated in browser context</param>377        /// <param name="args">Function arguments</param>378        /// <remarks>379        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.380        /// <see cref="JSHandle"/> instances can be passed as arguments381        /// </remarks>382        /// <returns>Task which resolves to script return value</returns>383        public async Task<JSHandle> EvaluateFunctionHandleAsync(string pageFunction, params object[] args)384        {385            var context = await MainFrame.GetExecutionContextAsync().ConfigureAwait(false);386            return await context.EvaluateFunctionHandleAsync(pageFunction, args).ConfigureAwait(false);387        }388        /// <summary>389        /// Adds a function which would be invoked in one of the following scenarios:390        /// - whenever the page is navigated391        /// - whenever the child frame is attached or navigated. In this case, the function is invoked in the context of the newly attached frame392        /// </summary>393        /// <param name="pageFunction">Function to be evaluated in browser context</param>394        /// <param name="args">Arguments to pass to <c>pageFunction</c></param>395        /// <remarks>396        /// 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>.397        /// </remarks>398        /// <example>399        /// An example of overriding the navigator.languages property before the page loads:400        /// <code>401        /// var overrideNavigatorLanguages = @"Object.defineProperty(navigator, 'languages', {402        ///   get: function() {403        ///     return ['en-US', 'en', 'bn'];404        ///   };405        /// });";406        /// await page.EvaluateOnNewDocumentAsync(overrideNavigatorLanguages);407        /// </code>408        /// </example>409        /// <returns>Task</returns>410        public Task EvaluateOnNewDocumentAsync(string pageFunction, params object[] args)411        {412            var source = EvaluationString(pageFunction, args);413            return Client.SendAsync("Page.addScriptToEvaluateOnNewDocument", new { source });414        }415        /// <summary>416        /// The method iterates JavaScript heap and finds all the objects with the given prototype.417        /// Shortcut for <c>page.MainFrame.GetExecutionContextAsync().QueryObjectsAsync(prototypeHandle)</c>.418        /// </summary>419        /// <returns>A task which resolves to a handle to an array of objects with this prototype.</returns>420        /// <param name="prototypeHandle">A handle to the object prototype.</param>421        public async Task<JSHandle> QueryObjectsAsync(JSHandle prototypeHandle)422        {423            var context = await MainFrame.GetExecutionContextAsync().ConfigureAwait(false);424            return await context.QueryObjectsAsync(prototypeHandle).ConfigureAwait(false);425        }426        /// <summary>427        /// Activating request interception enables <see cref="Request.AbortAsync(RequestAbortErrorCode)">request.AbortAsync</see>, 428        /// <see cref="Request.ContinueAsync(Payload)">request.ContinueAsync</see> and <see cref="Request.RespondAsync(ResponseData)">request.RespondAsync</see> methods.429        /// </summary>430        /// <returns>The request interception task.</returns>431        /// <param name="value">Whether to enable request interception..</param>432        public Task SetRequestInterceptionAsync(bool value)433            => _networkManager.SetRequestInterceptionAsync(value);434        /// <summary>435        /// Set offline mode for the page.436        /// </summary>437        /// <returns>Result task</returns>438        /// <param name="value">When <c>true</c> enables offline mode for the page.</param>439        public Task SetOfflineModeAsync(bool value) => _networkManager.SetOfflineModeAsync(value);440        /// <summary>441        /// Returns the page's cookies442        /// </summary>443        /// <param name="urls">Url's to return cookies for</param>444        /// <returns>Array of cookies</returns>445        /// <remarks>446        /// If no URLs are specified, this method returns cookies for the current page URL.447        /// If URLs are specified, only cookies for those URLs are returned.448        /// </remarks>449        public async Task<CookieParam[]> GetCookiesAsync(params string[] urls)450        {451            var response = await Client.SendAsync("Network.getCookies", new Dictionary<string, object>452            {453                { MessageKeys.Urls, urls.Length > 0 ? urls : new string[] { Url } }454            }).ConfigureAwait(false);455            return response[MessageKeys.Cookies].ToObject<CookieParam[]>();456        }457        /// <summary>458        /// Clears all of the current cookies and then sets the cookies for the page459        /// </summary>460        /// <param name="cookies">Cookies to set</param>461        /// <returns>Task</returns>462        public async Task SetCookieAsync(params CookieParam[] cookies)463        {464            foreach (var cookie in cookies)465            {466                if (string.IsNullOrEmpty(cookie.Url) && Url.StartsWith("http", StringComparison.Ordinal))467                {468                    cookie.Url = Url;469                }470                if (cookie.Url == "about:blank")471                {472                    throw new PuppeteerException($"Blank page can not have cookie \"{cookie.Name}\"");473                }474            }475            await DeleteCookieAsync(cookies).ConfigureAwait(false);476            if (cookies.Length > 0)477            {478                await Client.SendAsync("Network.setCookies", new Dictionary<string, object>479                {480                    { MessageKeys.Cookies, cookies }481                }).ConfigureAwait(false);482            }483        }484        /// <summary>485        /// Deletes cookies from the page486        /// </summary>487        /// <param name="cookies">Cookies to delete</param>488        /// <returns>Task</returns>489        public async Task DeleteCookieAsync(params CookieParam[] cookies)490        {491            var pageURL = Url;492            foreach (var cookie in cookies)493            {494                if (string.IsNullOrEmpty(cookie.Url) && pageURL.StartsWith("http", StringComparison.Ordinal))495                {496                    cookie.Url = pageURL;497                }498                await Client.SendAsync("Network.deleteCookies", cookie).ConfigureAwait(false);499            }500        }501        /// <summary>502        /// Adds a <c><![CDATA[<script>]]></c> tag into the page with the desired url or content503        /// </summary>504        /// <param name="options">add script tag options</param>505        /// <remarks>506        /// Shortcut for <c>page.MainFrame.AddScriptTagAsync(options)</c>507        /// </remarks>508        /// <returns>Task which resolves to the added tag when the script's onload fires or when the script content was injected into frame</returns>509        /// <seealso cref="Frame.AddScriptTag(AddTagOptions)"/>510        public Task<ElementHandle> AddScriptTagAsync(AddTagOptions options) => MainFrame.AddScriptTag(options);511        /// <summary>512        /// Adds a <c><![CDATA[<script>]]></c> tag into the page with the desired url or content513        /// </summary>514        /// <param name="url">script url</param>515        /// <remarks>516        /// Shortcut for <c>page.MainFrame.AddScriptTagAsync(new AddTagOptions { Url = url })</c>517        /// </remarks>518        /// <returns>Task which resolves to the added tag when the script's onload fires or when the script content was injected into frame</returns>519        public Task<ElementHandle> AddScriptTagAsync(string url) => AddScriptTagAsync(new AddTagOptions { Url = url });520        /// <summary>521        /// 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 content522        /// </summary>523        /// <param name="options">add style tag options</param>524        /// <remarks>525        /// Shortcut for <c>page.MainFrame.AddStyleTagAsync(options)</c>526        /// </remarks>527        /// <returns>Task which resolves to the added tag when the stylesheet's onload fires or when the CSS content was injected into frame</returns>528        /// <seealso cref="Frame.AddStyleTag(AddTagOptions)"/>529        public Task<ElementHandle> AddStyleTagAsync(AddTagOptions options) => MainFrame.AddStyleTag(options);530        /// <summary>531        /// 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 content532        /// </summary>533        /// <param name="url">stylesheel url</param>534        /// <remarks>535        /// Shortcut for <c>page.MainFrame.AddStyleTagAsync(new AddTagOptions { Url = url })</c>536        /// </remarks>537        /// <returns>Task which resolves to the added tag when the stylesheet's onload fires or when the CSS content was injected into frame</returns>538        public Task<ElementHandle> AddStyleTagAsync(string url) => AddStyleTagAsync(new AddTagOptions { Url = url });539        /// <summary>540        /// Adds a function called <c>name</c> on the page's <c>window</c> object.541        /// When called, the function executes <paramref name="puppeteerFunction"/> in C# and returns a <see cref="Task"/> which resolves when <paramref name="puppeteerFunction"/> completes.542        /// </summary>543        /// <param name="name">Name of the function on the window object</param>544        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>545        /// <remarks>546        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.547        /// Functions installed via <see cref="ExposeFunctionAsync(string, Action)"/> survive navigations548        /// </remarks>549        /// <returns>Task</returns>550        public Task ExposeFunctionAsync(string name, Action puppeteerFunction)551            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);552        /// <summary>553        /// Adds a function called <c>name</c> on the page's <c>window</c> object.554        /// 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"/>.555        /// </summary>556        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>557        /// <param name="name">Name of the function on the window object</param>558        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>559        /// <remarks>560        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.561        /// Functions installed via <see cref="ExposeFunctionAsync{TResult}(string, Func{TResult})"/> survive navigations562        /// </remarks>563        /// <returns>Task</returns>564        public Task ExposeFunctionAsync<TResult>(string name, Func<TResult> puppeteerFunction)565            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);566        /// <summary>567        /// Adds a function called <c>name</c> on the page's <c>window</c> object.568        /// 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"/>.569        /// </summary>570        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>571        /// <typeparam name="T">The parameter of <paramref name="puppeteerFunction"/></typeparam>572        /// <param name="name">Name of the function on the window object</param>573        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>574        /// <remarks>575        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.576        /// Functions installed via <see cref="ExposeFunctionAsync{T, TResult}(string, Func{T, TResult})"/> survive navigations577        /// </remarks>578        /// <returns>Task</returns>579        public Task ExposeFunctionAsync<T, TResult>(string name, Func<T, TResult> puppeteerFunction)580            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);581        /// <summary>582        /// Adds a function called <c>name</c> on the page's <c>window</c> object.583        /// 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"/>.584        /// </summary>585        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>586        /// <typeparam name="T1">The first parameter of <paramref name="puppeteerFunction"/></typeparam>587        /// <typeparam name="T2">The second parameter of <paramref name="puppeteerFunction"/></typeparam>588        /// <param name="name">Name of the function on the window object</param>589        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>590        /// <remarks>591        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.592        /// Functions installed via <see cref="ExposeFunctionAsync{T1, T2, TResult}(string, Func{T1, T2, TResult})"/> survive navigations593        /// </remarks>594        /// <returns>Task</returns>595        public Task ExposeFunctionAsync<T1, T2, TResult>(string name, Func<T1, T2, TResult> puppeteerFunction)596            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);597        /// <summary>598        /// Adds a function called <c>name</c> on the page's <c>window</c> object.599        /// 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"/>.600        /// </summary>601        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>602        /// <typeparam name="T1">The first parameter of <paramref name="puppeteerFunction"/></typeparam>603        /// <typeparam name="T2">The second parameter of <paramref name="puppeteerFunction"/></typeparam>604        /// <typeparam name="T3">The third parameter of <paramref name="puppeteerFunction"/></typeparam>605        /// <param name="name">Name of the function on the window object</param>606        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>607        /// <remarks>608        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.609        /// Functions installed via <see cref="ExposeFunctionAsync{T1, T2, T3, TResult}(string, Func{T1, T2, T3, TResult})"/> survive navigations610        /// </remarks>611        /// <returns>Task</returns>612        public Task ExposeFunctionAsync<T1, T2, T3, TResult>(string name, Func<T1, T2, T3, TResult> puppeteerFunction)613            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);614        /// <summary>615        /// Adds a function called <c>name</c> on the page's <c>window</c> object.616        /// 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"/>.617        /// </summary>618        /// <typeparam name="TResult">The result of <paramref name="puppeteerFunction"/></typeparam>619        /// <typeparam name="T1">The first parameter of <paramref name="puppeteerFunction"/></typeparam>620        /// <typeparam name="T2">The second parameter of <paramref name="puppeteerFunction"/></typeparam>621        /// <typeparam name="T3">The third parameter of <paramref name="puppeteerFunction"/></typeparam>622        /// <typeparam name="T4">The fourth parameter of <paramref name="puppeteerFunction"/></typeparam>623        /// <param name="name">Name of the function on the window object</param>624        /// <param name="puppeteerFunction">Callback function which will be called in Puppeteer's context.</param>625        /// <remarks>626        /// If the <paramref name="puppeteerFunction"/> returns a <see cref="Task"/>, it will be awaited.627        /// Functions installed via <see cref="ExposeFunctionAsync{T1, T2, T3, T4, TResult}(string, Func{T1, T2, T3, T4, TResult})"/> survive navigations628        /// </remarks>629        /// <returns>Task</returns>630        public Task ExposeFunctionAsync<T1, T2, T3, T4, TResult>(string name, Func<T1, T2, T3, T4, TResult> puppeteerFunction)631            => ExposeFunctionAsync(name, (Delegate)puppeteerFunction);632        /// <summary>633        /// Gets the full HTML contents of the page, including the doctype.634        /// </summary>635        /// <returns>Task which resolves to the HTML content.</returns>636        /// <seealso cref="Frame.GetContentAsync"/>637        public Task<string> GetContentAsync() => _frameManager.MainFrame.GetContentAsync();638        /// <summary>639        /// Sets the HTML markup to the page640        /// </summary>641        /// <param name="html">HTML markup to assign to the page.</param>642        /// <returns>Task.</returns>643        /// <seealso cref="Frame.SetContentAsync(string)"/>644        public Task SetContentAsync(string html) => _frameManager.MainFrame.SetContentAsync(html);645        /// <summary>646        /// Navigates to an url647        /// </summary>        648        /// <param name="url">URL to navigate page to. The url should include scheme, e.g. https://.</param>649        /// <param name="options">Navigation parameters.</param>650        /// <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>651        /// <seealso cref="GoToAsync(string, int?, WaitUntilNavigation[])"/>652        public Task<Response> GoToAsync(string url, NavigationOptions options) => _frameManager.MainFrame.GoToAsync(url, options);653        /// <summary>654        /// Navigates to an url655        /// </summary>656        /// <param name="url">URL to navigate page to. The url should include scheme, e.g. https://.</param>657        /// <param name="timeout">Maximum navigation time in milliseconds, defaults to 30 seconds, pass <c>0</c> to disable timeout. </param>658        /// <param name="waitUntil">When to consider navigation succeeded, defaults to <see cref="WaitUntilNavigation.Load"/>. Given an array of <see cref="WaitUntilNavigation"/>, navigation is considered to be successful after all events have been fired</param>659        /// <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>660        /// <seealso cref="GoToAsync(string, NavigationOptions)"/>661        public Task<Response> GoToAsync(string url, int? timeout = null, WaitUntilNavigation[] waitUntil = null)662            => GoToAsync(url, new NavigationOptions { Timeout = timeout, WaitUntil = waitUntil });663        /// <summary>664        /// Navigates to an url665        /// </summary>666        /// <param name="url">URL to navigate page to. The url should include scheme, e.g. https://.</param>667        /// <param name="waitUntil">When to consider navigation succeeded.</param>668        /// <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>669        /// <seealso cref="GoToAsync(string, NavigationOptions)"/>670        public Task<Response> GoToAsync(string url, WaitUntilNavigation waitUntil)671            => GoToAsync(url, new NavigationOptions { WaitUntil = new[] { waitUntil } });672        /// <summary>673        /// 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"/>674        /// </summary>675        /// <param name="file">The file path to save the PDF to. paths are resolved using <see cref="Path.GetFullPath(string)"/></param>676        /// <returns></returns>677        /// <remarks>678        /// Generating a pdf is currently only supported in Chrome headless679        /// </remarks>680        public Task PdfAsync(string file) => PdfAsync(file, new PdfOptions());681        /// <summary>682        ///  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"/>683        /// </summary>684        /// <param name="file">The file path to save the PDF to. paths are resolved using <see cref="Path.GetFullPath(string)"/></param>685        /// <param name="options">pdf options</param>686        /// <returns></returns>687        /// <remarks>688        /// Generating a pdf is currently only supported in Chrome headless689        /// </remarks>690        public async Task PdfAsync(string file, PdfOptions options)691        {692            var data = await PdfDataAsync(options).ConfigureAwait(false);693            using (var fs = AsyncFileHelper.CreateStream(file, FileMode.Create))694            {695                await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false);696            }697        }698        /// <summary>699        /// 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"/>700        /// </summary>701        /// <returns>Task which resolves to a <see cref="Stream"/> containing the PDF data.</returns>702        /// <remarks>703        /// Generating a pdf is currently only supported in Chrome headless704        /// </remarks>705        public Task<Stream> PdfStreamAsync() => PdfStreamAsync(new PdfOptions());706        /// <summary>707        /// 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"/>708        /// </summary>709        /// <param name="options">pdf options</param>710        /// <returns>Task which resolves to a <see cref="Stream"/> containing the PDF data.</returns>711        /// <remarks>712        /// Generating a pdf is currently only supported in Chrome headless713        /// </remarks>714        public async Task<Stream> PdfStreamAsync(PdfOptions options)715            => new MemoryStream(await PdfDataAsync(options).ConfigureAwait(false));716        /// <summary>717        /// 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"/>718        /// </summary>719        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the PDF data.</returns>720        /// <remarks>721        /// Generating a pdf is currently only supported in Chrome headless722        /// </remarks>723        public Task<byte[]> PdfDataAsync() => PdfDataAsync(new PdfOptions());724        /// <summary>725        /// 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"/>726        /// </summary>727        /// <param name="options">pdf options</param>728        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the PDF data.</returns>729        /// <remarks>730        /// Generating a pdf is currently only supported in Chrome headless731        /// </remarks>732        public async Task<byte[]> PdfDataAsync(PdfOptions options)733        {734            var paperWidth = PaperFormat.Letter.Width;735            var paperHeight = PaperFormat.Letter.Height;736            if (options.Format != null)737            {738                paperWidth = options.Format.Width;739                paperHeight = options.Format.Height;740            }741            else742            {743                if (options.Width != null)744                {745                    paperWidth = ConvertPrintParameterToInches(options.Width);746                }747                if (options.Height != null)748                {749                    paperHeight = ConvertPrintParameterToInches(options.Height);750                }751            }752            var marginTop = ConvertPrintParameterToInches(options.MarginOptions.Top);753            var marginLeft = ConvertPrintParameterToInches(options.MarginOptions.Left);754            var marginBottom = ConvertPrintParameterToInches(options.MarginOptions.Bottom);755            var marginRight = ConvertPrintParameterToInches(options.MarginOptions.Right);756            var result = await Client.SendAsync("Page.printToPDF", new757            {758                landscape = options.Landscape,759                displayHeaderFooter = options.DisplayHeaderFooter,760                headerTemplate = options.HeaderTemplate,761                footerTemplate = options.FooterTemplate,762                printBackground = options.PrintBackground,763                scale = options.Scale,764                paperWidth,765                paperHeight,766                marginTop,767                marginBottom,768                marginLeft,769                marginRight,770                pageRanges = options.PageRanges,771                preferCSSPageSize = options.PreferCSSPageSize772            }).ConfigureAwait(false);773            var buffer = Convert.FromBase64String(result.GetValue(MessageKeys.Data).AsString());774            return buffer;775        }776        /// <summary>777        /// Enables/Disables Javascript on the page778        /// </summary>779        /// <returns>Task.</returns>780        /// <param name="enabled">Whether or not to enable JavaScript on the page.</param>781        public Task SetJavaScriptEnabledAsync(bool enabled)782        {783            if (enabled == JavascriptEnabled)784            {785                return Task.CompletedTask;786            }787            JavascriptEnabled = enabled;788            return Client.SendAsync("Emulation.setScriptExecutionDisabled", new { value = !enabled });789        }790        /// <summary>791        /// Toggles bypassing page's Content-Security-Policy.792        /// </summary>793        /// <param name="enabled">sets bypassing of page's Content-Security-Policy.</param>794        /// <returns></returns>795        /// <remarks>796        /// CSP bypassing happens at the moment of CSP initialization rather then evaluation.797        /// Usually this means that <see cref="SetBypassCSPAsync(bool)"/> should be called before navigating to the domain.798        /// </remarks>799        public Task SetBypassCSPAsync(bool enabled) => Client.SendAsync("Page.setBypassCSP", new { enabled });800        /// <summary>801        /// Emulates a media such as screen or print.802        /// </summary>803        /// <returns>Task.</returns>804        /// <param name="media">Media to set.</param>805        public Task EmulateMediaAsync(MediaType media)806            => Client.SendAsync("Emulation.setEmulatedMedia", new { media });807        /// <summary>808        /// Sets the viewport.809        /// In the case of multiple pages in a single browser, each page can have its own viewport size.810        /// NOTE in certain cases, setting viewport will reload the page in order to set the isMobile or hasTouch properties.811        /// </summary>812        /// <returns>The viewport task.</returns>813        /// <param name="viewport">Viewport options.</param>814        public async Task SetViewportAsync(ViewPortOptions viewport)815        {816            var needsReload = await _emulationManager.EmulateViewport(viewport).ConfigureAwait(false);817            Viewport = viewport;818            if (needsReload)819            {820                await ReloadAsync().ConfigureAwait(false);821            }822        }823        /// <summary>824        /// Emulates given device metrics and user agent. 825        /// </summary>826        /// <remarks>827        /// This method is a shortcut for calling two methods:828        /// page.SetViewportAsync(userAgent)829        /// page.SetUserAgentAsync(viewport)830        /// </remarks>831        /// <returns>Task.</returns>832        /// <param name="options">Emulation options.</param>833        public Task EmulateAsync(DeviceDescriptor options) => Task.WhenAll(834            SetViewportAsync(options.ViewPort),835            SetUserAgentAsync(options.UserAgent)836        );837        /// <summary>838        /// Takes a screenshot of the page839        /// </summary>840        /// <returns>The screenshot task.</returns>841        /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension. 842        /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided, 843        /// the image won't be saved to the disk.</param>844        public Task ScreenshotAsync(string file) => ScreenshotAsync(file, new ScreenshotOptions());845        /// <summary>846        /// Takes a screenshot of the page847        /// </summary>848        /// <returns>The screenshot task.</returns>849        /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension. 850        /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided, 851        /// the image won't be saved to the disk.</param>852        /// <param name="options">Screenshot options.</param>853        public async Task ScreenshotAsync(string file, ScreenshotOptions options)854        {855            if (!options.Type.HasValue)856            {857                options.Type = ScreenshotOptions.GetScreenshotTypeFromFile(file);858            }859            var data = await ScreenshotDataAsync(options).ConfigureAwait(false);860            using (var fs = AsyncFileHelper.CreateStream(file, FileMode.Create))861            {862                await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false);863            }864        }865        /// <summary>866        /// Takes a screenshot of the page867        /// </summary>868        /// <returns>Task which resolves to a <see cref="Stream"/> containing the image data.</returns>869        public Task<Stream> ScreenshotStreamAsync() => ScreenshotStreamAsync(new ScreenshotOptions());870        /// <summary>871        /// Takes a screenshot of the page872        /// </summary>873        /// <returns>Task which resolves to a <see cref="Stream"/> containing the image data.</returns>874        /// <param name="options">Screenshot options.</param>875        public async Task<Stream> ScreenshotStreamAsync(ScreenshotOptions options)876            => new MemoryStream(await ScreenshotDataAsync(options).ConfigureAwait(false));877        /// <summary>878        /// Takes a screenshot of the page879        /// </summary>880        /// <returns>Task which resolves to a <see cref="string"/> containing the image data as base64.</returns>881        public Task<string> ScreenshotBase64Async() => ScreenshotBase64Async(new ScreenshotOptions());882        /// <summary>883        /// Takes a screenshot of the page884        /// </summary>885        /// <returns>Task which resolves to a <see cref="string"/> containing the image data as base64.</returns>886        /// <param name="options">Screenshot options.</param>887        public Task<string> ScreenshotBase64Async(ScreenshotOptions options)888        {889            var screenshotType = options.Type;890            if (!screenshotType.HasValue)891            {892                screenshotType = ScreenshotType.Png;893            }894            if (options.Quality.HasValue)895            {896                if (screenshotType != ScreenshotType.Jpeg)897                {898                    throw new ArgumentException($"options.Quality is unsupported for the {screenshotType} screenshots");899                }900                if (options.Quality < 0 || options.Quality > 100)901                {902                    throw new ArgumentException($"Expected options.quality to be between 0 and 100 (inclusive), got {options.Quality}");903                }904            }905            if (options.Clip != null && options.FullPage)906            {907                throw new ArgumentException("options.clip and options.fullPage are exclusive");908            }909            return _screenshotTaskQueue.Enqueue(() => PerformScreenshot(screenshotType.Value, options));910        }911        /// <summary>912        /// Takes a screenshot of the page913        /// </summary>914        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>915        public Task<byte[]> ScreenshotDataAsync() => ScreenshotDataAsync(new ScreenshotOptions());916        /// <summary>917        /// Takes a screenshot of the page918        /// </summary>919        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>920        /// <param name="options">Screenshot options.</param>921        public async Task<byte[]> ScreenshotDataAsync(ScreenshotOptions options)922            => Convert.FromBase64String(await ScreenshotBase64Async(options).ConfigureAwait(false));923        /// <summary>924        /// Returns page's title925        /// </summary>926        /// <returns>page's title</returns>927        /// <see cref="Frame.GetTitleAsync"/>928        public Task<string> GetTitleAsync() => MainFrame.GetTitleAsync();929        /// <summary>930        /// Closes the page.931        /// </summary>932        /// <returns>Task.</returns>933        public Task CloseAsync(PageCloseOptions options = null)934        {935            if (!(Client?.Connection?.IsClosed ?? true))936            {937                var runBeforeUnload = options?.RunBeforeUnload ?? false;938                if (runBeforeUnload)939                {940                    return Client.SendAsync("Page.close");941                }942                else943                {944                    return Client.Connection.SendAsync("Target.closeTarget", new945                    {946                        targetId = Target.TargetId947                    }).ContinueWith((task) => Target.CloseTask);948                }949            }950            _logger.LogWarning("Protocol error: Connection closed. Most likely the page has been closed.");951            return Task.CompletedTask;952        }953        /// <summary>954        /// Toggles ignoring cache for each request based on the enabled state. By default, caching is enabled.955        /// </summary>956        /// <param name="enabled">sets the <c>enabled</c> state of the cache</param>957        /// <returns>Task</returns>958        public Task SetCacheEnabledAsync(bool enabled = true)959            => Client.SendAsync("Network.setCacheDisabled", new { cacheDisabled = !enabled });960        /// <summary>961        /// 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.962        /// </summary>963        /// <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>964        /// <param name="options">click options</param>965        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>966        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully clicked</returns>967        public async Task ClickAsync(string selector, ClickOptions options = null)968        {969            var handle = await QuerySelectorAsync(selector).ConfigureAwait(false);970            if (handle == null)971            {972                throw new SelectorException($"No node found for selector: {selector}", selector);973            }974            await handle.ClickAsync(options).ConfigureAwait(false);975            await handle.DisposeAsync().ConfigureAwait(false);976        }977        /// <summary>978        /// 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.979        /// </summary>980        /// <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>981        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>982        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully hovered</returns>983        public async Task HoverAsync(string selector)984        {985            var handle = await QuerySelectorAsync(selector).ConfigureAwait(false);986            if (handle == null)987            {988                throw new SelectorException($"No node found for selector: {selector}", selector);989            }990            await handle.HoverAsync().ConfigureAwait(false);991            await handle.DisposeAsync().ConfigureAwait(false);992        }993        /// <summary>994        /// Fetches an element with <paramref name="selector"/> and focuses it995        /// </summary>996        /// <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>997        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>998        /// <returns>Task which resolves when the element matching <paramref name="selector"/> is successfully focused</returns>999        public async Task FocusAsync(string selector)1000        {1001            var handle = await QuerySelectorAsync(selector).ConfigureAwait(false);1002            if (handle == null)1003            {1004                throw new SelectorException($"No node found for selector: {selector}", selector);1005            }1006            await handle.FocusAsync().ConfigureAwait(false);1007            await handle.DisposeAsync().ConfigureAwait(false);1008        }1009        /// <summary>1010        /// Executes a script in browser context1011        /// </summary>1012        /// <param name="script">Script to be evaluated in browser context</param>1013        /// <remarks>1014        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.1015        /// </remarks>1016        /// <seealso cref="EvaluateFunctionAsync{T}(string, object[])"/>1017        /// <returns>Task which resolves to script return value</returns>1018        public Task<JToken> EvaluateExpressionAsync(string script)1019            => _frameManager.MainFrame.EvaluateExpressionAsync<JToken>(script);1020        /// <summary>1021        /// Executes a script in browser context1022        /// </summary>1023        /// <typeparam name="T">The type to deserialize the result to</typeparam>1024        /// <param name="script">Script to be evaluated in browser context</param>1025        /// <remarks>1026        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.1027        /// </remarks>1028        /// <seealso cref="EvaluateFunctionAsync{T}(string, object[])"/>1029        /// <returns>Task which resolves to script return value</returns>1030        public Task<T> EvaluateExpressionAsync<T>(string script)1031            => _frameManager.MainFrame.EvaluateExpressionAsync<T>(script);1032        /// <summary>1033        /// Executes a function in browser context1034        /// </summary>1035        /// <param name="script">Script to be evaluated in browser context</param>1036        /// <param name="args">Arguments to pass to script</param>1037        /// <remarks>1038        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.1039        /// <see cref="JSHandle"/> instances can be passed as arguments1040        /// </remarks>1041        /// <seealso cref="EvaluateExpressionAsync{T}(string)"/>1042        /// <returns>Task which resolves to script return value</returns>1043        public Task<JToken> EvaluateFunctionAsync(string script, params object[] args)1044            => _frameManager.MainFrame.EvaluateFunctionAsync<JToken>(script, args);1045        /// <summary>1046        /// Executes a function in browser context1047        /// </summary>1048        /// <typeparam name="T">The type to deserialize the result to</typeparam>1049        /// <param name="script">Script to be evaluated in browser context</param>1050        /// <param name="args">Arguments to pass to script</param>1051        /// <remarks>1052        /// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.1053        /// <see cref="JSHandle"/> instances can be passed as arguments1054        /// </remarks>1055        /// <seealso cref="EvaluateExpressionAsync{T}(string)"/>1056        /// <returns>Task which resolves to script return value</returns>1057        public Task<T> EvaluateFunctionAsync<T>(string script, params object[] args)1058            => _frameManager.MainFrame.EvaluateFunctionAsync<T>(script, args);1059        /// <summary>1060        /// Sets the user agent to be used in this page1061        /// </summary>1062        /// <param name="userAgent">Specific user agent to use in this page</param>1063        /// <returns>Task</returns>1064        public Task SetUserAgentAsync(string userAgent)1065            => _networkManager.SetUserAgentAsync(userAgent);1066        /// <summary>1067        /// Sets extra HTTP headers that will be sent with every request the page initiates1068        /// </summary>1069        /// <param name="headers">Additional http headers to be sent with every request</param>1070        /// <returns>Task</returns>1071        public Task SetExtraHttpHeadersAsync(Dictionary<string, string> headers)1072            => _networkManager.SetExtraHTTPHeadersAsync(headers);1073        /// <summary>1074        /// Provide credentials for http authentication <see href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication"/>1075        /// </summary>1076        /// <param name="credentials">The credentials</param>1077        /// <returns></returns>1078        /// <remarks>1079        /// To disable authentication, pass <c>null</c>1080        /// </remarks>1081        public Task AuthenticateAsync(Credentials credentials) => _networkManager.AuthenticateAsync(credentials);1082        /// <summary>1083        /// Reloads the page1084        /// </summary>1085        /// <param name="options">Navigation options</param>1086        /// <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>1087        /// <seealso cref="ReloadAsync(int?, WaitUntilNavigation[])"/>1088        public async Task<Response> ReloadAsync(NavigationOptions options)1089        {1090            var navigationTask = WaitForNavigationAsync(options);1091            await Task.WhenAll(1092              navigationTask,1093              Client.SendAsync("Page.reload")1094            ).ConfigureAwait(false);1095            return navigationTask.Result;1096        }1097        /// <summary>1098        /// Reloads the page1099        /// </summary>1100        /// <param name="timeout">Maximum navigation time in milliseconds, defaults to 30 seconds, pass <c>0</c> to disable timeout. </param>1101        /// <param name="waitUntil">When to consider navigation succeeded, defaults to <see cref="WaitUntilNavigation.Load"/>. Given an array of <see cref="WaitUntilNavigation"/>, navigation is considered to be successful after all events have been fired</param>1102        /// <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>1103        /// <seealso cref="ReloadAsync(NavigationOptions)"/>1104        public Task<Response> ReloadAsync(int? timeout = null, WaitUntilNavigation[] waitUntil = null)1105            => ReloadAsync(new NavigationOptions { Timeout = timeout, WaitUntil = waitUntil });1106        /// <summary>1107        /// Triggers a change and input event once all the provided options have been selected. 1108        /// If there's no <![CDATA[<select>]]> element matching selector, the method throws an error.1109        /// </summary>1110        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>1111        /// <param name="selector">A selector to query page for</param>1112        /// <param name="values">Values of options to select. If the <![CDATA[<select>]]> has the multiple attribute, 1113        /// all values are considered, otherwise only the first one is taken into account.</param>1114        /// <returns>Returns an array of option values that have been successfully selected.</returns>1115        /// <seealso cref="Frame.SelectAsync(string, string[])"/>1116        public Task<string[]> SelectAsync(string selector, params string[] values)1117            => MainFrame.SelectAsync(selector, values);1118        /// <summary>1119        /// Sends a <c>keydown</c>, <c>keypress</c>/<c>input</c>, and <c>keyup</c> event for each character in the text.1120        /// </summary>1121        /// <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>1122        /// <param name="text">A text to type into a focused element</param>1123        /// <param name="options"></param>1124        /// <exception cref="SelectorException">If there's no element matching <paramref name="selector"/></exception>1125        /// <remarks>1126        /// To press a special key, like <c>Control</c> or <c>ArrowDown</c> use <see cref="Keyboard.PressAsync(string, PressOptions)"/>1127        /// </remarks>1128        /// <example>1129        /// <code>1130        /// page.TypeAsync("#mytextarea", "Hello"); // Types instantly1131        /// page.TypeAsync("#mytextarea", "World", new TypeOptions { Delay = 100 }); // Types slower, like a user1132        /// </code>1133        /// </example>1134        /// <returns>Task</returns>1135        public async Task TypeAsync(string selector, string text, TypeOptions options = null)1136        {1137            var handle = await QuerySelectorAsync(selector).ConfigureAwait(false);1138            if (handle == null)1139            {1140                throw new SelectorException($"No node found for selector: {selector}", selector);1141            }1142            await handle.TypeAsync(text, options).ConfigureAwait(false);1143            await handle.DisposeAsync().ConfigureAwait(false);1144        }1145        /// <summary>1146        /// Waits for a timeout1147        /// </summary>1148        /// <param name="milliseconds"></param>1149        /// <returns>A task that resolves when after the timeout</returns>1150        /// <seealso cref="Frame.WaitForTimeoutAsync(int)"/>1151        public Task WaitForTimeoutAsync(int milliseconds)1152            => MainFrame.WaitForTimeoutAsync(milliseconds);1153        /// <summary>1154        /// Waits for a function to be evaluated to a truthy value1155        /// </summary>1156        /// <param name="script">Function to be evaluated in browser context</param>1157        /// <param name="options">Optional waiting parameters</param>1158        /// <param name="args">Arguments to pass to <c>script</c></param>1159        /// <returns>A task that resolves when the <c>script</c> returns a truthy value</returns>1160        /// <seealso cref="Frame.WaitForFunctionAsync(string, WaitForFunctionOptions, object[])"/>1161        public Task<JSHandle> WaitForFunctionAsync(string script, WaitForFunctionOptions options = null, params object[] args)1162            => MainFrame.WaitForFunctionAsync(script, options ?? new WaitForFunctionOptions(), args);1163        /// <summary>1164        /// Waits for a function to be evaluated to a truthy value1165        /// </summary>1166        /// <param name="script">Function to be evaluated in browser context</param>1167        /// <param name="args">Arguments to pass to <c>script</c></param>1168        /// <returns>A task that resolves when the <c>script</c> returns a truthy value</returns>1169        public Task<JSHandle> WaitForFunctionAsync(string script, params object[] args) => WaitForFunctionAsync(script, null, args);1170        /// <summary>1171        /// Waits for an expression to be evaluated to a truthy value1172        /// </summary>1173        /// <param name="script">Expression to be evaluated in browser context</param>1174        /// <param name="options">Optional waiting parameters</param>1175        /// <returns>A task that resolves when the <c>script</c> returns a truthy value</returns>1176        /// <seealso cref="Frame.WaitForExpressionAsync(string, WaitForFunctionOptions)"/>1177        public Task<JSHandle> WaitForExpressionAsync(string script, WaitForFunctionOptions options = null)1178            => MainFrame.WaitForExpressionAsync(script, options ?? new WaitForFunctionOptions());1179        /// <summary>1180        /// Waits for a selector to be added to the DOM1181        /// </summary>1182        /// <param name="selector">A selector of an element to wait for</param>1183        /// <param name="options">Optional waiting parameters</param>1184        /// <returns>A task that resolves when element specified by selector string is added to DOM</returns>1185        /// <seealso cref="WaitForXPathAsync(string, WaitForSelectorOptions)"/>1186        /// <seealso cref="Frame.WaitForSelectorAsync(string, WaitForSelectorOptions)"/>1187        public Task<ElementHandle> WaitForSelectorAsync(string selector, WaitForSelectorOptions options = null)1188            => MainFrame.WaitForSelectorAsync(selector, options ?? new WaitForSelectorOptions());1189        /// <summary>1190        /// Waits for a xpath selector to be added to the DOM1191        /// </summary>1192        /// <param name="xpath">A xpath selector of an element to wait for</param>1193        /// <param name="options">Optional waiting parameters</param>1194        /// <returns>A task that resolves when element specified by selector string is added to DOM</returns>1195        /// <example>1196        /// <code>1197        /// <![CDATA[1198        /// var browser = await Puppeteer.LaunchAsync(new LaunchOptions());1199        /// var page = await browser.NewPageAsync();1200        /// string currentURL = null;1201        /// page1202        ///     .WaitForXPathAsync("//img")1203        ///     .ContinueWith(_ => Console.WriteLine("First URL with image: " + currentURL));1204        /// foreach (var current in new[] { "https://example.com", "https://google.com", "https://bbc.com" })1205        /// {1206        ///     currentURL = current;1207        ///     await page.GoToAsync(currentURL);1208        /// }1209        /// await browser.CloseAsync();1210        /// ]]>1211        /// </code>1212        /// </example>1213        /// <seealso cref="WaitForSelectorAsync(string, WaitForSelectorOptions)"/>1214        /// <seealso cref="Frame.WaitForXPathAsync(string, WaitForSelectorOptions)"/>1215        public Task<ElementHandle> WaitForXPathAsync(string xpath, WaitForSelectorOptions options = null)1216            => MainFrame.WaitForXPathAsync(xpath, options ?? new WaitForSelectorOptions());1217        /// <summary>1218        /// This resolves when the page navigates to a new URL or reloads.1219        /// It is useful for when you run code which will indirectly cause the page to navigate.1220        /// </summary>1221        /// <param name="options">navigation options</param>1222        /// <returns>Task which resolves to the main resource response. 1223        /// In case of multiple redirects, the navigation will resolve with the response of the last redirect.1224        /// In case of navigation to a different anchor or navigation due to History API usage, the navigation will resolve with `null`.1225        /// </returns>1226        /// <remarks>1227        /// Usage of the <c>History API</c> <see href="https://developer.mozilla.org/en-US/docs/Web/API/History_API"/> to change the URL is considered a navigation1228        /// </remarks>1229        /// <example>1230        /// <code>1231        /// <![CDATA[1232        /// var navigationTask = page.WaitForNavigationAsync();1233        /// await page.ClickAsync("a.my-link");1234        /// await navigationTask;1235        /// ]]>1236        /// </code>1237        /// </example>1238        public Task<Response> WaitForNavigationAsync(NavigationOptions options = null) => _frameManager.WaitForFrameNavigationAsync(_frameManager.MainFrame, options);1239        /// <summary>1240        /// Waits for a request.1241        /// </summary>1242        /// <example>1243        /// <code>1244        /// <![CDATA[1245        /// var firstRequest = await page.WaitForRequestAsync("http://example.com/resource");1246        /// return firstRequest.Url;1247        /// ]]>1248        /// </code>1249        /// </example>1250        /// <returns>A task which resolves when a matching request was made.</returns>1251        /// <param name="url">URL to wait for.</param>1252        /// <param name="options">Options.</param>1253        public Task<Request> WaitForRequestAsync(string url, WaitForOptions options = null)1254            => WaitForRequestAsync(request => request.Url == url, options);1255        /// <summary>1256        /// Waits for a request.1257        /// </summary>1258        /// <example>1259        /// <code>1260        /// <![CDATA[1261        /// var request = await page.WaitForRequestAsync(request => request.Url === "http://example.com" && request.Method === HttpMethod.Get;1262        /// return request.Url;1263        /// ]]>1264        /// </code>1265        /// </example>1266        /// <returns>A task which resolves when a matching request was made.</returns>1267        /// <param name="predicate">Function which looks for a matching request.</param>1268        /// <param name="options">Options.</param>1269        public async Task<Request> WaitForRequestAsync(Func<Request, bool> predicate, WaitForOptions options = null)1270        {1271            var timeout = options?.Timeout ?? DefaultWaitForTimeout;1272            var requestTcs = new TaskCompletionSource<Request>();1273            void requestEventListener(object sender, RequestEventArgs e)1274            {1275                if (predicate(e.Request))1276                {1277                    requestTcs.TrySetResult(e.Request);1278                    _networkManager.Request -= requestEventListener;1279                }1280            }1281            _networkManager.Request += requestEventListener;1282            await Task.WhenAny(new[]1283            {1284                TaskHelper.CreateTimeoutTask(timeout),1285                requestTcs.Task1286            }).ConfigureAwait(false);1287            return await requestTcs.Task.ConfigureAwait(false);1288        }1289        /// <summary>1290        /// Waits for a response.1291        /// </summary>1292        /// <example>1293        /// <code>1294        /// <![CDATA[1295        /// var firstResponse = await page.WaitForResponseAsync("http://example.com/resource");1296        /// return firstResponse.Url;1297        /// ]]>1298        /// </code>1299        /// </example>1300        /// <returns>A task which resolves when a matching response is received.</returns>1301        /// <param name="url">URL to wait for.</param>1302        /// <param name="options">Options.</param>1303        public Task<Response> WaitForResponseAsync(string url, WaitForOptions options = null)1304            => WaitForResponseAsync(response => response.Url == url, options);1305        /// <summary>1306        /// Waits for a response.1307        /// </summary>1308        /// <example>1309        /// <code>1310        /// <![CDATA[1311        /// var response = await page.WaitForResponseAsync(response => response.Url === "http://example.com" && response.Status === HttpStatus.Ok;1312        /// return response.Url;1313        /// ]]>1314        /// </code>1315        /// </example>1316        /// <returns>A task which resolves when a matching response is received.</returns>1317        /// <param name="predicate">Function which looks for a matching response.</param>1318        /// <param name="options">Options.</param>1319        public async Task<Response> WaitForResponseAsync(Func<Response, bool> predicate, WaitForOptions options = null)1320        {1321            var timeout = options?.Timeout ?? DefaultWaitForTimeout;1322            var responseTcs = new TaskCompletionSource<Response>();1323            void responseEventListener(object sender, ResponseCreatedEventArgs e)1324            {1325                if (predicate(e.Response))1326                {1327                    responseTcs.TrySetResult(e.Response);1328                    _networkManager.Response -= responseEventListener;1329                }1330            }1331            _networkManager.Response += responseEventListener;1332            await Task.WhenAny(new[]1333            {1334                TaskHelper.CreateTimeoutTask(timeout),1335                responseTcs.Task1336            }).ConfigureAwait(false);1337            return await responseTcs.Task.ConfigureAwait(false);1338        }1339        /// <summary>1340        /// Navigate to the previous page in history.1341        /// </summary>1342        /// <returns>Task which which resolves to the main resource response. In case of multiple redirects, 1343        /// the navigation will resolve with the response of the last redirect. If can not go back, resolves to null.</returns>1344        /// <param name="options">Navigation parameters.</param>1345        public Task<Response> GoBackAsync(NavigationOptions options = null) => GoAsync(-1, options);1346        /// <summary>1347        /// Navigate to the next page in history.1348        /// </summary>1349        /// <returns>Task which which resolves to the main resource response. In case of multiple redirects, 1350        /// the navigation will resolve with the response of the last redirect. If can not go forward, resolves to null.</returns>1351        /// <param name="options">Navigation parameters.</param>1352        public Task<Response> GoForwardAsync(NavigationOptions options = null) => GoAsync(1, options);1353        /// <summary>1354        /// Resets the background color and Viewport after taking Screenshots using BurstMode.1355        /// </summary>1356        /// <returns>The burst mode off.</returns>1357        public Task SetBurstModeOffAsync()1358        {1359            _screenshotBurstModeOn = false;1360            if (_screenshotBurstModeOptions != null)1361            {1362                ResetBackgroundColorAndViewport(_screenshotBurstModeOptions);1363            }1364            return Task.CompletedTask;1365        }1366        #endregion1367        #region Private Method1368        internal static async Task<Page> CreateAsync(1369            CDPSession client,1370            Target target,1371            bool ignoreHTTPSErrors,1372            ViewPortOptions defaultViewPort,1373            TaskQueue screenshotTaskQueue)1374        {1375            await client.SendAsync("Page.enable", null).ConfigureAwait(false);1376            var result = await client.SendAsync("Page.getFrameTree").ConfigureAwait(false);1377            var page = new Page(client, target, new FrameTree(result[MessageKeys.FrameTree]), ignoreHTTPSErrors, screenshotTaskQueue);1378            await Task.WhenAll(1379                client.SendAsync("Target.setAutoAttach", new { autoAttach = true, waitForDebuggerOnStart = false }),1380                client.SendAsync("Page.setLifecycleEventsEnabled", new { enabled = true }),1381                client.SendAsync("Network.enable", null),1382                client.SendAsync("Runtime.enable", null),1383                client.SendAsync("Security.enable", null),1384                client.SendAsync("Performance.enable", null),1385                client.SendAsync("Log.enable", null)1386            ).ConfigureAwait(false);1387            if (ignoreHTTPSErrors)1388            {1389                await client.SendAsync("Security.setOverrideCertificateErrors", new Dictionary<string, object>1390                {1391                    {"override", true}1392                }).ConfigureAwait(false);1393            }1394            if (defaultViewPort != null)1395            {1396                await page.SetViewportAsync(defaultViewPort).ConfigureAwait(false);1397            }1398            return page;1399        }1400        private async Task<Response> GoAsync(int delta, NavigationOptions options)1401        {1402            var history = await Client.SendAsync<PageGetNavigationHistoryResponse>("Page.getNavigationHistory").ConfigureAwait(false);1403            if (history.Entries.Count <= history.CurrentIndex + delta)1404            {1405                return null;1406            }1407            var entry = history.Entries[history.CurrentIndex + delta];1408            var waitTask = WaitForNavigationAsync(options);1409            await Task.WhenAll(1410                waitTask,1411                Client.SendAsync("Page.navigateToHistoryEntry", new1412                {1413                    entryId = entry.Id1414                })1415            ).ConfigureAwait(false);1416            return waitTask.Result;1417        }1418        private Dictionary<string, decimal> BuildMetricsObject(List<Metric> metrics)1419        {1420            var result = new Dictionary<string, decimal>();1421            foreach (var item in metrics)1422            {1423                if (SupportedMetrics.Contains(item.Name))1424                {1425                    result.Add(item.Name, item.Value);1426                }1427            }1428            return result;1429        }1430        private async Task<string> PerformScreenshot(ScreenshotType type, ScreenshotOptions options)1431        {1432            if (!_screenshotBurstModeOn)1433            {1434                await Client.SendAsync("Target.activateTarget", new1435                {1436                    targetId = Target.TargetId1437                }).ConfigureAwait(false);1438            }1439            var clip = options.Clip?.Clone();1440            if (clip != null)1441            {1442                clip.Scale = 1;1443            }1444            if (!_screenshotBurstModeOn)1445            {1446                if (options != null && options.FullPage)1447                {1448                    var metrics = _screenshotBurstModeOn1449                        ? _burstModeMetrics :1450                        await Client.SendAsync<PageGetLayoutMetricsResponse>("Page.getLayoutMetrics").ConfigureAwait(false);1451                    if (options.BurstMode)1452                    {1453                        _burstModeMetrics = metrics;1454                    }1455                    var contentSize = metrics.ContentSize;1456                    var width = Convert.ToInt32(Math.Ceiling(contentSize.Width));1457                    var height = Convert.ToInt32(Math.Ceiling(contentSize.Height));1458                    // Overwrite clip for full page at all times.1459                    clip = new Clip1460                    {1461                        X = 0,1462                        Y = 0,1463                        Width = width,1464                        Height = height,1465                        Scale = 11466                    };1467                    var isMobile = Viewport?.IsMobile ?? false;1468                    var deviceScaleFactor = Viewport?.DeviceScaleFactor ?? 1;1469                    var isLandscape = Viewport?.IsLandscape ?? false;1470                    var screenOrientation = isLandscape ?1471                        new ScreenOrientation1472                        {1473                            Angle = 90,1474                            Type = ScreenOrientationType.LandscapePrimary1475                        } :1476                        new ScreenOrientation1477                        {1478                            Angle = 0,1479                            Type = ScreenOrientationType.PortraitPrimary1480                        };1481                    await Client.SendAsync("Emulation.setDeviceMetricsOverride", new1482                    {1483                        mobile = isMobile,1484                        width,1485                        height,1486                        deviceScaleFactor,1487                        screenOrientation1488                    }).ConfigureAwait(false);1489                }1490                if (options?.OmitBackground == true && type == ScreenshotType.Png)1491                {1492                    await Client.SendAsync("Emulation.setDefaultBackgroundColorOverride", new1493                    {1494                        color = new1495                        {1496                            r = 0,1497                            g = 0,1498                            b = 0,1499                            a = 01500                        }1501                    }).ConfigureAwait(false);1502                }1503            }1504            dynamic screenMessage = new ExpandoObject();1505            screenMessage.format = type.ToString().ToLower();1506            if (options.Quality.HasValue)1507            {1508                screenMessage.quality = options.Quality.Value;1509            }1510            if (clip != null)1511            {1512                screenMessage.clip = clip;1513            }1514            var result = await Client.SendAsync<PageCaptureScreenshotResponse>("Page.captureScreenshot", screenMessage).ConfigureAwait(false);1515            if (options.BurstMode)1516            {1517                _screenshotBurstModeOptions = options;1518                _screenshotBurstModeOn = true;1519            }1520            else1521            {1522                await ResetBackgroundColorAndViewport(options);1523            }1524            return result.Data;1525        }1526        private Task ResetBackgroundColorAndViewport(ScreenshotOptions options)1527        {1528            var omitBackgroundTask = options?.OmitBackground == true && options.Type == ScreenshotType.Png ?1529                Client.SendAsync("Emulation.setDefaultBackgroundColorOverride") : Task.CompletedTask;1530            var setViewPortTask = (options?.FullPage == true && Viewport != null) ?1531                SetViewportAsync(Viewport) : Task.CompletedTask;1532            return Task.WhenAll(omitBackgroundTask, setViewPortTask);1533        }1534        private decimal ConvertPrintParameterToInches(object parameter)1535        {1536            if (parameter == null)1537            {1538                return 0;1539            }1540            var pixels = 0m;1541            if (parameter is decimal || parameter is int)1542            {1543                pixels = Convert.ToDecimal(parameter);1544            }1545            else1546            {1547                var text = parameter.ToString();1548                var unit = text.Substring(text.Length - 2).ToLower();1549                var valueText = "";1550                if (_unitToPixels.ContainsKey(unit))1551                {1552                    valueText = text.Substring(0, text.Length - 2);1553                }1554                else1555                {1556                    // In case of unknown unit try to parse the whole parameter as number of pixels.1557                    // This is consistent with phantom's paperSize behavior.1558                    unit = "px";1559                    valueText = text;1560                }1561                if (decimal.TryParse(valueText, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out var number))1562                {1563                    pixels = number * _unitToPixels[unit];1564                }1565                else1566                {1567                    throw new ArgumentException($"Failed to parse parameter value: '{text}'", nameof(parameter));1568                }1569            }1570            return pixels / 96;1571        }1572        private async void Client_MessageReceived(object sender, MessageEventArgs e)1573        {1574            switch (e.MessageID)1575            {1576                case "Page.domContentEventFired":1577                    DOMContentLoaded?.Invoke(this, EventArgs.Empty);1578                    break;1579                case "Page.loadEventFired":1580                    Load?.Invoke(this, EventArgs.Empty);1581                    break;1582                case "Runtime.consoleAPICalled":1583                    await OnConsoleAPI(e.MessageData.ToObject<PageConsoleResponse>()).ConfigureAwait(false);1584                    break;1585                case "Page.javascriptDialogOpening":1586                    OnDialog(e.MessageData.ToObject<PageJavascriptDialogOpeningResponse>());1587                    break;1588                case "Runtime.exceptionThrown":1589                    HandleException(e.MessageData.SelectToken(MessageKeys.ExceptionDetails).ToObject<EvaluateExceptionDetails>());1590                    break;1591                case "Security.certificateError":1592                    await OnCertificateError(e.MessageData.ToObject<CertificateErrorResponse>()).ConfigureAwait(false);1593                    break;1594                case "Inspector.targetCrashed":1595                    OnTargetCrashed();1596                    break;1597                case "Performance.metrics":1598                    EmitMetrics(e.MessageData.ToObject<PerformanceMetricsResponse>());1599                    break;1600                case "Target.attachedToTarget":1601                    await OnAttachedToTarget(e).ConfigureAwait(false);1602                    break;1603                case "Target.detachedFromTarget":1604                    OnDetachedFromTarget(e);1605                    break;1606                case "Log.entryAdded":1607                    OnLogEntryAdded(e.MessageData.ToObject<LogEntryAddedResponse>());1608                    break;1609                case "Runtime.bindingCalled":1610                    await OnBindingCalled(e.MessageData.ToObject<BindingCalledResponse>()).ConfigureAwait(false);1611                    break;1612            }1613        }1614        private async Task OnBindingCalled(BindingCalledResponse e)1615        {1616            var result = await ExecuteBinding(e).ConfigureAwait(false);1617            var expression = EvaluationString(1618                @"function deliverResult(name, seq, result) {1619                    window[name]['callbacks'].get(seq)(result);1620                    window[name]['callbacks'].delete(seq);1621                }", e.Payload.Name, e.Payload.Seq, result);1622            Client.Send("Runtime.evaluate", new1623            {1624                expression,1625                contextId = e.ExecutionContextId1626            });1627        }1628        private async Task<object> ExecuteBinding(BindingCalledResponse e)1629        {1630            object result;1631            var binding = _pageBindings[e.Payload.Name];1632            var methodParams = binding.Method.GetParameters().Select(parameter => parameter.ParameterType).ToArray();1633            var args = e.Payload.JsonObject.GetValue(MessageKeys.Args).Select((token, i) => token.ToObject(methodParams[i])).ToArray();1634            result = binding.DynamicInvoke(args);1635            if (result is Task taskResult)1636            {1637                await taskResult.ConfigureAwait(false);1638                if (taskResult.GetType().IsGenericType)1639                {1640                    // the task is already awaited and therefore the call to property Result will not deadlock1641                    result = ((dynamic)taskResult).Result;1642                }1643            }1644            return result;1645        }1646        private void OnDetachedFromTarget(MessageEventArgs e)1647        {1648            var sessionId = e.MessageData.SelectToken(MessageKeys.SessionId).AsString();1649            if (_workers.TryGetValue(sessionId, out var worker))1650            {1651                WorkerDestroyed?.Invoke(this, new WorkerEventArgs(worker));1652                _workers.Remove(sessionId);1653            }1654        }1655        private async Task OnAttachedToTarget(MessageEventArgs e)1656        {1657            var targetInfo = e.MessageData.SelectToken(MessageKeys.TargetInfo).ToObject<TargetInfo>();1658            var sessionId = e.MessageData.SelectToken(MessageKeys.SessionId).ToObject<string>();1659            if (targetInfo.Type != TargetType.Worker)1660            {1661                try1662                {1663                    await Client.SendAsync("Target.detachFromTarget", new { sessionId }).ConfigureAwait(false);1664                }1665                catch (Exception ex)1666                {1667                    _logger.LogError(ex.ToString());1668                }1669                return;1670            }1671            var session = Client.CreateSession(TargetType.Worker, sessionId);1672            var worker = new Worker(session, targetInfo.Url, AddConsoleMessage, HandleException);1673            _workers[sessionId] = worker;1674            WorkerCreated?.Invoke(this, new WorkerEventArgs(worker));1675        }1676        private void OnLogEntryAdded(LogEntryAddedResponse e)1677        {1678            if (e.Entry.Args != null)1679            {1680                foreach (var arg in e.Entry?.Args)1681                {1682                    RemoteObjectHelper.ReleaseObject(Client, arg, _logger);1683                }1684            }1685            if (e.Entry.Source != TargetType.Worker)1686            {1687                Console?.Invoke(this, new ConsoleEventArgs(new ConsoleMessage(e.Entry.Level, e.Entry.Text)));1688            }...FacebookRegistration.cs
Source:FacebookRegistration.cs  
...192            page.FrameAttached += Page_FrameAttached;193            page.FrameNavigated += Page_FrameNavigated;194            page.WorkerCreated += Page_WorkerCreated;195        }196        private static void Page_WorkerCreated(object sender, WorkerEventArgs e)197        {198            Log.Info($"{nameof(Page_WorkerCreated)} {e.Worker.Url}");199        }200        private async static void Page_FrameNavigated(object sender, FrameEventArgs e)201        {202            Log.Info($"{nameof(Page_FrameNavigated)} {e.Frame.Url}");203            //if (e.Frame.Url.Contains("referer_frame"))204            //{205            //    var anticaptchaScriptText = File.ReadAllText(Path.GetFullPath(".\\Data\\recaptchaaifb.js"));206            //    //await e.Frame.AddScriptTagAsync(new AddTagOptions { Url = "https://cdn.antcpt.com/imacros_inclusion/recaptcha.js" });207            //    await e.Frame.AddScriptTagAsync(new AddTagOptions { Content = anticaptchaScriptText });208            //}209        }210        private async static void Page_FrameAttached(object sender, FrameEventArgs e)...BrowserContext.cs
Source:BrowserContext.cs  
...293				}294			}295		}296	}297	private void Page_WorkerCreated(object sender, WorkerEventArgs e)298	{299		if (DebugInfo)300		{301			Console.WriteLine($"Page_WorkerCreated: {e.Worker.Url}");302		}303	}304	private void Page_WorkerDestroyed(object sender, WorkerEventArgs e)305	{306		if (DebugInfo)307		{308			Console.WriteLine($"Page_WorkerDestroyed: {e.Worker.Url}");309		}310	}311}...WorkerEventArgs.cs
Source:WorkerEventArgs.cs  
...3{4    /// <summary>5    /// Workder created event arguments.6    /// </summary>7    public class WorkerEventArgs : EventArgs8    {9        /// <summary>10        /// Worker11        /// </summary>12        /// <value>The worker.</value>13        public Worker Worker { get; set; }14        /// <summary>15        /// Initializes a new instance of the <see cref="WorkerEventArgs"/> class.16        /// </summary>17        /// <param name="worker">Worker.</param>18        public WorkerEventArgs(Worker worker) => Worker = worker;19    }20}...WorkerEventArgs
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5    {6        static async Task Main(string[] args)7        {8            var browser = await Puppeteer.LaunchAsync(new LaunchOptions9            {10            });11            var page = await browser.NewPageAsync();12            page.WorkerCreated += Page_WorkerCreated;13            await page.WaitForSelectorAsync("input[name=q]");14            await page.TypeAsync("input[name=q]", "puppeteer");15            await page.ClickAsync("input[name=btnK]");16            await page.WaitForNavigationAsync();17            await page.CloseAsync();18            await browser.CloseAsync();19        }20        private static void Page_WorkerCreated(object sender, WorkerEventArgs e)21        {22            Console.WriteLine("Worker Created: " + e.Worker.Url);23        }24    }25}26using System;27using System.Threading.Tasks;28using PuppeteerSharp;29{30    {31        static async Task Main(string[] args)32        {33            var browser = await Puppeteer.LaunchAsync(new LaunchOptions34            {35            });36            var page = await browser.NewPageAsync();37            page.WorkerCreated += Page_WorkerCreated;38            await page.WaitForSelectorAsync("input[name=q]");39            await page.TypeAsync("input[name=q]", "puppeteer");40            await page.ClickAsync("input[name=btnK]");41            await page.WaitForNavigationAsync();42            await page.CloseAsync();43            await browser.CloseAsync();44        }45        private static void Page_WorkerCreated(object sender, WorkerEventArgs e)46        {47            Console.WriteLine("Worker Created: " + e.Worker.Url);48        }49    }50}51using System;52using System.Threading.Tasks;53using PuppeteerSharp;54{55    {56        static async Task Main(string[] args)57        {58            var browser = await Puppeteer.LaunchAsync(new LaunchOptions59            {WorkerEventArgs
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5    {6        public static async Task Run()7        {8            using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions9            {10                Args = new string[] { "--no-sandbox" }11            }))12            {13                using (var page = await browser.NewPageAsync())14                {15                    page.WorkerCreated += Page_WorkerCreated;16                    page.WorkerDestroyed += Page_WorkerDestroyed;17                }18            }19        }20        private static void Page_WorkerDestroyed(object sender, WorkerEventArgs e)21        {22            Console.WriteLine(e.Worker.Url);23        }24        private static void Page_WorkerCreated(object sender, WorkerEventArgs e)25        {26            Console.WriteLine(e.Worker.Url);27        }28    }29}WorkerEventArgs
Using AI Code Generation
1using PuppeteerSharp;2{3    {4        static void Main(string[] args)5        {6            var task = MainAsync(args);7            task.Wait();8        }9        static async Task MainAsync(string[] args)10        {11            var options = new LaunchOptions { Headless = true };12            using (var browser = await Puppeteer.LaunchAsync(options))13            using (var page = await browser.NewPageAsync())14            {15                page.WorkerCreated += Page_WorkerCreated;16                page.WorkerDestroyed += Page_WorkerDestroyed;17            }18        }19        private static void Page_WorkerDestroyed(object sender, WorkerEventArgs e)20        {21            Console.WriteLine($"Worker destroyed: {e.Worker.Url}");22        }23        private static void Page_WorkerCreated(object sender, WorkerEventArgs e)24        {25            Console.WriteLine($"Worker created: {e.Worker.Url}");26        }27    }28}29using PuppeteerSharp;30{31    {32        static void Main(string[] args)33        {34            var task = MainAsync(args);35            task.Wait();36        }37        static async Task MainAsync(string[] args)38        {39            var options = new LaunchOptions { Headless = true };40            using (var browser = await Puppeteer.LaunchAsync(options))41            using (var page = await browser.NewPageAsync())42            {43                page.WorkerCreated += Page_WorkerCreated;44                page.WorkerDestroyed += Page_WorkerDestroyed;45            }46        }47        private static void Page_WorkerDestroyed(object sender, WorkerEventArgs e)48        {49            Console.WriteLine($"Worker destroyed: {e.Worker.Url}");50        }51        private static void Page_WorkerCreated(object sender, WorkerEventArgs e)52        {53            Console.WriteLine($"Worker created: {e.Worker.Url}");54        }55    }56}57using PuppeteerSharp;58{59    {60        static void Main(string[] args)61        {62            var task = MainAsync(args);63            task.Wait();64        }65        static async Task MainAsync(string[]WorkerEventArgs
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5    static void Main(string[] args)6    {7        MainAsync(args).GetAwaiter().GetResult();8    }9    static async Task MainAsync(string[] args)10    {11        var browser = await Puppeteer.LaunchAsync(new LaunchOptions12        {13        });14        var page = await browser.NewPageAsync();15        page.WorkerCreated += Page_WorkerCreated;16        await Task.Delay(2000);17        await browser.CloseAsync();18    }19    private static void Page_WorkerCreated(object sender, WorkerEventArgs e)20    {21        Console.WriteLine(e.Worker.Url);22    }23}24{25    public string Url { get; internal set; }26    public Task TerminateAsync() { }27    public Task<JSHandle> EvaluateExpressionHandleAsync(string pageFunction, object arg = null) { }28    public Task<JSHandle> EvaluateExpressionHandleAsync(string pageFunction, params object[] args) { }29    public Task<JsonElement> EvaluateExpressionAsync(string pageFunction, object arg = null) { }30    public Task<JsonElement> EvaluateExpressionAsync(string pageFunction, params object[] args) { }31    public Task<JsonElement> EvaluateExpressionAsync<T>(string pageFunction, T arg) { }32    public Task<JsonElement> EvaluateExpressionAsync<T1, T2>(string pageFunction, T1 arg1, T2 arg2) { }33    public Task<JsonElement> EvaluateExpressionAsync<T1, T2, T3>(string pageFunction, T1 arg1, T2 arg2, T3 arg3) { }WorkerEventArgs
Using AI Code Generation
1var worker = new WorkerEventArgs();2worker.Type = "service_worker";3Console.WriteLine("Worker Type: " + worker.Type);4Console.WriteLine("Worker Url: " + worker.Url);5var worker = new WorkerEventArgs();6worker.Type = "service_worker";7Console.WriteLine("Worker Type: " + worker.Type);8Console.WriteLine("Worker Url: " + worker.Url);9var worker = new WorkerEventArgs();10worker.Type = "service_worker";11Console.WriteLine("Worker Type: " + worker.Type);12Console.WriteLine("Worker Url: " + worker.Url);13var worker = new WorkerEventArgs();14worker.Type = "service_worker";15Console.WriteLine("Worker Type: " + worker.Type);16Console.WriteLine("Worker Url: " + worker.Url);17var worker = new WorkerEventArgs();18worker.Type = "service_worker";19Console.WriteLine("Worker Type: " + worker.Type);20Console.WriteLine("Worker Url: " + worker.Url);21var worker = new WorkerEventArgs();22worker.Type = "service_worker";23Console.WriteLine("Worker Type: " + worker.Type);24Console.WriteLine("Worker Url: " + worker.Url);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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
