How to use BoxModel class of PuppeteerSharp package

Best Puppeteer-sharp code snippet using PuppeteerSharp.BoxModel

ElementHandle.cs

Source:ElementHandle.cs Github

copy

Full Screen

...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),397                    Border = FromProtocolQuad(result.Model.Border),398                    Margin = FromProtocolQuad(result.Model.Margin),399                    Width = result.Model.Width,400                    Height = result.Model.Height401                };402        }403        /// <summary>404        ///Content frame for element handles referencing iframe nodes, or null otherwise.405        /// </summary>406        /// <returns>Resolves to the content frame</returns>407        public async Task<Frame> ContentFrameAsync()408        {409            var nodeInfo = await Client.SendAsync<DomDescribeNodeResponse>("DOM.describeNode", new DomDescribeNodeRequest410            {411                ObjectId = RemoteObject.ObjectId412            }).ConfigureAwait(false);413            return string.IsNullOrEmpty(nodeInfo.Node.FrameId) ? null : await _frameManager.GetFrameAsync(nodeInfo.Node.FrameId).ConfigureAwait(false);414        }415        /// <summary>416        /// Evaluates if the element is visible in the current viewport.417        /// </summary>418        /// <returns>A task which resolves to true if the element is visible in the current viewport.</returns>419        public Task<bool> IsIntersectingViewportAsync()420            => ExecutionContext.EvaluateFunctionAsync<bool>(421                @"async element =>422                {423                    const visibleRatio = await new Promise(resolve =>424                    {425                        const observer = new IntersectionObserver(entries =>426                        {427                            resolve(entries[0].intersectionRatio);428                            observer.disconnect();429                        });430                        observer.observe(element);431                    });432                    return visibleRatio > 0;433                }",434                this);435        /// <summary>436        /// Triggers a `change` and `input` event once all the provided options have been selected.437        /// If there's no `select` element matching `selector`, the method throws an exception.438        /// </summary>439        /// <example>440        /// <code>441        /// await handle.SelectAsync("blue"); // single selection442        /// await handle.SelectAsync("red", "green", "blue"); // multiple selections443        /// </code>444        /// </example>445        /// <param name="values">Values of options to select. If the `select` has the `multiple` attribute, all values are considered, otherwise only the first one is taken into account.</param>446        /// <returns>A task that resolves to an array of option values that have been successfully selected.</returns>447        public Task<string[]> SelectAsync(params string[] values)448            => EvaluateFunctionAsync<string[]>(449                @"(element, values) =>450                {451                    if (element.nodeName.toLowerCase() !== 'select')452                        throw new Error('Element is not a <select> element.');453                    const options = Array.from(element.options);454                    element.value = undefined;455                    for (const option of options) {456                        option.selected = values.includes(option.value);457                        if (option.selected && !element.multiple)458                            break;459                    }460                    element.dispatchEvent(new Event('input', { 'bubbles': true }));461                    element.dispatchEvent(new Event('change', { 'bubbles': true }));462                    return options.filter(option => option.selected).map(option => option.value);463                }",464                new[] { values });465        /// <summary>466        /// This method creates and captures a dragevent from the element.467        /// </summary>468        /// <param name="x">X coordinate</param>469        /// <param name="y">Y coordinate</param>470        /// <returns>A Task that resolves when the message was confirmed by the browser with the drag data</returns>471        public async Task<DragData> DragAsync(decimal x, decimal y)472        {473            if (!Page.IsDragInterceptionEnabled)474            {475                throw new PuppeteerException("Drag Interception is not enabled!");476            }477            await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);478            var start = await ClickablePointAsync().ConfigureAwait(false);479            return await Page.Mouse.DragAsync(start.X, start.Y, x, y).ConfigureAwait(false);480        }481        /// <summary>482        /// Dispatches a `dragenter` event.483        /// </summary>484        /// <param name="data">Drag data containing items and operations mask.</param>485        /// <returns>A Task that resolves when the message was confirmed by the browser</returns>486        public async Task DragEnterAsync(DragData data)487        {488            if (!Page.IsDragInterceptionEnabled)489            {490                throw new PuppeteerException("Drag Interception is not enabled!");491            }492            await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);493            var (x, y) = await ClickablePointAsync().ConfigureAwait(false);494            await Page.Mouse.DragEnterAsync(x, y, data).ConfigureAwait(false);495        }496        /// <summary>497        /// Dispatches a `dragover` event.498        /// </summary>499        /// <param name="data">Drag data containing items and operations mask.</param>500        /// <returns>A Task that resolves when the message was confirmed by the browser</returns>501        public async Task DragOverAsync(DragData data)502        {503            if (!Page.IsDragInterceptionEnabled)504            {505                throw new PuppeteerException("Drag Interception is not enabled!");506            }507            await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);508            var (x, y) = await ClickablePointAsync().ConfigureAwait(false);509            await Page.Mouse.DragOverAsync(x, y, data).ConfigureAwait(false);510        }511        /// <summary>512        /// Performs a dragenter, dragover, and drop in sequence.513        /// </summary>514        /// <param name="data">Drag data containing items and operations mask.</param>515        /// <returns>A Task that resolves when the message was confirmed by the browser</returns>516        public async Task DropAsync(DragData data)517        {518            if (!Page.IsDragInterceptionEnabled)519            {520                throw new PuppeteerException("Drag Interception is not enabled!");521            }522            await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);523            var (x, y) = await ClickablePointAsync().ConfigureAwait(false);524            await Page.Mouse.DropAsync(x, y, data).ConfigureAwait(false);525        }526        /// <summary>527        /// Performs a drag, dragenter, dragover, and drop in sequence.528        /// </summary>529        /// <param name="target">Target element</param>530        /// <param name="delay">If specified, is the time to wait between `dragover` and `drop` in milliseconds.</param>531        /// <returns>A Task that resolves when the message was confirmed by the browser</returns>532        public async Task DragAndDropAsync(ElementHandle target, int delay = 0)533        {534            if (target == null)535            {536                throw new ArgumentException("Target cannot be null", nameof(target));537            }538            if (!Page.IsDragInterceptionEnabled)539            {540                throw new PuppeteerException("Drag Interception is not enabled!");541            }542            await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);543            var (x, y) = await ClickablePointAsync().ConfigureAwait(false);544            var targetPoint = await target.ClickablePointAsync().ConfigureAwait(false);545            await Page.Mouse.DragAndDropAsync(x, y, targetPoint.X, targetPoint.Y, delay).ConfigureAwait(false);546        }547        private async Task<(decimal X, decimal Y)> ClickablePointAsync()548        {549            GetContentQuadsResponse result = null;550            var contentQuadsTask = Client.SendAsync<GetContentQuadsResponse>("DOM.getContentQuads", new DomGetContentQuadsRequest551            {552                ObjectId = RemoteObject.ObjectId553            });554            var layoutTask = Client.SendAsync<PageGetLayoutMetricsResponse>("Page.getLayoutMetrics");555            try556            {557                await Task.WhenAll(contentQuadsTask, layoutTask).ConfigureAwait(false);558                result = contentQuadsTask.Result;559            }560            catch (Exception ex)561            {562                _logger.LogError(ex, "Unable to get content quads");563            }564            if (result == null || result.Quads.Length == 0)565            {566                throw new PuppeteerException("Node is either not visible or not an HTMLElement");567            }568            // Filter out quads that have too small area to click into.569            var quads = result.Quads570                .Select(FromProtocolQuad)571                .Select(q => IntersectQuadWithViewport(q, layoutTask.Result))572                .Where(q => ComputeQuadArea(q.ToArray()) > 1);573            if (!quads.Any())574            {575                throw new PuppeteerException("Node is either not visible or not an HTMLElement");576            }577            // Return the middle point of the first quad.578            var quad = quads.First();579            var x = 0m;580            var y = 0m;581            foreach (var point in quad)582            {583                x += point.X;584                y += point.Y;585            }586            return (587                X: x / 4,588                Y: y / 4);589        }590        private IEnumerable<BoxModelPoint> IntersectQuadWithViewport(IEnumerable<BoxModelPoint> quad, PageGetLayoutMetricsResponse viewport)591            => quad.Select(point => new BoxModelPoint592            {593                X = Math.Min(Math.Max(point.X, 0), viewport.ContentSize.Width),594                Y = Math.Min(Math.Max(point.Y, 0), viewport.ContentSize.Height),595            });596        private async Task ScrollIntoViewIfNeededAsync()597        {598            var errorMessage = await EvaluateFunctionAsync<string>(599                @"async(element, pageJavascriptEnabled) => {600                    if (!element.isConnected)601                        return 'Node is detached from document';602                    if (element.nodeType !== Node.ELEMENT_NODE)603                        return 'Node is not of type HTMLElement';604                    // force-scroll if page's javascript is disabled.605                    if (!pageJavascriptEnabled) {606                        element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});607                        return null;608                    }609                    const visibleRatio = await new Promise(resolve => {610                    const observer = new IntersectionObserver(entries => {611                        resolve(entries[0].intersectionRatio);612                        observer.disconnect();613                    });614                    observer.observe(element);615                    });616                    if (visibleRatio !== 1.0)617                        element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});618                    return null;619                }",620                Page.JavascriptEnabled).ConfigureAwait(false);621            if (errorMessage != null)622            {623                throw new PuppeteerException(errorMessage);624            }625        }626        private async Task<BoxModelResponse> GetBoxModelAsync()627        {628            try629            {630                return await Client.SendAsync<BoxModelResponse>("DOM.getBoxModel", new DomGetBoxModelRequest631                {632                    ObjectId = RemoteObject.ObjectId633                }).ConfigureAwait(false);634            }635            catch (PuppeteerException ex)636            {637                Logger.LogError(ex.Message);638                return null;639            }640        }641        private BoxModelPoint[] FromProtocolQuad(decimal[] quad) => new[]642        {643            new BoxModelPoint { X = quad[0], Y = quad[1] },644            new BoxModelPoint { X = quad[2], Y = quad[3] },645            new BoxModelPoint { X = quad[4], Y = quad[5] },646            new BoxModelPoint { X = quad[6], Y = quad[7] }647        };648        private decimal ComputeQuadArea(BoxModelPoint[] quad)649        {650            var area = 0m;651            for (var i = 0; i < quad.Length; ++i)652            {653                var p1 = quad[i];654                var p2 = quad[(i + 1) % quad.Length];655                area += ((p1.X * p2.Y) - (p2.X * p1.Y)) / 2;656            }657            return Math.Abs(area);658        }659    }660}...

Full Screen

Full Screen

BoxModelTests.cs

Source:BoxModelTests.cs Github

copy

Full Screen

...6using Xunit.Abstractions;7namespace PuppeteerSharp.Tests.ElementHandleTests8{9    [Collection(TestConstants.TestFixtureCollectionName)]10    public class BoxModelTests : PuppeteerPageBaseTest11    {12        public BoxModelTests(ITestOutputHelper output) : base(output)13        {14        }15        [PuppeteerTest("elementhandle.spec.ts", "ElementHandle.boxModel", "should work")]16        [SkipBrowserFact(skipFirefox: true)]17        public async Task ShouldWork()18        {19            await Page.GoToAsync(TestConstants.ServerUrl + "/resetcss.html");20            // Step 1: Add Frame and position it absolutely.21            await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.ServerUrl + "/resetcss.html");22            await Page.EvaluateExpressionAsync(@"23              const frame = document.querySelector('#frame1');24              frame.style = `25                position: absolute;26                left: 1px;27                top: 2px;28              `;");29            // Step 2: Add div and position it absolutely inside frame.30            var frame = Page.FirstChildFrame();31            var divHandle = (ElementHandle)await frame.EvaluateFunctionHandleAsync(@"() => {32              const div = document.createElement('div');33              document.body.appendChild(div);34              div.style = `35                box-sizing: border-box;36                position: absolute;37                border-left: 1px solid black;38                padding-left: 2px;39                margin-left: 3px;40                left: 4px;41                top: 5px;42                width: 6px;43                height: 7px;44              `;45              return div;46            }");47            // Step 3: query div's boxModel and assert box values.48            var box = await divHandle.BoxModelAsync();49            Assert.Equal(6, box.Width);50            Assert.Equal(7, box.Height);51            Assert.Equal(new BoxModelPoint52            {53                X = 1 + 4, // frame.left + div.left54                Y = 2 + 555            }, box.Margin[0]);56            Assert.Equal(new BoxModelPoint57            {58                X = 1 + 4 + 3, // frame.left + div.left + div.margin-left59                Y = 2 + 560            }, box.Border[0]);61            Assert.Equal(new BoxModelPoint62            {63                X = 1 + 4 + 3 + 1, // frame.left + div.left + div.marginLeft + div.borderLeft64                Y = 2 + 565            }, box.Padding[0]);66            Assert.Equal(new BoxModelPoint67            {68                X = 1 + 4 + 3 + 1 + 2, // frame.left + div.left + div.marginLeft + div.borderLeft + dif.paddingLeft69                Y = 2 + 570            }, box.Content[0]);71        }72        [PuppeteerTest("elementhandle.spec.ts", "ElementHandle.boxModel", "should return null for invisible elements")]73        [SkipBrowserFact(skipFirefox: true)]74        public async Task ShouldReturnNullForInvisibleElements()75        {76            await Page.SetContentAsync("<div style='display:none'>hi</div>");77            var elementHandle = await Page.QuerySelectorAsync("div");78            Assert.Null(await elementHandle.BoxModelAsync());79        }80    }81}...

Full Screen

Full Screen

BoxModel.cs

Source:BoxModel.cs Github

copy

Full Screen

2{3    /// <summary>4    /// Represents boxes of the element.5    /// </summary>6    public class BoxModel7    {8        internal BoxModel()9        {10        }11        /// <summary>12        /// Gets the Content box13        /// </summary>14        public BoxModelPoint[] Content { get; internal set; }15        /// <summary>16        /// Gets the Padding box17        /// </summary>18        public BoxModelPoint[] Padding { get; internal set; }19        /// <summary>20        /// Gets the Border box21        /// </summary>22        public BoxModelPoint[] Border { get; internal set; }23        /// <summary>24        /// Gets the Margin box25        /// </summary>26        public BoxModelPoint[] Margin { get; internal set; }27        /// <summary>28        /// Gets the element's width29        /// </summary>30        public int Width { get; internal set; }31        /// <summary>32        /// Gets the element's height33        /// </summary>34        public int Height { get; internal set; }35    }36}...

Full Screen

Full Screen

BoxModelPoint.cs

Source:BoxModelPoint.cs Github

copy

Full Screen

1namespace PuppeteerSharp2{3    /// <summary>4    /// Represents a <see cref="BoxModel"/> point5    /// </summary>6    public struct BoxModelPoint7    {8        /// <summary>9        /// Gets the X point10        /// </summary>11        public decimal X { get; set; }12        /// <summary>13        /// Gets the y point14        /// </summary>15        public decimal Y { get; set; }16    }17}...

Full Screen

Full Screen

BoxModel

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5    {6        static async Task Main(string[] args)7        {8            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);9            var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false });10            var page = await browser.NewPageAsync();11            var boxModel = await page.EvaluateFunctionAsync<BoxModel>("() => document.querySelector('img').getBoxModel()");12            Console.WriteLine(boxModel.Margin[0].X);13        }14    }15}

Full Screen

Full Screen

BoxModel

Using AI Code Generation

copy

Full Screen

1var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {2    return element.getBoxModel();3}");4var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {5    return element.getBoxModel();6}");7var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {8    return element.getBoxModel();9}");10var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {11    return element.getBoxModel();12}");13var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {14    return element.getBoxModel();15}");16var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {17    return element.getBoxModel();18}");19var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {20    return element.getBoxModel();21}");22var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {23    return element.getBoxModel();24}");25var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {26    return element.getBoxModel();27}");28var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {29    return element.getBoxModel();30}");31var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {32    return element.getBoxModel();33}");34var boxModel = await page.QuerySelectorAsync(selector).EvaluateFunctionAsync<BoxModel>("element => {35    return element.getBoxModel();36}");

Full Screen

Full Screen

BoxModel

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5    {6        static async Task Main(string[] args)7        {8            var browser = await Puppeteer.LaunchAsync(new LaunchOptions9            {10            });11            var page = await browser.NewPageAsync();12            var boxModel = await page.EvaluateFunctionAsync<BoxModel>("() => document.querySelector('input').getBoxModel()");13            Console.WriteLine(boxModel);14            await browser.CloseAsync();15        }16    }17}18const puppeteer = require('puppeteer');19const util = require('util');20const fs = require('fs');21(async () => {22    const browser = await puppeteer.launch({23    });24    const page = await browser.newPage();25    const boxModel = await page.evaluate(() => document.querySelector('input').getBoxModel());26    console.log(util.inspect(boxModel, false, null, true));27    await browser.close();28})();29from playwright.sync_api import sync_playwright30with sync_playwright() as p:31    browser = p.chromium.launch(headless=False)32    page = browser.new_page()33    boxModel = page.evaluate("() => document.querySelector('input').getBoxModel()")34    print(boxModel)35    browser.close()

Full Screen

Full Screen

BoxModel

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using PuppeteerSharp;4{5    {6        static void Main(string[] args)7        {8            new Program().MainAsync().Wait();9        }10        public async Task MainAsync()11        {12            var browser = await Puppeteer.LaunchAsync(new LaunchOptions13            {14            });15            var page = await browser.NewPageAsync();16            await page.SetViewportAsync(new ViewPortOptions17            {18            });19            var element = await page.QuerySelectorAsync("body");20            var boxModel = await element.BoxModelAsync();21            Console.WriteLine(boxModel);22            await browser.CloseAsync();23        }24    }25}26BoxModel {27        { X: 0, Y: 0 },28        { X: 1080, Y: 0 },29        { X: 1080, Y: 720 },30        { X: 0, Y: 720 }31        { X: 0, Y: 0 },32        { X: 1080, Y: 0 },33        { X: 1080, Y: 720 },34        { X: 0, Y: 720 }35        { X: 0, Y: 0 },36        { X: 1080, Y: 0 },37        { X: 1080, Y: 720 },38        { X: 0, Y: 720 }39        { X: 0, Y: 0 },40        { X: 1080, Y: 0 },41        { X: 1080, Y: 720 },42        { X: 0, Y: 720 }43}44using System;45using System.Threading.Tasks;46using PuppeteerSharp;

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.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful