How to use FrameTree class of PuppeteerSharp package

Best Puppeteer-sharp code snippet using PuppeteerSharp.FrameTree

Page.cs

Source:Page.cs Github

copy

Full Screen

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

Full Screen

Full Screen

FrameManager.cs

Source:FrameManager.cs Github

copy

Full Screen

...13 private Dictionary<int, ExecutionContext> _contextIdToContext;14 private bool _ensureNewDocumentNavigation;15 private readonly ILogger _logger;16 private readonly NetworkManager _networkManager;17 internal FrameManager(CDPSession client, FrameTree frameTree, Page page, NetworkManager networkManager)18 {19 _client = client;20 Page = page;21 Frames = new Dictionary<string, Frame>();22 _contextIdToContext = new Dictionary<int, ExecutionContext>();23 _logger = _client.Connection.LoggerFactory.CreateLogger<FrameManager>();24 _networkManager = networkManager;25 _client.MessageReceived += _client_MessageReceived;26 HandleFrameTree(frameTree);27 }28 #region Properties29 internal event EventHandler<FrameEventArgs> FrameAttached;30 internal event EventHandler<FrameEventArgs> FrameDetached;31 internal event EventHandler<FrameEventArgs> FrameNavigated;32 internal event EventHandler<FrameEventArgs> FrameNavigatedWithinDocument;33 internal event EventHandler<FrameEventArgs> LifecycleEvent;34 internal Dictionary<string, Frame> Frames { get; set; }35 internal Frame MainFrame { get; set; }36 internal Page Page { get; }37 internal int DefaultNavigationTimeout { get; set; } = 30000;38 #endregion39 #region Public Methods40 internal ExecutionContext ExecutionContextById(int contextId)41 {42 _contextIdToContext.TryGetValue(contextId, out var context);43 if (context == null)44 {45 _logger.LogError("INTERNAL ERROR: missing context with id = {ContextId}", contextId);46 }47 return context;48 }49 public async Task<Response> NavigateFrameAsync(Frame frame, string url, NavigationOptions options)50 {51 var referrer = string.IsNullOrEmpty(options.Referer)52 ? _networkManager.ExtraHTTPHeaders?.GetValueOrDefault(MessageKeys.Referer)53 : options.Referer;54 var requests = new Dictionary<string, Request>();55 var timeout = options?.Timeout ?? DefaultNavigationTimeout;56 var watcher = new NavigatorWatcher(_client, this, frame, _networkManager, timeout, options);57 var navigateTask = NavigateAsync(_client, url, referrer, frame.Id);58 await Task.WhenAny(59 watcher.TimeoutOrTerminationTask,60 navigateTask).ConfigureAwait(false);61 AggregateException exception = null;62 if (navigateTask.IsFaulted)63 {64 exception = navigateTask.Exception;65 }66 else67 {68 await Task.WhenAny(69 watcher.TimeoutOrTerminationTask,70 _ensureNewDocumentNavigation ? watcher.NewDocumentNavigationTask : watcher.SameDocumentNavigationTask71 ).ConfigureAwait(false);72 if (watcher.TimeoutOrTerminationTask.IsCompleted && watcher.TimeoutOrTerminationTask.Result.IsFaulted)73 {74 exception = watcher.TimeoutOrTerminationTask.Result.Exception;75 }76 }77 if (exception != null)78 {79 throw new NavigationException(exception.InnerException.Message, exception.InnerException);80 }81 return watcher.NavigationResponse;82 }83 private async Task NavigateAsync(CDPSession client, string url, string referrer, string frameId)84 {85 var response = await client.SendAsync<PageNavigateResponse>("Page.navigate", new86 {87 url,88 referrer = referrer ?? string.Empty,89 frameId90 }).ConfigureAwait(false);91 _ensureNewDocumentNavigation = !string.IsNullOrEmpty(response.LoaderId);92 if (!string.IsNullOrEmpty(response.ErrorText))93 {94 throw new NavigationException(response.ErrorText, url);95 }96 }97 public async Task<Response> WaitForFrameNavigationAsync(Frame frame, NavigationOptions options = null)98 {99 var timeout = options?.Timeout ?? DefaultNavigationTimeout;100 var watcher = new NavigatorWatcher(_client, this, frame, _networkManager, timeout, options);101 var raceTask = await Task.WhenAny(102 watcher.NewDocumentNavigationTask,103 watcher.SameDocumentNavigationTask,104 watcher.TimeoutOrTerminationTask105 ).ConfigureAwait(false);106 var exception = raceTask.Exception;107 if (exception == null &&108 watcher.TimeoutOrTerminationTask.IsCompleted &&109 watcher.TimeoutOrTerminationTask.Result.IsFaulted)110 {111 exception = watcher.TimeoutOrTerminationTask.Result.Exception;112 }113 if (exception != null)114 {115 throw new NavigationException(exception.Message, exception);116 }117 return watcher.NavigationResponse;118 }119 #endregion120 #region Private Methods121 private void _client_MessageReceived(object sender, MessageEventArgs e)122 {123 switch (e.MessageID)124 {125 case "Page.frameAttached":126 OnFrameAttached(127 e.MessageData.SelectToken(MessageKeys.FrameId).ToObject<string>(),128 e.MessageData.SelectToken("parentFrameId").ToObject<string>());129 break;130 case "Page.frameNavigated":131 OnFrameNavigated(e.MessageData.SelectToken(MessageKeys.Frame).ToObject<FramePayload>());132 break;133 case "Page.navigatedWithinDocument":134 OnFrameNavigatedWithinDocument(e.MessageData.ToObject<NavigatedWithinDocumentResponse>());135 break;136 case "Page.frameDetached":137 OnFrameDetached(e.MessageData.ToObject<BasicFrameResponse>());138 break;139 case "Page.frameStoppedLoading":140 OnFrameStoppedLoading(e.MessageData.ToObject<BasicFrameResponse>());141 break;142 case "Runtime.executionContextCreated":143 OnExecutionContextCreated(e.MessageData.SelectToken(MessageKeys.Context).ToObject<ContextPayload>());144 break;145 case "Runtime.executionContextDestroyed":146 OnExecutionContextDestroyed(e.MessageData.SelectToken(MessageKeys.ExecutionContextId).ToObject<int>());147 break;148 case "Runtime.executionContextsCleared":149 OnExecutionContextsCleared();150 break;151 case "Page.lifecycleEvent":152 OnLifeCycleEvent(e.MessageData.ToObject<LifecycleEventResponse>());153 break;154 default:155 break;156 }157 }158 private void OnFrameStoppedLoading(BasicFrameResponse e)159 {160 if (Frames.TryGetValue(e.FrameId, out var frame))161 {162 frame.OnLoadingStopped();163 LifecycleEvent?.Invoke(this, new FrameEventArgs(frame));164 }165 }166 private void OnLifeCycleEvent(LifecycleEventResponse e)167 {168 if (Frames.TryGetValue(e.FrameId, out var frame))169 {170 frame.OnLifecycleEvent(e.LoaderId, e.Name);171 LifecycleEvent?.Invoke(this, new FrameEventArgs(frame));172 }173 }174 private void OnExecutionContextsCleared()175 {176 foreach (var context in _contextIdToContext.Values)177 {178 RemoveContext(context);179 }180 _contextIdToContext.Clear();181 }182 private void OnExecutionContextDestroyed(int executionContextId)183 {184 _contextIdToContext.TryGetValue(executionContextId, out var context);185 if (context != null)186 {187 _contextIdToContext.Remove(executionContextId);188 RemoveContext(context);189 }190 }191 private void OnExecutionContextCreated(ContextPayload contextPayload)192 {193 var frameId = contextPayload.AuxData.IsDefault ? contextPayload.AuxData.FrameId : null;194 var frame = !string.IsNullOrEmpty(frameId) ? Frames[frameId] : null;195 var context = new ExecutionContext(196 _client,197 contextPayload,198 frame);199 _contextIdToContext[contextPayload.Id] = context;200 if (frame != null)201 {202 frame.SetDefaultContext(context);203 }204 }205 private void OnFrameDetached(BasicFrameResponse e)206 {207 if (Frames.TryGetValue(e.FrameId, out var frame))208 {209 RemoveFramesRecursively(frame);210 }211 }212 private void OnFrameNavigated(FramePayload framePayload)213 {214 var isMainFrame = string.IsNullOrEmpty(framePayload.ParentId);215 var frame = isMainFrame ? MainFrame : Frames[framePayload.Id];216 Contract.Assert(isMainFrame || frame != null, "We either navigate top level or have old version of the navigated frame");217 // Detach all child frames first.218 if (frame != null)219 {220 while (frame.ChildFrames.Count > 0)221 {222 RemoveFramesRecursively(frame.ChildFrames[0]);223 }224 }225 // Update or create main frame.226 if (isMainFrame)227 {228 if (frame != null)229 {230 // Update frame id to retain frame identity on cross-process navigation.231 if (frame.Id != null)232 {233 Frames.Remove(frame.Id);234 }235 frame.Id = framePayload.Id;236 }237 else238 {239 // Initial main frame navigation.240 frame = new Frame(this, _client, null, framePayload.Id);241 }242 Frames[framePayload.Id] = frame;243 MainFrame = frame;244 }245 // Update frame payload.246 frame.Navigated(framePayload);247 FrameNavigated?.Invoke(this, new FrameEventArgs(frame));248 }249 private void OnFrameNavigatedWithinDocument(NavigatedWithinDocumentResponse e)250 {251 if (Frames.TryGetValue(e.FrameId, out var frame))252 {253 frame.NavigatedWithinDocument(e.Url);254 var eventArgs = new FrameEventArgs(frame);255 FrameNavigatedWithinDocument?.Invoke(this, eventArgs);256 FrameNavigated?.Invoke(this, eventArgs);257 }258 }259 private void RemoveContext(ExecutionContext context)260 {261 if (context.Frame != null)262 {263 context.Frame.SetDefaultContext(null);264 }265 }266 private void RemoveFramesRecursively(Frame frame)267 {268 while (frame.ChildFrames.Count > 0)269 {270 RemoveFramesRecursively(frame.ChildFrames[0]);271 }272 frame.Detach();273 Frames.Remove(frame.Id);274 FrameDetached?.Invoke(this, new FrameEventArgs(frame));275 }276 private void OnFrameAttached(string frameId, string parentFrameId)277 {278 if (!Frames.ContainsKey(frameId) && Frames.ContainsKey(parentFrameId))279 {280 var parentFrame = Frames[parentFrameId];281 var frame = new Frame(this, _client, parentFrame, frameId);282 Frames[frame.Id] = frame;283 FrameAttached?.Invoke(this, new FrameEventArgs(frame));284 }285 }286 private void HandleFrameTree(FrameTree frameTree)287 {288 if (!string.IsNullOrEmpty(frameTree.Frame.ParentId))289 {290 OnFrameAttached(frameTree.Frame.Id, frameTree.Frame.ParentId);291 }292 OnFrameNavigated(frameTree.Frame);293 if (frameTree.Childs != null)294 {295 foreach (var child in frameTree.Childs)296 {297 HandleFrameTree(child);298 }299 }300 }301 #endregion302 }303}...

Full Screen

Full Screen

MessageKeys.cs

Source:MessageKeys.cs Github

copy

Full Screen

...37 public const string ParentId = "parentId";38 public const string Url = "url";39 public const string Urls = "urls";40 public const string ChildFrames = "childFrames";41 public const string FrameTree = "frameTree";42 public const string ContentSize = "contentSize";43 public const string Width = "width";44 public const string Height = "height";45 public const string FrameId = "frameId";46 public const string ExecutionContextId = "executionContextId";47 public const string Args = "args";48 public const string EventId = "eventId";49 public const string BrowserContextId = "browserContextId";50 public const string RequestId = "requestId";51 public const string InterceptionId = "interceptionId";52 public const string Headers = "headers";53 public const string TargetInfo = "targetInfo";54 public const string PostData = "postData";55 public const string Modifiers = "modifiers";...

Full Screen

Full Screen

FrameTree.cs

Source:FrameTree.cs Github

copy

Full Screen

...3using PuppeteerSharp.Helpers;4using PuppeteerSharp.Messaging;5namespace PuppeteerSharp6{7 internal class FrameTree8 {9 internal FrameTree()10 {11 Childs = new List<FrameTree>();12 }13 internal FrameTree(JToken frameTree)14 {15 var frame = frameTree[MessageKeys.Frame];16 Frame = new FramePayload17 {18 Id = frame[MessageKeys.Id].AsString(),19 ParentId = frame[MessageKeys.ParentId].AsString(),20 Name = frame[MessageKeys.Name].AsString(),21 Url = frame[MessageKeys.Url].AsString()22 };23 Childs = new List<FrameTree>();24 LoadChilds(this, frameTree);25 }26 #region Properties27 internal FramePayload Frame { get; set; }28 internal List<FrameTree> Childs { get; set; }29 #endregion30 #region Private Functions31 private void LoadChilds(FrameTree frame, JToken frameTree)32 {33 var childFrames = frameTree[MessageKeys.ChildFrames];34 if (childFrames != null)35 {36 foreach (var item in childFrames)37 {38 var childFrame = item[MessageKeys.Frame];39 var newFrame = new FrameTree40 {41 Frame = new FramePayload42 {43 Id = childFrame[MessageKeys.Id].AsString(),44 ParentId = childFrame[MessageKeys.ParentId].AsString(),45 Url = childFrame[MessageKeys.Url].AsString()46 }47 };48 if ((item as JObject)[MessageKeys.ChildFrames] != null)49 {50 LoadChilds(newFrame, item);51 }52 frame.Childs.Add(newFrame);53 }...

Full Screen

Full Screen

PageGetFrameTreeResponse.cs

Source:PageGetFrameTreeResponse.cs Github

copy

Full Screen

1using System.Collections.Generic;2using Newtonsoft.Json.Linq;3namespace PuppeteerSharp.Messaging4{5 internal class PageGetFrameTreeResponse6 {7 public PageGetFrameTreeItem FrameTree { get; set; }8 }9}...

Full Screen

Full Screen

FrameTree

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5 {6 public static async Task Main(string[] args)7 {8 await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);9 using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false }))10 using (var page = await browser.NewPageAsync())11 {12 var frame = await page.QuerySelectorAsync("iframe");13 var frameTree = await page.GetFrameTreeAsync();14 var frameId = frameTree.Frame.Id;15 var childFrame = page.Frames[1];16 var childFrameId = childFrame.Id;17 var childFrameTree = await childFrame.GetFrameTreeAsync();18 Console.WriteLine("Frame tree: {0}", frameTree);19 }20 }21 }22}23 at PuppeteerSharp.FrameTree.get_Frame()24 at PuppeteerSharpTest.FrameTree.Main(String[] args) in C:\Users\user\source\repos\PuppeteerSharpTest\PuppeteerSharpTest\FrameTree.cs:line 25

Full Screen

Full Screen

FrameTree

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5 {6 static void Main(string[] args)7 {8 MainAsync(args).GetAwaiter().GetResult();9 }10 static async Task MainAsync(string[] args)11 {12 var browser = await Puppeteer.LaunchAsync(new LaunchOptions13 {14 Args = new string[] { "--start-maximized" }15 });16 var page = await browser.NewPageAsync();17 var frameTree = await page.MainFrame.GetFrameTreeAsync();18 Console.WriteLine(frameTree.ToString());19 await browser.CloseAsync();20 }21 }22}23FrameTree {24 FrameTree {

Full Screen

Full Screen

FrameTree

Using AI Code Generation

copy

Full Screen

1var frameTree = await page.GetFrameTreeAsync();2var frame = frameTree.ChildFrames[0];3await frame.ClickAsync("button");4await frame.ClickAsync("button");5await frame.ClickAsync("button");6await frame.ClickAsync("button");7await frame.ClickAsync("button");8var frameTree = await page.GetFrameTreeAsync();9var frame = frameTree.ChildFrames[0];10var frameTree2 = await frame.GetFrameTreeAsync();11var frame2 = frameTree2.ChildFrames[0];12await frame2.ClickAsync("button");13await frame2.ClickAsync("button");14await frame2.ClickAsync("button");15await frame2.ClickAsync("button");16await frame2.ClickAsync("button");17var frameTree = await page.GetFrameTreeAsync();18var frame = frameTree.ChildFrames[0];19var frameTree2 = await frame.GetFrameTreeAsync();20var frame2 = frameTree2.ChildFrames[0];21var frameTree3 = await frame2.GetFrameTreeAsync();22var frame3 = frameTree3.ChildFrames[0];23await frame3.ClickAsync("button");24await frame3.ClickAsync("button");25await frame3.ClickAsync("button");26await frame3.ClickAsync("button");27await frame3.ClickAsync("button");28var frameTree = await page.GetFrameTreeAsync();29var frame = frameTree.ChildFrames[0];30var frameTree2 = await frame.GetFrameTreeAsync();31var frame2 = frameTree2.ChildFrames[0];32var frameTree3 = await frame2.GetFrameTreeAsync();33var frame3 = frameTree3.ChildFrames[0];34var frameTree4 = await frame3.GetFrameTreeAsync();35var frame4 = frameTree4.ChildFrames[0];36await frame4.ClickAsync("button");37await frame4.ClickAsync("button");38await frame4.ClickAsync("button");39await frame4.ClickAsync("button");40await frame4.ClickAsync("button");41var frameTree = await page.GetFrameTreeAsync();42var frame = frameTree.ChildFrames[0];

Full Screen

Full Screen

FrameTree

Using AI Code Generation

copy

Full Screen

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 var frameTree = page.MainFrame.GetFrameTree();13 Console.WriteLine(frameTree);14 Console.ReadLine();15 await browser.CloseAsync();16 }17 }18}19FrameTree {20 Frame = Frame {21 }22 FrameTree {23 Frame = Frame {24 ParentFrame = Frame {25 }26 }27 }28}

Full Screen

Full Screen

FrameTree

Using AI Code Generation

copy

Full Screen

1using System;2using System.IO;3using System.Threading.Tasks;4using PuppeteerSharp;5{6 {7 static async Task Main(string[] args)8 {9 string fileName = "FrameTree.txt";10 await GetFrameTree(url, fileName);11 }12 static async Task GetFrameTree(string url, string fileName)13 {14 await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);15 using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }))16 using (var page = await browser.NewPageAsync())17 {18 await page.GoToAsync(url);19 FrameTree frameTree = page.MainFrame.GetFrameTree();20 using (StreamWriter sw = new StreamWriter(fileName))21 {22 await sw.WriteLineAsync(frameTree.ToString());23 }24 }25 }26 }27}

Full Screen

Full Screen

Automation Testing Tutorials

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

LambdaTest Learning Hubs:

YouTube

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

Run Puppeteer-sharp automation tests on LambdaTest cloud grid

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

Most used methods in FrameTree

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful