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