How to use DialogEventArgs method of PuppeteerSharp.DialogEventArgs class

Best Puppeteer-sharp code snippet using PuppeteerSharp.DialogEventArgs.DialogEventArgs

Page.cs

Source:Page.cs Github

copy

Full Screen

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

Full Screen

Full Screen

PuppeteerBrowserBuilder.cs

Source:PuppeteerBrowserBuilder.cs Github

copy

Full Screen

...59 public bool PageEvents { get; private set; }60 public bool BrowserEvents { get; private set; }61 public TimeSpan PageLoadTimeout { get; private set; }62 public bool PageCacheEnabled { get; private set; }63 public EventHandler<DialogEventArgs> DialogHandler { get; private set; }64 public PuppeteerContext(IBrowserViewPortConfig browserConfig, IDelayService delayService, ILoggingContext loggingContext)65 {66 _logger = loggingContext.CreateLogger<IPuppeteerContext>();67 _browserConfig = browserConfig;68 _delayService = delayService;69 _loggingContext = loggingContext;70 _browserProperties = new List<string>();71 _headless = true;72 }73 public IPuppeteerContext SetDefaultLaunchProperties()74 {75 _browserProperties.Add("--no-sandbox");76 _browserProperties.Add("--disable-infobars");77 _browserProperties.Add("--disable-setuid-sandbox");78 _browserProperties.Add("--ignore-certificate-errors");79 _browserProperties.Add("--disable-gpu");80 _browserProperties.Add("--lang=en-US,en");81 return this;82 }83 public IPuppeteerContext SetEnLangAndIgnoreCertErrors()84 {85 _browserProperties.Add("--ignore-certificate-errors");86 _browserProperties.Add("--lang=en-US,en");87 return this;88 }89 public IPuppeteerContext SetPageDialogHandler(EventHandler<DialogEventArgs> eventHandler)90 {91 DialogHandler = eventHandler;92 return this;93 }94 public IPuppeteerContext SetBrowserProperty(string property)95 {96 _browserProperties.Add(property);97 return this;98 }99 public IPuppeteerContext SetIncognito(bool incognito = true)100 {101 _isIncognito = incognito;102 _browserProperties.AddRange(new[] {103 "--incognito"...

Full Screen

Full Screen

BrowserContext.cs

Source:BrowserContext.cs Github

copy

Full Screen

...163 {164 Console.WriteLine($"Page_Console: {e.Message.Type}, {e.Message.Text}");165 }166 }167 private void Page_Dialog(object sender, DialogEventArgs e)168 {169 if (DebugInfo)170 {171 Console.WriteLine($"Page_Dialog: {e.Dialog.DialogType}, {e.Dialog.Message}");172 }173 }174 private void Page_DOMContentLoaded(object sender, EventArgs e)175 {176 if (DebugInfo)177 {178 Console.WriteLine("Page_DOMContentLoaded");179 }180 }181 private void Page_Error(object sender, ErrorEventArgs e)...

Full Screen

Full Screen

BrowserInstance.cs

Source:BrowserInstance.cs Github

copy

Full Screen

...148 DefaultViewport = new ViewPortOptions() {Height = 600, Width = 1000}149 });150 private void OnCurrentBrowserInstanceOnClosed(object? sender, EventArgs args) =>151 App.PuppeteerLogger.Information($"Browser closed.");152 private void OnCurrentPageInstanceOnDialog(object? sender, DialogEventArgs args) =>153 App.PuppeteerLogger.Information($"{args.Dialog.DialogType} {args.Dialog.Message}");154 private void OnCurrentPageInstanceOnPageInstanceError(object? sender, PageErrorEventArgs args) =>155 App.PuppeteerLogger.Error($"PageError {args.Message}");156 private void OnCurrentPageInstanceOnClose(object? sender, EventArgs args) =>157 App.PuppeteerLogger.Information($"Page closed.");158 private void OnCurrentPageInstanceOnRequestFailed(object? sender, RequestEventArgs args) =>159 App.PuppeteerLogger.Error($"{args.Request.Method.Method} {args.Request.Url}");160 private void OnCurrentPageInstanceOnDomContentLoaded(object? sender, EventArgs args) =>161 App.PuppeteerLogger.Information($"DOMLoaded {CurrentPageInstance.Url}");162 private void OnCurrentPageInstanceOnError(object? sender, ErrorEventArgs args) =>163 App.PuppeteerLogger.Error($"{args.Error}");164 private void OnCurrentPageInstanceOnLoad(object? sender, EventArgs args) =>165 App.PuppeteerLogger.Information($"OnLoaded {CurrentPageInstance.Url}");166 private void OnCurrentPageInstanceOnFrameNavigated(object? sender, FrameEventArgs args) =>...

Full Screen

Full Screen

IPuppeteerContext.cs

Source:IPuppeteerContext.cs Github

copy

Full Screen

...11 bool PageEvents { get; }12 bool BrowserEvents { get; }13 TimeSpan PageLoadTimeout { get; }14 bool PageCacheEnabled { get; }15 EventHandler<DialogEventArgs> DialogHandler { get; }16 IPuppeteerContext SetOverridePermission();17 IPuppeteerContext SetDefaultLaunchProperties();18 IPuppeteerContext SetEnLangAndIgnoreCertErrors();19 IPuppeteerContext SetPageDialogHandler(EventHandler<DialogEventArgs> eventHandler);20 IPuppeteerContext SetBrowserProperty(string property);21 IPuppeteerContext SetIncognito(bool incognito = true);22 IPuppeteerContext SetProxy(string ip, int port, string userName, string pwd);23 IPuppeteerContext SetHeadless(bool headless);24 IPuppeteerContext SetHeadless(TimeSpan timeout);25 IPuppeteerContext SetPageCacheEnabled(bool enabled);26 Task<IPuppeteerBrowser> CreateBrowser(Platform platform);27 IPuppeteerContext DisableWebSecurity();28 IPuppeteerContext DisableFeatures(string arg); 29 IPuppeteerContext DisableXssAuditor();30 IPuppeteerContext EnableBrowserEvents(bool browserEvents);31 IPuppeteerContext EnablePageEvents(bool pageEvents);32 }33}...

Full Screen

Full Screen

DialogEventArgs.cs

Source:DialogEventArgs.cs Github

copy

Full Screen

...4{5 /// <summary>6 /// <see cref="Page.Dialog"/> arguments.7 /// </summary>8 public class DialogEventArgs : EventArgs9 {10 /// <summary>11 /// Dialog data.12 /// </summary>13 /// <value>Dialog data.</value>14 public Dialog Dialog { get; }15 /// <summary>16 /// Initializes a new instance of the <see cref="DialogEventArgs"/> class.17 /// </summary>18 /// <param name="dialog">Dialog.</param>19 public DialogEventArgs(Dialog dialog) => Dialog = dialog;20 }21}...

Full Screen

Full Screen

DialogEventArgs

Using AI Code Generation

copy

Full Screen

1using System.Threading.Tasks;2using PuppeteerSharp;3using System;4{5 {6 static void Main(string[] args)7 {8 Console.WriteLine("Hello World!");9 }10 public async Task RunSample()11 {12 var browser = await Puppeteer.LaunchAsync(new LaunchOptions13 {14 });15 var page = await browser.NewPageAsync();16 page.Dialog += async (sender, e) =>17 {18 Console.WriteLine(e.Dialog.Type);19 Console.WriteLine(e.Dialog.Message);20 await e.Dialog.AcceptAsync();21 };22 await page.EvaluateExpressionAsync("alert('1')");23 }24 }25}

Full Screen

Full Screen

DialogEventArgs

Using AI Code Generation

copy

Full Screen

1using System;2using System.IO;3using System.Threading.Tasks;4using PuppeteerSharp;5{6 {7 public static async Task RunAsync()8 {9 await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);10 using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false }))11 using (var page = await browser.NewPageAsync())12 {13 page.Dialog += async (sender, e) =>14 {15 Console.WriteLine(e.Message);16 await e.Dialog.AcceptAsync();17 };18 await page.EvaluateExpressionAsync("confirm('This message is displayed by the onbeforeunload event')");19 await page.CloseAsync();20 }21 }22 }23}24using System;25using System.IO;26using System.Threading.Tasks;27using PuppeteerSharp;28{29 {30 public static async Task RunAsync()31 {32 await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);33 using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false }))34 using (var page = await browser.NewPageAsync())35 {36 page.Dialog += async (sender, e) =>37 {38 Console.WriteLine(e.Message);39 await e.Dialog.DismissAsync();40 };41 await page.EvaluateExpressionAsync("confirm('This message is displayed by the onbeforeunload event')");42 await page.CloseAsync();43 }44 }45 }46}47using System;48using System.IO;49using System.Threading.Tasks;50using PuppeteerSharp;51{52 {53 public static async Task RunAsync()54 {55 await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);56 using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false }))57 using (var page = await browser.NewPageAsync())58 {59 page.Dialog += async (sender, e) =>60 {61 Console.WriteLine(e.Message);62 await e.Dialog.AcceptAsync("answer");63 };

Full Screen

Full Screen

DialogEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5 {6 public static void Main(string[] args)7 {8 Console.WriteLine("Hello World!");9 MainAsync(args).GetAwaiter().GetResult();10 }11 static async Task MainAsync(string[] args)12 {13 var browser = await Puppeteer.LaunchAsync(new LaunchOptions14 {15 });16 var page = await browser.NewPageAsync();17 page.Dialog += async (sender, e) =>18 {19 Console.WriteLine(e.Dialog.Message);20 await e.Dialog.AcceptAsync();21 };22 await page.EvaluateExpressionAsync("alert('1')");23 await page.EvaluateExpressionAsync("alert('2')");24 await page.EvaluateExpressionAsync("alert('3')");25 await page.EvaluateExpressionAsync("alert('4')");26 await page.EvaluateExpressionAsync("alert('5')");27 await page.EvaluateExpressionAsync("alert('6')");28 await page.EvaluateExpressionAsync("alert('7')");29 await page.EvaluateExpressionAsync("alert('8')");30 await page.EvaluateExpressionAsync("alert('9')");31 await page.EvaluateExpressionAsync("alert('10')");32 await page.EvaluateExpressionAsync("alert('11')");33 await page.EvaluateExpressionAsync("alert('12')");34 await page.EvaluateExpressionAsync("alert('13')");35 await page.EvaluateExpressionAsync("alert('14')");36 await page.EvaluateExpressionAsync("alert('15')");37 await page.EvaluateExpressionAsync("alert('16')");38 await page.EvaluateExpressionAsync("alert('17')");39 await page.EvaluateExpressionAsync("alert('18')");40 await page.EvaluateExpressionAsync("alert('19')");41 await page.EvaluateExpressionAsync("alert('20')");42 await page.EvaluateExpressionAsync("alert('21')");43 await page.EvaluateExpressionAsync("alert('22')");44 await page.EvaluateExpressionAsync("alert('23')");45 await page.EvaluateExpressionAsync("alert('24')");46 await page.EvaluateExpressionAsync("alert('25')");47 await page.EvaluateExpressionAsync("alert('26')");48 await page.EvaluateExpressionAsync("alert('27')");49 await page.EvaluateExpressionAsync("alert('28')");50 await page.EvaluateExpressionAsync("alert('29')");51 await page.EvaluateExpressionAsync("alert('30')");52 await page.EvaluateExpressionAsync("alert('31')");53 await page.EvaluateExpressionAsync("

Full Screen

Full Screen

DialogEventArgs

Using AI Code Generation

copy

Full Screen

1var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });2var page = await browser.NewPageAsync();3await page.ClickAsync("input[name='btnI']");4await page.WaitForNavigationAsync();5await page.WaitForSelectorAsync("input[name='q']");6await page.ClickAsync("input[name='q']");7await page.Keyboard.TypeAsync("PuppeteerSharp");8await page.Keyboard.PressAsync("Enter");9await page.WaitForNavigationAsync();10await page.WaitForSelectorAsync("div[class='g']");11await page.ClickAsync("div[class='g']");12await page.WaitForNavigationAsync();13await page.WaitForSelectorAsync("div[class='g']");14await page.ClickAsync("a[href='

Full Screen

Full Screen

DialogEventArgs

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System.Threading.Tasks;3{4 {5 static async Task Main(string[] args)6 {7 {8 Args = new string[] { "--no-sandbox" }9 };10 using (var browser = await Puppeteer.LaunchAsync(options))11 {12 var page = await browser.NewPageAsync();13 await page.EvaluateFunctionAsync("() => alert('This message is from PuppeteerSharp!')");14 page.Dialog += async (sender, e) =>15 {16 System.Console.WriteLine(e.Dialog.Message);17 await e.Dialog.AcceptAsync();18 };19 }20 }21 }22}

Full Screen

Full Screen

DialogEventArgs

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 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 page.Dialog += async (sender, e) =>13 {14 Console.WriteLine(e.Message);15 await e.Dialog.AcceptAsync();16 };17 await page.EvaluateFunctionAsync("() => alert('1')");18 }19 }20 }21}

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 method in DialogEventArgs

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful