How to use BoundingBox class of PuppeteerSharp package

Best Puppeteer-sharp code snippet using PuppeteerSharp.BoundingBox

ElementHandle.cs

Source:ElementHandle.cs Github

copy

Full Screen

...111 {112 throw new ArgumentNullException(nameof(options));113 }114 var needsViewportReset = false;115 var boundingBox = await BoundingBoxAsync().ConfigureAwait(false);116 if (boundingBox == null)117 {118 throw new PuppeteerException("Node is either not visible or not an HTMLElement");119 }120 var viewport = Page.Viewport;121 if (viewport != null && (boundingBox.Width > viewport.Width || boundingBox.Height > viewport.Height))122 {123 var newRawViewport = JObject.FromObject(viewport);124 newRawViewport.Merge(new ViewPortOptions125 {126 Width = (int)Math.Max(viewport.Width, Math.Ceiling(boundingBox.Width)),127 Height = (int)Math.Max(viewport.Height, Math.Ceiling(boundingBox.Height))128 });129 await Page.SetViewportAsync(newRawViewport.ToObject<ViewPortOptions>(true)).ConfigureAwait(false);130 needsViewportReset = true;131 }132 await ExecutionContext.EvaluateFunctionAsync(133 @"function(element) {134 element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant'});135 }",136 this).ConfigureAwait(false);137 await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);138 boundingBox = await BoundingBoxAsync().ConfigureAwait(false);139 if (boundingBox == null)140 {141 throw new PuppeteerException("Node is either not visible or not an HTMLElement");142 }143 if (boundingBox.Width == 0)144 {145 throw new PuppeteerException("Node has 0 width.");146 }147 if (boundingBox.Height == 0)148 {149 throw new PuppeteerException("Node has 0 height.");150 }151 var getLayoutMetricsResponse = await Client.SendAsync<GetLayoutMetricsResponse>("Page.getLayoutMetrics").ConfigureAwait(false);152 var clip = boundingBox;153 clip.X += getLayoutMetricsResponse.LayoutViewport.PageX;154 clip.Y += getLayoutMetricsResponse.LayoutViewport.PageY;155 options.Clip = boundingBox.ToClip();156 var imageData = await Page.ScreenshotBase64Async(options).ConfigureAwait(false);157 if (needsViewportReset)158 {159 await Page.SetViewportAsync(viewport).ConfigureAwait(false);160 }161 return imageData;162 }163 /// <summary>164 /// Scrolls element into view if needed, and then uses <see cref="PuppeteerSharp.Page.Mouse"/> to hover over the center of the element.165 /// </summary>166 /// <returns>Task which resolves when the element is successfully hovered</returns>167 public async Task HoverAsync()168 {169 await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);170 var (x, y) = await ClickablePointAsync().ConfigureAwait(false);171 await Page.Mouse.MoveAsync(x, y).ConfigureAwait(false);172 }173 /// <summary>174 /// Scrolls element into view if needed, and then uses <see cref="PuppeteerSharp.Page.Mouse"/> to click in the center of the element.175 /// </summary>176 /// <param name="options">click options</param>177 /// <exception cref="PuppeteerException">if the element is detached from DOM</exception>178 /// <returns>Task which resolves when the element is successfully clicked</returns>179 public async Task ClickAsync(ClickOptions options = null)180 {181 await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);182 var (x, y) = await ClickablePointAsync().ConfigureAwait(false);183 await Page.Mouse.ClickAsync(x, y, options).ConfigureAwait(false);184 }185 /// <summary>186 /// Uploads files187 /// </summary>188 /// <param name="filePaths">Sets the value of the file input to these paths. Paths are resolved using <see cref="Path.GetFullPath(string)"/></param>189 /// <remarks>This method expects <c>elementHandle</c> to point to an <c>input element</c> <see href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"/> </remarks>190 /// <returns>Task</returns>191 public Task UploadFileAsync(params string[] filePaths) => UploadFileAsync(true, filePaths);192 /// <summary>193 /// Uploads files194 /// </summary>195 /// <param name="resolveFilePaths">Set to true to resolve paths using <see cref="Path.GetFullPath(string)"/></param>196 /// <param name="filePaths">Sets the value of the file input to these paths. Paths are resolved using <see cref="Path.GetFullPath(string)"/></param>197 /// <remarks>This method expects <c>elementHandle</c> to point to an <c>input element</c> <see href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"/> </remarks>198 /// <returns>Task</returns>199 public async Task UploadFileAsync(bool resolveFilePaths, params string[] filePaths)200 {201 var isMultiple = await EvaluateFunctionAsync<bool>("element => element.multiple").ConfigureAwait(false);202 if (!isMultiple && filePaths.Length > 1)203 {204 throw new PuppeteerException("Multiple file uploads only work with <input type=file multiple>");205 }206 var objectId = RemoteObject.ObjectId;207 var node = await Client.SendAsync<DomDescribeNodeResponse>("DOM.describeNode", new DomDescribeNodeRequest208 {209 ObjectId = RemoteObject.ObjectId210 }).ConfigureAwait(false);211 var backendNodeId = node.Node.BackendNodeId;212 if (!filePaths.Any() || filePaths == null)213 {214 await EvaluateFunctionAsync(@"(element) => {215 element.files = new DataTransfer().files;216 // Dispatch events for this case because it should behave akin to a user action.217 element.dispatchEvent(new Event('input', { bubbles: true }));218 element.dispatchEvent(new Event('change', { bubbles: true }));219 }").ConfigureAwait(false);220 }221 else222 {223 var files = resolveFilePaths ? filePaths.Select(Path.GetFullPath).ToArray() : filePaths;224 CheckForFileAccess(files);225 await Client.SendAsync("DOM.setFileInputFiles", new DomSetFileInputFilesRequest226 {227 ObjectId = objectId,228 Files = files,229 BackendNodeId = backendNodeId230 }).ConfigureAwait(false);231 }232 }233 private void CheckForFileAccess(string[] files)234 {235 foreach (var file in files)236 {237 try238 {239 File.Open(file, FileMode.Open).Dispose();240 }241 catch (Exception ex)242 {243 throw new PuppeteerException($"{files} does not exist or is not readable", ex);244 }245 }246 }247 /// <summary>248 /// Scrolls element into view if needed, and then uses <see cref="Touchscreen.TapAsync(decimal, decimal)"/> to tap in the center of the element.249 /// </summary>250 /// <exception cref="PuppeteerException">if the element is detached from DOM</exception>251 /// <returns>Task which resolves when the element is successfully tapped</returns>252 public async Task TapAsync()253 {254 await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);255 var (x, y) = await ClickablePointAsync().ConfigureAwait(false);256 await Page.Touchscreen.TapAsync(x, y).ConfigureAwait(false);257 }258 /// <summary>259 /// Calls <c>focus</c> <see href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus"/> on the element.260 /// </summary>261 /// <returns>Task</returns>262 public Task FocusAsync() => EvaluateFunctionAsync("element => element.focus()");263 /// <summary>264 /// Focuses the element, and sends a <c>keydown</c>, <c>keypress</c>/<c>input</c>, and <c>keyup</c> event for each character in the text.265 /// </summary>266 /// <param name="text">A text to type into a focused element</param>267 /// <param name="options">type options</param>268 /// <remarks>269 /// To press a special key, like <c>Control</c> or <c>ArrowDown</c> use <see cref="ElementHandle.PressAsync(string, PressOptions)"/>270 /// </remarks>271 /// <example>272 /// <code>273 /// elementHandle.TypeAsync("#mytextarea", "Hello"); // Types instantly274 /// elementHandle.TypeAsync("#mytextarea", "World", new TypeOptions { Delay = 100 }); // Types slower, like a user275 /// </code>276 /// An example of typing into a text field and then submitting the form:277 /// <code>278 /// var elementHandle = await page.GetElementAsync("input");279 /// await elementHandle.TypeAsync("some text");280 /// await elementHandle.PressAsync("Enter");281 /// </code>282 /// </example>283 /// <returns>Task</returns>284 public async Task TypeAsync(string text, TypeOptions options = null)285 {286 await FocusAsync().ConfigureAwait(false);287 await Page.Keyboard.TypeAsync(text, options).ConfigureAwait(false);288 }289 /// <summary>290 /// Focuses the element, and then uses <see cref="Keyboard.DownAsync(string, DownOptions)"/> and <see cref="Keyboard.UpAsync(string)"/>.291 /// </summary>292 /// <param name="key">Name of key to press, such as <c>ArrowLeft</c>. See <see cref="KeyDefinitions"/> for a list of all key names.</param>293 /// <param name="options">press options</param>294 /// <remarks>295 /// If <c>key</c> is a single character and no modifier keys besides <c>Shift</c> are being held down, a <c>keypress</c>/<c>input</c> event will also be generated. The <see cref="DownOptions.Text"/> option can be specified to force an input event to be generated.296 /// </remarks>297 /// <returns></returns>298 public async Task PressAsync(string key, PressOptions options = null)299 {300 await FocusAsync().ConfigureAwait(false);301 await Page.Keyboard.PressAsync(key, options).ConfigureAwait(false);302 }303 /// <summary>304 /// The method runs <c>element.querySelector</c> within the page. If no element matches the selector, the return value resolve to <c>null</c>.305 /// </summary>306 /// <param name="selector">A selector to query element for</param>307 /// <returns>Task which resolves to <see cref="ElementHandle"/> pointing to the frame element</returns>308 public async Task<ElementHandle> QuerySelectorAsync(string selector)309 {310 var handle = await EvaluateFunctionHandleAsync(311 "(element, selector) => element.querySelector(selector)",312 selector).ConfigureAwait(false);313 if (handle is ElementHandle element)314 {315 return element;316 }317 await handle.DisposeAsync().ConfigureAwait(false);318 return null;319 }320 /// <summary>321 /// Runs <c>element.querySelectorAll</c> within the page. If no elements match the selector, the return value resolve to <see cref="Array.Empty{T}"/>.322 /// </summary>323 /// <param name="selector">A selector to query element for</param>324 /// <returns>Task which resolves to ElementHandles pointing to the frame elements</returns>325 public async Task<ElementHandle[]> QuerySelectorAllAsync(string selector)326 {327 var arrayHandle = await EvaluateFunctionHandleAsync(328 "(element, selector) => element.querySelectorAll(selector)",329 selector).ConfigureAwait(false);330 var properties = await arrayHandle.GetPropertiesAsync().ConfigureAwait(false);331 await arrayHandle.DisposeAsync().ConfigureAwait(false);332 return properties.Values.OfType<ElementHandle>().ToArray();333 }334 /// <summary>335 /// A utility function to be used with <see cref="PuppeteerHandleExtensions.EvaluateFunctionAsync{T}(Task{JSHandle}, string, object[])"/>336 /// </summary>337 /// <param name="selector">A selector to query element for</param>338 /// <returns>Task which resolves to a <see cref="JSHandle"/> of <c>document.querySelectorAll</c> result</returns>339 public Task<JSHandle> QuerySelectorAllHandleAsync(string selector)340 => ExecutionContext.EvaluateFunctionHandleAsync(341 "(element, selector) => Array.from(element.querySelectorAll(selector))", this, selector);342 /// <summary>343 /// Evaluates the XPath expression relative to the elementHandle. If there's no such element, the method will resolve to <c>null</c>.344 /// </summary>345 /// <param name="expression">Expression to evaluate <see href="https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate"/></param>346 /// <returns>Task which resolves to an array of <see cref="ElementHandle"/></returns>347 public async Task<ElementHandle[]> XPathAsync(string expression)348 {349 var arrayHandle = await ExecutionContext.EvaluateFunctionHandleAsync(350 @"(element, expression) => {351 const document = element.ownerDocument || element;352 const iterator = document.evaluate(expression, element, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);353 const array = [];354 let item;355 while ((item = iterator.iterateNext()))356 array.push(item);357 return array;358 }",359 this,360 expression).ConfigureAwait(false);361 var properties = await arrayHandle.GetPropertiesAsync().ConfigureAwait(false);362 await arrayHandle.DisposeAsync().ConfigureAwait(false);363 return properties.Values.OfType<ElementHandle>().ToArray();364 }365 /// <summary>366 /// This method returns the bounding box of the element (relative to the main frame),367 /// or null if the element is not visible.368 /// </summary>369 /// <returns>The BoundingBox task.</returns>370 public async Task<BoundingBox> BoundingBoxAsync()371 {372 var result = await GetBoxModelAsync().ConfigureAwait(false);373 if (result == null)374 {375 return null;376 }377 var quad = result.Model.Border;378 var x = new[] { quad[0], quad[2], quad[4], quad[6] }.Min();379 var y = new[] { quad[1], quad[3], quad[5], quad[7] }.Min();380 var width = new[] { quad[0], quad[2], quad[4], quad[6] }.Max() - x;381 var height = new[] { quad[1], quad[3], quad[5], quad[7] }.Max() - y;382 return new BoundingBox(x, y, width, height);383 }384 /// <summary>385 /// returns boxes of the element, or <c>null</c> if the element is not visible. Box points are sorted clock-wise.386 /// </summary>387 /// <returns>Task BoxModel task.</returns>388 public async Task<BoxModel> BoxModelAsync()389 {390 var result = await GetBoxModelAsync().ConfigureAwait(false);391 return result == null392 ? null393 : new BoxModel394 {395 Content = FromProtocolQuad(result.Model.Content),396 Padding = FromProtocolQuad(result.Model.Padding),...

Full Screen

Full Screen

GhostCursor.cs

Source:GhostCursor.cs Github

copy

Full Screen

...45 }46 private static double OvershootThreshold = 500;47 private Func<Vector2, Vector2, bool> ShouldOvershoot = (Vector2 a, Vector2 b) => GhostMath.Magnitude(GhostMath.Direction(a, b)) > OvershootThreshold;48 49 private Vector2 GetRandomBoxPoint(BoundingBox box, BoxOptions? options = null)50 {51 // { x, y, width, height52 decimal paddingWidth = 0;53 decimal paddingHeight = 0;54 if (options?.PaddingPercentage != null && options?.PaddingPercentage > 0 && options?.PaddingPercentage < 100)55 {56 paddingWidth = box.Width * options.PaddingPercentage / 100;57 paddingHeight = box.Height * options.PaddingPercentage / 100;58 }59 return new Vector260 {61 X = Convert.ToSingle(box.X + (paddingWidth / 2) + Convert.ToDecimal(Randomizer.NextDouble()) * (box.Width - paddingWidth)),62 Y = Convert.ToSingle(box.Y + (paddingHeight / 2) + Convert.ToDecimal(Randomizer.NextDouble()) * (box.Height - paddingHeight))63 };64 }65 // Get a random point on a browser window66 public async Task<Vector2> GetRandomPagePoint(Page page)67 {68 string targetId = page.Target.TargetId;69 dynamic window = await page.Client.SendAsync("Browser.getWindowForTarget", new { targetId });70 var width = Convert.ToDecimal(window.bounds.width);71 var height = Convert.ToDecimal(window.bounds.height);72 return GetRandomBoxPoint(new BoundingBox { X = Convert.ToDecimal(GhostMath.Origin.X), Y = Convert.ToDecimal(GhostMath.Origin.Y), Width = width, Height = height });73 }74 // Using this method to get correct position of Inline elements (elements like <a>)75 private async Task<BoundingBox?> GetElementBox(Page page, ElementHandle element, bool relativeToMainFrame = true)76 {77 if (element.RemoteObject.ObjectId == null)78 {79 return null;80 }81 dynamic quads;82 try83 {84 quads = await page.Client.SendAsync("DOM.getContentQuads", new { objectId = element.RemoteObject.ObjectId });85 }86 catch87 {88 // console.debug('Quads not found, trying regular boundingBox')89 return await element.BoundingBoxAsync();90 }91 var elementBox = new BoundingBox92 {93 X = quads.quads[0][0],94 Y = quads.quads[0][1],95 Width = quads.quads[0][4] - quads.quads[0][0],96 Height = quads.quads[0][5] - quads.quads[0][1]97 };98 if (elementBox == null)99 {100 return null;101 }102 if (!relativeToMainFrame)103 {104 Frame elementFrame = element.ExecutionContext.Frame;105 var iframes = await elementFrame.ParentFrame.XPathAsync("//iframe");106 ElementHandle? frame = null;107 if (iframes != null)108 {109 foreach (var iframe in iframes)110 {111 if ((await iframe.ContentFrameAsync()) == elementFrame)112 frame = iframe;113 }114 }115 if (frame != null)116 {117 var boundingBox = await frame.BoundingBoxAsync();118 elementBox.X = boundingBox != null ? elementBox.X - boundingBox.X : elementBox.X;119 elementBox.Y = boundingBox != null ? elementBox.Y - boundingBox.Y : elementBox.Y;120 }121 }122 return elementBox;123 }124 public List<Vector2> Path(Vector2 start, BoundingBox end, double? spreadOverride = null)125 {126 // var defaultWidth = 100;127 var minSteps = 25;128 var width = end.Width; // : defaultWidth; (if Vector2)129 var curve = GhostMath.BezierCurve(start, new Vector2(Convert.ToSingle(end.X), Convert.ToSingle(end.Y)), spreadOverride);130 var length = curve.Length * 0.8;131 var baseTime = Randomizer.NextDouble() * minSteps;132 var steps = Math.Ceiling((Math.Log(Fitts(length, Convert.ToDouble(width)) + 1, 2) + baseTime) * 3);133 // what is the equivalent of 134 var re = curve.Reduce(steps / 1000);135 List<Vector2> lookupTable = re.SelectMany(r => r.Points).ToList();136 return ClampPositive(lookupTable);137 }138 public List<Vector2> ClampPositive(List<Vector2> vectors)139 {140 Func<float, float> clamp0 = (float elem) => Math.Max(0, elem);141 return vectors.Select(vector =>142 {143 return new Vector2 { X = clamp0(vector.X), Y = clamp0(vector.Y) };144 }).ToList();145 }146 private BoundingBox VectorToBoundingboxDefaultWidth(Vector2 vector)147 {148 return new BoundingBox149 {150 X = Convert.ToDecimal(vector.X),151 Y = Convert.ToDecimal(vector.X),152 Width = 100153 };154 }155 private bool Moving = false;156 #region CreateCursor Helpers157 /// <summary>158 /// Move the mouse over a number of vectors159 /// </summary>160 private async Task<Vector2> tracePath(List<Vector2> vectors, bool abortOnMove, Page page, Vector2 previous)161 {162 foreach (var v in vectors)163 {164 try165 {166 // In case this is called from random mouse movements and the users wants to move the mouse, abort167 if (abortOnMove && this.Moving)168 {169 return previous;170 }171 await page.Mouse.MoveAsync(Convert.ToDecimal(v.X), Convert.ToDecimal(v.Y));172 previous = v;173 }174 catch (Exception ex)175 {176 // Exit function if the browser is no longer connected177 if (!page.Browser.IsConnected)178 return previous;179 // console.debug('Warning: could not move mouse, error message:', ex.Message)180 }181 }182 return previous;183 }184 // Start random mouse movements. Function recursively calls itself185 private async Task<Vector2> randomMove(Page page, Vector2 previous, MoveOptions? options = null)186 {187 try188 {189 if (!this.Moving)190 {191 var rand = await GetRandomPagePoint(page);192 previous = await tracePath(Path(previous, VectorToBoundingboxDefaultWidth(rand)), true, page, previous);193 previous = rand;194 }195 if (options?.MoveDelay != null && options.MoveDelay >= 0)196 {197 await Task.Delay(Convert.ToInt32(Randomizer.NextDouble() * options.MoveDelay));198 }199 else200 {201 await Task.Delay(Convert.ToInt32(Randomizer.NextDouble() * 2000));// 2s by default202 }203 previous = await randomMove(page, previous); // fire and forget, recursive function204 }205 catch206 {207 // console.debug('Warning: stopping random mouse movements')208 }209 return previous;210 }211 #endregion212 public async Task<GhostCursorActions> CreateCursor(Page page, Vector2 start, bool performRandomMoves = false)213 {214 // this is kind of arbitrary, not a big fan but it seems to work215 var overshootSpread = 10;216 var overshootRadius = 120;217 Vector2 previous = start;218 // Initial state: mouse is not moving219 //bool moving = false; 220 Action<bool> toggleRandomMove = random => { this.Moving = !random; };221 Func<ElementHandle, MoveOptions, Task> move = async (ElementHandle selector, MoveOptions options) =>222 {223 toggleRandomMove(false);224 ElementHandle elem = selector;225 // Make sure the object is in view226 if (elem.RemoteObject?.ObjectId != null)227 {228 try229 {230 await page.Client.SendAsync("DOM.scrollIntoViewIfNeeded", new { objectId = elem.RemoteObject.ObjectId });231 }232 catch233 {234 // use regular JS scroll method as a fallback235 await elem.EvaluateFunctionAsync("e => e.scrollIntoView({ behavior: 'smooth' })");236 }237 }238 var box = await GetElementBox(page, elem);239 /*if (box == null)240 {241 // not working on puppeterr sharp ?242 box = await elem.EvaluateFunctionAsync("e => e.getBoundingClientRect()");243 }*/244 var destination = GetRandomBoxPoint(box, options);245 var dimensions = new { box.Height, box.Width };246 var overshooting = ShouldOvershoot(previous, destination);247 var to = overshooting ? GhostMath.Overshoot(destination, overshootRadius) : destination;248 previous = await tracePath(Path(previous, VectorToBoundingboxDefaultWidth(to)), false, page, previous);249 if (overshooting)250 {251 var correction = Path(to, new BoundingBox { Height = box.Height, Width = box.Width, X = Convert.ToDecimal(destination.X), Y = Convert.ToDecimal(destination.Y) }, overshootSpread);252 previous = await tracePath(correction, false, page, previous);253 }254 previous = destination;255 toggleRandomMove(true);256 };257 GhostCursorActions actions = new GhostCursorActions258 {259 ToggleRandomMove = (random) => { this.Moving = !random; },260 Click = async (selector, options) =>261 {262 toggleRandomMove(false);263 if (selector != null)264 {265 await move(selector, options);...

Full Screen

Full Screen

ClickerBot.cs

Source:ClickerBot.cs Github

copy

Full Screen

...105 await UpdateWrongQuizAnswers(frame);106 var highImportanceButtons = await frame.QuerySelectorAllAsync(".question-example-overlay:not([hidden='hidden']) .example-buttons .button:not(.is-disabled)");107 foreach (var buttonHandle in highImportanceButtons)108 {109 var boundingBox = await buttonHandle.BoundingBoxAsync();110 var isVisible = boundingBox != null && boundingBox.Width > 0 && boundingBox.Height > 0;111 if (!isVisible)112 continue;113 var buttonText = await frame.GetInnerText(buttonHandle);114 var isCandidate = new[] { "schließen" }.Any(x => buttonText.ToLower().Contains(x));115 if (isCandidate)116 return buttonHandle;117 }118 var decisionTextHandle = await frame.QuerySelectorAllAsync(".decision-wrapper .text-column");119 if (decisionTextHandle.Any())120 {121 var decisionText = await frame.EvaluateFunctionAsync<string>("el => el.innerText", decisionTextHandle.First());122 var decisionHash = decisionText.GetHashCode();123 var choices = await frame.QuerySelectorAllAsync(".content-region .decision-choices li.choice button:not(.is-disabled)");124 Question decision = null;125 if (_decisions.Questions.All(x => x.Hash != decisionHash))126 {127 decision = new Question { Hash = decisionHash };128 foreach (var elementHandle in choices)129 {130 var choiceText = await frame.GetInnerText(elementHandle);131 decision.Answers.Add(new Answer { Result = null, Text = choiceText });132 }133 _decisions.Questions.Add(decision);134 }135 else136 decision = _decisions.Questions.Single(x => x.Hash == decisionHash);137 var bestAnswer = decision.GetBestAnswer();138 if (bestAnswer != null)139 {140 foreach (var elementHandle in choices)141 {142 var boundingBox = await elementHandle.BoundingBoxAsync();143 var isVisible = boundingBox != null && boundingBox.Width > 0 && boundingBox.Height > 0;144 if (!isVisible)145 continue;146 var choiceText = await frame.EvaluateFunctionAsync<string>("e => e.innerText", elementHandle);147 if (choiceText == bestAnswer)148 return elementHandle;149 }150 }151 }152 var quizChoices = await frame.QuerySelectorAllAsync(".content-region .question-choices li.choice button:not(.is-disabled)");153 if (quizChoices.Any())154 {155 var contentHash = await GetQuizHash(frame);156 var bestAnswer = _quiz.Questions.Single(x => x.Hash == contentHash).GetBestAnswer();157 if (bestAnswer != null)158 {159 foreach (var elementHandle in quizChoices)160 {161 var boundingBox = await elementHandle.BoundingBoxAsync();162 var isVisible = boundingBox != null && boundingBox.Width > 0 && boundingBox.Height > 0;163 if (!isVisible)164 continue;165 var choiceText = await frame.GetInnerText(elementHandle);166 if (choiceText == bestAnswer)167 return elementHandle;168 }169 }170 }171 var regularButtons = await frame.QuerySelectorAllAsync(".content-region button.action:not(.is-disabled)");172 var exampleButtons = await frame.QuerySelectorAllAsync(".example-button-container .button:not(.is-disabled)");173 var buttonHandles = regularButtons.Concat(exampleButtons).Concat(highImportanceButtons);174 foreach (var buttonHandle in buttonHandles)175 {176 var boundingBox = await buttonHandle.BoundingBoxAsync();177 var isVisible = boundingBox != null && boundingBox.Width > 0 && boundingBox.Height > 0;178 if (!isVisible)179 continue;180 var buttonText = await frame.GetInnerText(buttonHandle);181 var isCandidate = new[] { "beginnen", "weiter", "mehr", "anzeigen", "schließen", "wiederholen" }.Any(x => buttonText.ToLower().Contains(x));182 if (isCandidate)183 return buttonHandle;184 }185 var currentCalloutHandles = await frame.QuerySelectorAllAsync(".callout-trigger.is-current");186 if (!currentCalloutHandles.Any())187 {188 var calloutHandles = await frame.QuerySelectorAllAsync(".callout-trigger.is-unlocked:not(.is-current)");189 if (calloutHandles.Any())190 return calloutHandles.First();191 }192 else193 {194 var next = await frame.QuerySelectorAllAsync(".callout-navigation.next a");195 if (next.Any())196 {197 var boundingBox = await next.First().BoundingBoxAsync();198 var isVisible = boundingBox != null && boundingBox.Width > 0 && boundingBox.Height > 0;199 if (isVisible)200 return next.First();201 }202 }203 var bannerHandles = await frame.QuerySelectorAllAsync(".banner-wrapper.is-unlocked");204 if (bannerHandles.Any())205 return bannerHandles.First();206 var explorerHandles = await frame.QuerySelectorAllAsync(".explorer-trigger.is-unlocked:not(.is-completed)");207 if (explorerHandles.Any())208 return explorerHandles.First();209 var flashCardHandles = await frame.QuerySelectorAllAsync(".content-region article.flash-card:not(.flash-card-flipped) .flash-card-side");210 if (flashCardHandles.Any())211 return flashCardHandles.First();...

Full Screen

Full Screen

BoundingBoxTests.cs

Source:BoundingBoxTests.cs Github

copy

Full Screen

...6using Xunit.Abstractions;7namespace PuppeteerSharp.Tests.ElementHandleTests8{9 [Collection(TestConstants.TestFixtureCollectionName)]10 public class BoundingBoxTests : PuppeteerPageBaseTest11 {12 public BoundingBoxTests(ITestOutputHelper output) : base(output)13 {14 }15 [PuppeteerTest("elementhandle.spec.ts", "ElementHandle.boundingBox", "should work")]16 [SkipBrowserFact(skipFirefox: true)]17 public async Task ShouldWork()18 {19 await Page.SetViewportAsync(new ViewPortOptions20 {21 Width = 500,22 Height = 50023 });24 await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html");25 var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(13)");26 var box = await elementHandle.BoundingBoxAsync();27 Assert.Equal(new BoundingBox(100, 50, 50, 50), box);28 }29 [PuppeteerTest("elementhandle.spec.ts", "ElementHandle.boundingBox", "should handle nested frames")]30 [SkipBrowserFact(skipFirefox: true)]31 public async Task ShouldHandleNestedFrames()32 {33 await Page.SetViewportAsync(new ViewPortOptions34 {35 Width = 500,36 Height = 50037 });38 await Page.GoToAsync(TestConstants.ServerUrl + "/frames/nested-frames.html", WaitUntilNavigation.Networkidle0);39 var childFrame = Page.Frames.First(f => f.Url.Contains("two-frames.html"));40 var nestedFrame = childFrame.ChildFrames.Last();41 var elementHandle = await nestedFrame.QuerySelectorAsync("div");42 var box = await elementHandle.BoundingBoxAsync();43 if (TestConstants.IsChrome)44 {45 Assert.Equal(new BoundingBox(28, 182, 264, 18), box);46 }47 else48 {49 Assert.Equal(new BoundingBox(28, 182, 254, 18), box);50 }51 }52 [PuppeteerTest("elementhandle.spec.ts", "ElementHandle.boundingBox", "should return null for invisible elements")]53 [SkipBrowserFact(skipFirefox: true)]54 public async Task ShouldReturnNullForInvisibleElements()55 {56 await Page.SetContentAsync("<div style='display:none'>hi</div>");57 var elementHandle = await Page.QuerySelectorAsync("div");58 Assert.Null(await elementHandle.BoundingBoxAsync());59 }60 [PuppeteerTest("elementhandle.spec.ts", "ElementHandle.boundingBox", "should force a layout")]61 [SkipBrowserFact(skipFirefox: true)]62 public async Task ShouldForceALayout()63 {64 await Page.SetViewportAsync(new ViewPortOptions { Width = 500, Height = 500 });65 await Page.SetContentAsync("<div style='width: 100px; height: 100px'>hello</div>");66 var elementHandle = await Page.QuerySelectorAsync("div");67 await Page.EvaluateFunctionAsync("element => element.style.height = '200px'", elementHandle);68 var box = await elementHandle.BoundingBoxAsync();69 Assert.Equal(new BoundingBox(8, 8, 100, 200), box);70 }71 [PuppeteerTest("elementhandle.spec.ts", "ElementHandle.boundingBox", "should work with SVG nodes")]72 [SkipBrowserFact(skipFirefox: true)]73 public async Task ShouldWworkWithSVGNodes()74 {75 await Page.SetContentAsync(@"76 <svg xmlns=""http://www.w3.org/2000/svg"" width=""500"" height=""500"">77 <rect id=""theRect"" x=""30"" y=""50"" width=""200"" height=""300""></rect>78 </svg>79 ");80 var element = await Page.QuerySelectorAsync("#therect");81 var pptrBoundingBox = await element.BoundingBoxAsync();82 var webBoundingBox = await Page.EvaluateFunctionAsync<BoundingBox>(@"e =>83 {84 const rect = e.getBoundingClientRect();85 return { x: rect.x, y: rect.y, width: rect.width, height: rect.height};86 }", element);87 Assert.Equal(webBoundingBox, pptrBoundingBox);88 }89 }90}...

Full Screen

Full Screen

Chromium.cs

Source:Chromium.cs Github

copy

Full Screen

...10 public async Task ScreenshotSelectorAsync (Page page, string selector, string pathFilePNG, ILogger log) {11 try {12 log.LogInformation ("Begin - ScreenshotSelectorAsync()");13 ElementHandle bodyHandle = await page.WaitForSelectorAsync ("body");14 BoundingBox bounding_box = await bodyHandle.BoundingBoxAsync ();15 await page.SetViewportAsync (new ViewPortOptions {16 Width = Convert.ToInt32 (Math.Max (page.Viewport.Width, Math.Ceiling (bounding_box.Width))),17 Height = Convert.ToInt32 (Math.Max (page.Viewport.Height, Math.Ceiling (bounding_box.Height))),18 });19 ElementHandle element = await page.WaitForSelectorAsync (selector);20 await element.ScreenshotAsync (pathFilePNG);21 await element.DisposeAsync ();22 log.LogInformation ("End - ScreenshotSelectorAsync()");23 } catch (Exception ex) {24 log.LogError ("Erro: {0}", ex.Message);25 }26 }27 public async Task InputSelectorAsync (Page page, string selector, string dataInput, ILogger log) {28 try {...

Full Screen

Full Screen

BoundingBox.cs

Source:BoundingBox.cs Github

copy

Full Screen

...3using Newtonsoft.Json;4namespace PuppeteerSharp5{6 /// <summary>7 /// Bounding box data returned by <see cref="ElementHandle.BoundingBoxAsync"/>.8 /// </summary>9 public class BoundingBox : IEquatable<BoundingBox>10 {11 /// <summary>12 /// The x coordinate of the element in pixels.13 /// </summary>14 /// <value>The x.</value>15 [JsonProperty("x")]16 public decimal X { get; set; }17 /// <summary>18 /// The y coordinate of the element in pixels.19 /// </summary>20 /// <value>The y.</value>21 [JsonProperty("y")]22 public decimal Y { get; set; }23 /// <summary>24 /// The width of the element in pixels.25 /// </summary>26 /// <value>The width.</value>27 [JsonProperty("width")]28 public decimal Width { get; set; }29 /// <summary>30 /// The height of the element in pixels.31 /// </summary>32 /// <value>The height.</value>33 [JsonProperty("height")]34 public decimal Height { get; set; }35 /// <summary>36 /// Initializes a new instance of the <see cref="T:PuppeteerSharp.BoundingBox"/> class.37 /// </summary>38 public BoundingBox() { }39 /// <summary>40 /// Initializes a new instance of the <see cref="BoundingBox"/> class.41 /// </summary>42 /// <param name="x">The x coordinate.</param>43 /// <param name="y">The y coordinate.</param>44 /// <param name="width">Width.</param>45 /// <param name="height">Height.</param>46 public BoundingBox(decimal x, decimal y, decimal width, decimal height)47 {48 X = x;49 Y = y;50 Width = width;51 Height = height;52 }53 internal Clip ToClip()54 {55 return new Clip56 {57 X = X,58 Y = Y,59 Width = Width,60 Height = Height61 };62 }63 /// <inheritdoc/>64 public override bool Equals(object obj)65 {66 if (obj == null && GetType() != obj.GetType())67 {68 return false;69 }70 return Equals((BoundingBox)obj);71 }72 /// <summary>73 /// Determines whether the specified <see cref="PuppeteerSharp.BoundingBox"/> is equal to the current <see cref="T:PuppeteerSharp.BoundingBox"/>.74 /// </summary>75 /// <param name="obj">The <see cref="PuppeteerSharp.BoundingBox"/> to compare with the current <see cref="T:PuppeteerSharp.BoundingBox"/>.</param>76 /// <returns><c>true</c> if the specified <see cref="PuppeteerSharp.BoundingBox"/> is equal to the current77 /// <see cref="T:PuppeteerSharp.BoundingBox"/>; otherwise, <c>false</c>.</returns>78 public bool Equals(BoundingBox obj)79 => obj != null &&80 obj.X == X &&81 obj.Y == Y &&82 obj.Height == Height &&83 obj.Width == Width;84 /// <inheritdoc/>85 public override int GetHashCode()86 => X.GetHashCode() * 39787 ^ Y.GetHashCode() * 39788 ^ Width.GetHashCode() * 39789 ^ Height.GetHashCode() * 397;90 }91}...

Full Screen

Full Screen

IPuppeteerBrowser.cs

Source:IPuppeteerBrowser.cs Github

copy

Full Screen

...38 /// <param name="defaultCountryCode">The country code tu return default details.</param>39 /// <returns>The instance of <see cref="IpDetails"></see></returns>40 Task<IpDetails> GetIpDetails(string ipFetcherUrl, string defaultCountryCode);41 Task CloseAsync();42 Task<Page> MouseClickAndGetPage(BoundingBox box, Page page);43 }44}...

Full Screen

Full Screen

Clip.cs

Source:Clip.cs Github

copy

Full Screen

...4{5 /// <summary>6 /// Clip data.7 /// </summary>8 /// <seealso cref="BoundingBox.ToClip"/>9 /// <seealso cref="ScreenshotOptions.Clip"/>10 public class Clip11 {12 /// <summary>13 /// x-coordinate of top-left corner of clip area.14 /// </summary>15 /// <value>The x.</value>16 [JsonProperty("x")]17 public decimal X { get; set; }18 /// <summary>19 /// y-coordinate of top-left corner of clip area.20 /// </summary>21 /// <value>The y.</value>22 [JsonProperty("y")]...

Full Screen

Full Screen

BoundingBox

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8 {9 static void Main(string[] args)10 {11 var task = MainAsync();12 task.Wait();13 }14 static async Task MainAsync()15 {16 {17 };18 var browser = await Puppeteer.LaunchAsync(options);19 var page = await browser.NewPageAsync();20 var element = await page.QuerySelectorAsync("input[name='q']");21 var box = await element.BoundingBoxAsync();22 Console.WriteLine("Element bounding box is: {0}", box);23 await browser.CloseAsync();24 }25 }26}

Full Screen

Full Screen

BoundingBox

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Threading.Tasks;4{5 {6 static async Task Main(string[] args)7 {8 await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);9 using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false }))10 using (var page = await browser.NewPageAsync())11 {12 var element = await page.QuerySelectorAsync("input[name='q']");13 var box = await element.BoundingBoxAsync();14 Console.WriteLine(box.X);15 Console.WriteLine(box.Y);16 Console.WriteLine(box.Width);17 Console.WriteLine(box.Height);18 }19 }20 }21}22I am trying to get the bounding box of an element on a page using PuppeteerSharp. I am using the BoundingBoxAsync() method to do this. However, the output is always 0. I am not sure what I am doing wrong. I am using the latest version of PuppeteerSharp. Here is the code I am using:23I am trying to get the bounding box of an element on a page using PuppeteerSharp. I am using the BoundingBoxAsync() method to do this. However, the output is always 0. I am not sure what I am doing wrong. I am using the latest version of PuppeteerSharp. Here is the code I am using:24await page.SetViewportAsync(new ViewPortOptions25{26});27await page.SetViewportAsync(new ViewPortOptions28{29});30await page.SetViewportAsync(new ViewPort

Full Screen

Full Screen

BoundingBox

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using PuppeteerSharp;3using PuppeteerSharp;4using PuppeteerSharp;5using PuppeteerSharp;6using PuppeteerSharp;7using PuppeteerSharp;8using PuppeteerSharp;9using PuppeteerSharp;10using PuppeteerSharp;11using PuppeteerSharp;12using PuppeteerSharp;13using PuppeteerSharp;14using PuppeteerSharp;15using PuppeteerSharp;16using PuppeteerSharp;17using PuppeteerSharp;18using PuppeteerSharp;19using PuppeteerSharp;20using PuppeteerSharp;

Full Screen

Full Screen

BoundingBox

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Threading.Tasks;6{7 {8 static void Main(string[] args)9 {10 MainAsync().Wait();11 }12 static async Task MainAsync()13 {14 var options = new LaunchOptions();15 options.Headless = false;16 options.DefaultViewport = null;17 options.Args = new string[] { "--start-maximized" };18 using (var browser = await Puppeteer.LaunchAsync(options))19 using (var page = await browser.NewPageAsync())20 {21 await page.ScreenshotAsync("google.png");22 }23 }24 }25}26using PuppeteerSharp;27using System;28using System.Collections.Generic;29using System.Linq;30using System.Threading.Tasks;31{32 {33 static void Main(string[] args)34 {35 MainAsync().Wait();36 }37 static async Task MainAsync()38 {39 var options = new LaunchOptions();40 options.Headless = false;41 options.DefaultViewport = null;42 options.Args = new string[] { "--start-maximized" };43 using (var browser = await Puppeteer.LaunchAsync(options))44 using (var page = await browser.NewPageAsync())45 {46 await page.ScreenshotAsync("google.png");47 }48 }49 }50}51using PuppeteerSharp;52using System;53using System.Collections.Generic;54using System.Linq;55using System.Threading.Tasks;56{57 {58 static void Main(string[] args)59 {60 MainAsync().Wait();61 }62 static async Task MainAsync()63 {64 var options = new LaunchOptions();65 options.Headless = false;66 options.DefaultViewport = null;67 options.Args = new string[] { "--start-maximized" };68 using (var browser = await Puppeteer.LaunchAsync(options))69 using (var page = await browser.NewPageAsync())70 {71 await page.ScreenshotAsync("

Full Screen

Full Screen

BoundingBox

Using AI Code Generation

copy

Full Screen

1using PuppeteerSharp;2{3 public async Task MyMethod()4 {5 var browser = await Puppeteer.LaunchAsync(new LaunchOptions6 {7 });8 var page = await browser.NewPageAsync();9 var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {10 return document.querySelector('input').getBoundingClientRect();11 }");12 await browser.CloseAsync();13 }14}15using PuppeteerSharp;16{17 public async Task MyMethod()18 {19 var browser = await Puppeteer.LaunchAsync(new LaunchOptions20 {21 });22 var page = await browser.NewPageAsync();23 var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {24 return document.querySelector('input').getBoundingClientRect();25 }");26 await browser.CloseAsync();27 }28}29using PuppeteerSharp;30{31 public async Task MyMethod()32 {33 var browser = await Puppeteer.LaunchAsync(new LaunchOptions34 {35 });36 var page = await browser.NewPageAsync();37 var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {38 return document.querySelector('input').getBoundingClientRect();39 }");40 await browser.CloseAsync();41 }42}43using PuppeteerSharp;44{45 public async Task MyMethod()46 {47 var browser = await Puppeteer.LaunchAsync(new LaunchOptions48 {49 });50 var page = await browser.NewPageAsync();51 var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {52 return document.querySelector('input').getBoundingClientRect();53 }");54 await browser.CloseAsync();55 }56}57using PuppeteerSharp;

Full Screen

Full Screen

BoundingBox

Using AI Code Generation

copy

Full Screen

1var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {2 return document.querySelector('div').getBoundingClientRect();3}");4Console.WriteLine(box.X);5var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {6 return document.querySelector('div').getBoundingClientRect();7}");8Console.WriteLine(box.X);9var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {10 return document.querySelector('div').getBoundingClientRect();11}");12Console.WriteLine(box.X);13var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {14 return document.querySelector('div').getBoundingClientRect();15}");16Console.WriteLine(box.X);17var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {18 return document.querySelector('div').getBoundingClientRect();19}");20Console.WriteLine(box.X);21var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {22 return document.querySelector('div').getBoundingClientRect();23}");24Console.WriteLine(box.X);25var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {26 return document.querySelector('div').getBoundingClientRect();27}");28Console.WriteLine(box.X);29var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {30 return document.querySelector('div').getBoundingClientRect();31}");32Console.WriteLine(box.X);33var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {34 return document.querySelector('div').getBoundingClientRect();35}");36Console.WriteLine(box.X);37var box = await page.EvaluateFunctionAsync<BoundingBox>("() => {38 return document.querySelector('div').getBoundingClientRect();39}");40Console.WriteLine(box.X);

Full Screen

Full Screen

BoundingBox

Using AI Code Generation

copy

Full Screen

1var bb = new BoundingBox();2bb.x = 2;3bb.y = 3;4bb.width = 4;5bb.height = 5;6Console.WriteLine(bb.x + bb.y + bb.width + bb.height);7var bb = new BoundingBox();8bb.x = 2;9bb.y = 3;10bb.width = 4;11bb.height = 5;12Console.WriteLine(bb.x + bb.y + bb.width + bb.height);13var bb = new BoundingBox();14bb.x = 2;15bb.y = 3;16bb.width = 4;17bb.height = 5;18Console.WriteLine(bb.x + bb.y + bb.width + bb.height);19var bb = new BoundingBox();20bb.x = 2;21bb.y = 3;22bb.width = 4;23bb.height = 5;24Console.WriteLine(bb.x + bb.y + bb.width + bb.height);25var bb = new BoundingBox();26bb.x = 2;27bb.y = 3;28bb.width = 4;29bb.height = 5;30Console.WriteLine(bb.x + bb.y + bb.width + bb.height);31var bb = new BoundingBox();32bb.x = 2;33bb.y = 3;34bb.width = 4;35bb.height = 5;36Console.WriteLine(bb.x + bb.y + bb.width + bb.height);37var bb = new BoundingBox();38bb.x = 2;39bb.y = 3;40bb.width = 4;

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 BoundingBox

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful