How to use QuerySelectorAsync method of Microsoft.Playwright.Core.Frame class

Best Playwright-dotnet code snippet using Microsoft.Playwright.Core.Frame.QuerySelectorAsync

Run Playwright-dotnet automation tests on LambdaTest cloud grid

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

ProcessService.cs

Source: ProcessService.cs Github

copy
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Text.RegularExpressions;
5using System.Threading;
6using System.Threading.Tasks;
7using App.Core.Helpers;
8using App.Core.Models;
9using App.Core.Models.Configuration;
10using App.Core.Models.Options;
11using App.Core.Services.Configuration;
12using Flurl;
13using Microsoft.Extensions.Logging;
14using Microsoft.Playwright;
15using Newtonsoft.Json;
16using SixLabors.ImageSharp;
17using SixLabors.ImageSharp.Processing;
18
19namespace App.Services
20{
21    public interface IProcessService
22    {
23        Task Process(RunOptions runOptions);
24    }
25
26    public class ProcessService : IProcessService
27    {
28        private static ILogger<ProcessService> _logger;
29        private static FileSettings _fileSettings;
30        private static SearchSettings _searchSettings;
31
32        private static readonly Regex ResultCountRegex = new("(?<ResultCount>\\d+)");
33        //private static readonly Regex NoLocationRegex = new Regex("(?<Location>\\.+)[\\d+] miles away");
34        private static readonly Regex PriceRegex = new("(?<Price>£\\d+,\\d+)");
35        //private static readonly Regex MileageRegex = new("(?<Mileage>\\d+,\\d+)");
36
37        private static readonly string AssetsDir = Path.Combine(Environment.CurrentDirectory, "Assets");
38        private static string _runDir;
39
40        private static DateTime _runDateTime;
41
42        public ProcessService(ILogger<ProcessService> logger, IFileSettingsService fileSettingsSvc, ISearchSettingsService searchSettingsSvc)
43        {
44            _logger = logger;
45
46            _fileSettings = fileSettingsSvc.GetSettings();
47
48            _searchSettings = searchSettingsSvc.GetSettings();
49
50            _runDateTime = DateTime.Now;
51        }
52
53        public async Task Process(RunOptions options)
54        {
55            await SetupRun(options);
56
57            try
58            {
59                foreach (var searchConfig in _searchSettings.Searches)
60                {
61                    // set up the file system for the search
62                    string searchDirectory = SetupSearch(searchConfig);
63
64                    // scrape autotrader for this search config
65                    Results results = await Scrape(searchConfig, searchDirectory);
66
67                    // write all the scraped results as a json log file
68                    await File.WriteAllTextAsync(Path.Combine(searchDirectory, "results.json"), JsonConvert.SerializeObject(results, Formatting.Indented));
69
70                    // create the web assets for this search config
71                    await BuildMapScript(results, searchDirectory);
72                }
73            }
74            catch (Exception e)
75            {
76                _logger?.LogError(e, "Scraping failed");
77            }
78        }
79
80        /// <summary>
81        /// Scrape Autotrader for advert details
82        /// </summary>
83        /// <param name="searchConfig"></param>
84        /// <param name="searchDirectory"></param>
85        /// <returns></returns>
86        private async Task<Results> Scrape(SearchConfig searchConfig, string searchDirectory)
87        {
88            // build the search URL
89            string searchUrl = Url.Combine(_searchSettings.Domain, searchConfig.Url);
90
91            // set up playwright and go to autotrader
92            using var playwright = await Playwright.CreateAsync();
93
94            await using var browser = await playwright.Firefox.LaunchAsync();
95            
96            var page = await browser.NewPageAsync();
97            
98            await page.GotoAsync(searchUrl);
99
100            // get result count for validation
101            IElementHandle resultEls = await page.QuerySelectorAsync(".search-form__count");
102
103            int resultsCount = 0;
104            int pages = resultEls != null
105                ? int.TryParse(ResultCountRegex.Match(await resultEls.InnerTextAsync()).Groups["ResultCount"].Value, out resultsCount)
106                    ? (int)Math.Ceiling((decimal)resultsCount / 10)
107                    : 1
108                : 1;
109
110            var results = new Results {Expected = resultsCount};
111            
112            _logger?.LogInformation("Expecting {ResultsCount} results", resultsCount);
113
114            // iterate pages of adverts
115            for (var i = 1; i <= pages; i++)
116            {
117                _logger?.LogInformation("Processing page {Page}", i);
118                
119                // if this isn't the first page then append the page number and navigate
120                if (i > 1)
121                {
122                    var navPage = searchUrl.SetQueryParam("page", i);
123                    
124                    results.Pages.Add(navPage);
125                    
126                    await page.GotoAsync(navPage);
127                }
128                else
129                    results.Pages.Add(searchUrl);
130
131                // get adverts on page
132                var ads = await page.QuerySelectorAllAsync("article.product-card[data-standout-type=''] > a");
133                
134                // iterate all adverts
135                foreach (var ad in ads)
136                {
137                    // build a car object
138                    var car = new Car(await ad.GetAttributeAsync("href"));
139                    
140                    _logger?.LogInformation("Processing ad {Url}", car.Url);
141                    
142                    // open the advert in a new browser page
143                    IPage adPage = await browser.NewPageAsync();
144
145                    await adPage.GotoAsync(car.Url.AsFullUrl(_searchSettings.Domain));
146                    
147                    // wait 1 second to try and improve image quality of snapshot
148                    Thread.Sleep(1000);
149                    
150                    // snapshot entire ad
151                    var adSelector = ":is(main > div > div:nth-child(2), main > article > div:nth-child(2), main > div > div)";
152                    
153                    if (await ElementExists(adSelector, adPage, "ad image", false))
154                    {
155                        IElementHandle image = await adPage.QuerySelectorAsync(adSelector);
156                        
157                        if (image == null)
158                            _logger?.LogError("Failed to retrieve ad image after successfully finding the ad image element");
159                        else
160                        {
161                            var imageDir = Path.Combine(searchDirectory, "images");
162
163                            car.AdImage = $"{car.Id}_ad.png";
164                            var fullSizePath = Path.Combine(imageDir, $"{car.Id}_ad_full.png");
165                            
166                            await image.ScreenshotAsync(new ElementHandleScreenshotOptions { Path = fullSizePath });
167
168                            await using var input = File.OpenRead(fullSizePath);
169
170                            using var img = await Image.LoadAsync(input);
171
172                            img.Mutate(r => r.Resize(new ResizeOptions
173                            {
174                                Size = new Size(img.Width, img.Width),
175                                Mode = ResizeMode.Crop,
176                                Position = AnchorPositionMode.Top
177                            }));
178                            
179                            await img.SaveAsync(Path.Combine(imageDir, car.AdImage));
180                        }
181                    }
182
183                    #region attempts to get more granular data, not required when snapshotting entire ad
184                    // snapshot image
185                    // var imgSelector = ":is(.gallery__container, section[data-gui='gallery-section'])";
186                    //
187                    // if (await ElementExists(imgSelector, adPage, "image", false))
188                    // {
189                    //     IElementHandle image = await page.QuerySelectorAsync(imgSelector);
190                    //     
191                    //     if (image == null)
192                    //         _logger.LogError("Failed to retrieve image after successfully finding the image element");
193                    //     else
194                    //     {
195                    //         car.Image = $"{car.Id}.png";
196                    //         
197                    //         await image.ScreenshotAsync(new ElementHandleScreenshotOptions { Path = Path.Combine(_imageDir, car.Image) });
198                    //     }
199                    // }
200
201                    // get price
202                    // var priceSelector = "text=/£\\d{2},\\d{3}/i";
203                    //
204                    // if (await ElementExists(priceSelector, adPage, "price", false))
205                    // {
206                    //     IElementHandle price = await adPage.QuerySelectorAsync(priceSelector);
207                    //     
208                    //     if (price == null)
209                    //         _logger.LogError("Failed to retrieve price after successfully finding the price element");
210                    //     else
211                    //         car.Price = PriceRegex.Match(await price.InnerHTMLAsync()).Groups["Price"].Value;
212                    // }
213
214                    // get mileage
215                    // var mileageSelector = "text=/\\d+,\\d+ miles/i";
216                    //
217                    // if (await ElementExists(mileageSelector, adPage, "mileage", false))
218                    // {
219                    //     IElementHandle mileage = await adPage.QuerySelectorAsync(mileageSelector);
220                    //     
221                    //     if (mileage == null)
222                    //         _logger.LogError("Failed to retrieve mileage after successfully finding the mileage element");
223                    //     else
224                    //         car.Mileage = await mileage.InnerTextAsync();
225                    // }
226                    #endregion
227
228                    bool locationLinkFound = false;
229
230                    // try to find a location link
231                    try
232                    {
233                        var locBtnSelector = ":is(button[data-gui-test='dealerLocationLink'], button.seller-location__toggle)";
234
235                        if (!await ElementExists(locBtnSelector, adPage, "location"))
236                        {
237                            results.Cars.Add(car);
238                        
239                            continue;
240                        }
241
242                        await adPage.ClickAsync(locBtnSelector);
243                    
244                        var mapFrameSelector = "iframe[src^='https://www.google.com/maps/embed']";
245
246                        if (!await ElementExists(mapFrameSelector, adPage, "map frame", false))
247                        {
248                            results.Cars.Add(car);
249                        
250                            continue;
251                        }
252                    
253                        Thread.Sleep(500);
254                    
255                        var mapFrameQuery = await adPage.QuerySelectorAsync(mapFrameSelector);
256
257                        if (mapFrameQuery == null)
258                        {
259                            _logger?.LogError("Failed to find the map iframe after successfully finding the map frame element");
260                    
261                            results.Cars.Add(car);
262
263                            await adPage.CloseAsync();
264
265                            continue;
266                        }
267                    
268                        var mapFrame = await mapFrameQuery.ContentFrameAsync();
269
270                        if (mapFrame == null)
271                        {
272                            _logger?.LogError("Failed to select the map iframe element after successfully finding the map iframe element");
273                    
274                            results.Cars.Add(car);
275
276                            await adPage.CloseAsync();
277
278                            continue;
279                        }
280                    
281                        var coordsSelector = "div.place-name";
282
283                        if (await ElementExists(coordsSelector, mapFrame, "coordinates"))
284                        {
285                            IElementHandle coords = await mapFrame.QuerySelectorAsync(coordsSelector);
286                        
287                            if (coords == null)
288                                _logger?.LogError("Failed to retrieve coordinates after successfully finding the coordinates element");
289                            else
290                                car.Coords = await coords.InnerTextAsync();
291                        }
292                    
293                        var addressSelector = "div.address";
294
295                        if (await ElementExists(coordsSelector, mapFrame, "address"))
296                        {
297                            IElementHandle address = await mapFrame.QuerySelectorAsync(addressSelector);
298
299                            if (address == null)
300                                _logger?.LogError("Failed to retrieve address after successfully finding the address element");
301                            else
302                                car.Location = await address.InnerTextAsync();
303                        }
304
305                        locationLinkFound = true;
306                    }
307                    catch (Exception e)
308                    {
309                        _logger?.LogWarning(e, "Failed to find a location link for advert");
310
311                        locationLinkFound = false;
312                    }
313
314                    // todo - if a location link wasn't found, ust the approximate location from the summary screen
315                    if (!locationLinkFound)
316                    {
317
318                    }
319
320                    car.Success = true;
321                    
322                    results.Cars.Add(car);
323
324                    await adPage.CloseAsync();
325                }
326            }
327
328            return results;
329        }
330
331        /// <summary>
332        /// Set up the run directory
333        /// </summary>
334        private async Task SetupRun(RunOptions options)
335        {
336            // allow output directory to be replaced with a command argument, fallback to config file setting
337            string output;
338
339            if (string.IsNullOrWhiteSpace(options.OutputDirectory))
340            {
341                output = _fileSettings.RunsDirectory;
342
343                _runDir = Path.Combine(_fileSettings.RunsDirectory, $"{DateTime.Now:yyyyMMdd HHmmss}");
344            }
345            else
346            {
347                output = _runDir = options.OutputDirectory;
348            }
349
350            // create the output directory if it doesn't exist
351            if (!Directory.Exists(output))
352                Directory.CreateDirectory(output);
353
354            if (!Directory.Exists(_runDir))
355                Directory.CreateDirectory(_runDir);
356
357            foreach (var file in Directory.GetFiles(AssetsDir))
358            {
359                File.Copy(file, Path.Combine(_runDir, Path.GetFileName(file)));
360            }
361
362            // dashboard
363            var dashboard = Path.Combine(_runDir, "index.html");
364
365            await File.WriteAllTextAsync(dashboard, (await File.ReadAllTextAsync(dashboard))
366                .Replace("//SEARCHES_ARRAY_PLACEHOLDER", _searchSettings.SearchesJsonArray())
367                .Replace("//RUN_DATETIME", _runDateTime.ToString("yyyy-MM-dd"))
368                .Replace("//RUN_DAY", _runDateTime.ToString("dddd"))
369                .Replace("//RUN_DATE", _runDateTime.ToString("dd"))
370                .Replace("//RUN_MONTH", _runDateTime.ToString("MM"))
371                .Replace("//RUN_YEAR", _runDateTime.ToString("yyyy")));
372        }
373
374        /// <summary>
375        /// Set up a search directory
376        /// </summary>
377        private string SetupSearch(SearchConfig searchConfig)
378        {
379            var searchDirectory = Path.Combine(_runDir, searchConfig.Id);
380
381            Directory.CreateDirectory(searchDirectory);
382
383            Directory.CreateDirectory(Path.Combine(searchDirectory, "images"));
384
385            foreach (var file in Directory.GetFiles(Path.Combine(AssetsDir, "MapTemplate")))
386            {
387                File.Copy(file, Path.Combine(searchDirectory, Path.GetFileName(file)));
388            }
389
390            return searchDirectory;
391        }
392
393        /// <summary>
394        /// Build Google map script
395        /// </summary>
396        /// <param name="results"></param>
397        /// <param name="searchDirectory"></param>
398        private async Task BuildMapScript(Results results, string searchDirectory)
399        {
400            var indexJsFile = Path.Combine(searchDirectory, "index.js");
401
402            await File.WriteAllTextAsync(indexJsFile, (await File.ReadAllTextAsync(indexJsFile))
403                .Replace("//CARS_ARRAY_PLACEHOLDER", results.JsCarsArray)
404                .Replace("//MARKERS_ARRAY_PLACEHOLDER", results.JsMarkers));
405        }
406
407        /// <summary>
408        /// Checks that an element exists in a page
409        /// </summary>
410        /// <param name="selector"></param>
411        /// <param name="page"></param>
412        /// <param name="selectorType"></param>
413        /// <param name="closePage"></param>
414        /// <returns></returns>
415        private async Task<bool> ElementExists(string selector, IPage page, string selectorType, bool closePage = true)
416        {
417            try
418            {
419                await page.WaitForSelectorAsync(selector, new PageWaitForSelectorOptions{Timeout = 3000});
420
421                return true;
422            }
423            catch (Exception e)
424            {
425                //await page.PauseAsync();
426                
427                _logger?.LogError(e, "Unable to find {SelectorType} for advert at {PageUrl}", selectorType, page.Url.AsFullUrl(_searchSettings.Domain));
428
429                if (closePage)
430                    await page.CloseAsync();
431
432                return false;
433            }
434        }
435
436        /// <summary>
437        /// Checks that an element exists in a frame
438        /// </summary>
439        /// <param name="selector"></param>
440        /// <param name="frame"></param>
441        /// <param name="selectorType"></param>
442        /// <returns></returns>
443        private async Task<bool> ElementExists(string selector, IFrame frame, string selectorType)
444        {
445            try
446            {
447                await frame.WaitForSelectorAsync(selector, new FrameWaitForSelectorOptions{Timeout = 3000});
448
449                return true;
450            }
451            catch (Exception e)
452            {
453                _logger?.LogError(e, "Unable to find {SelectorType} for advert at {FrameUrl}", selectorType, frame.Url);
454
455                return false;
456            }
457        }
458    }
459}
460
Full Screen

Frame.cs

Source: Frame.cs Github

copy
1/*
2 * MIT License
3 *
4 * Copyright (c) 2020 Darío Kondratiuk
5 * Copyright (c) 2020 Meir Blachman
6 * Modifications copyright (c) Microsoft Corporation.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26using System;
27using System.Collections.Generic;
28using System.IO;
29using System.Linq;
30using System.Text.Json;
31using System.Text.RegularExpressions;
32using System.Threading.Tasks;
33using Microsoft.Playwright.Helpers;
34using Microsoft.Playwright.Transport;
35using Microsoft.Playwright.Transport.Channels;
36using Microsoft.Playwright.Transport.Protocol;
37
38namespace Microsoft.Playwright.Core
39{
40    internal class Frame : ChannelOwnerBase, IChannelOwner<Frame>, IFrame
41    {
42        internal readonly FrameChannel _channel;
43        private readonly List<WaitUntilState> _loadStates = new();
44
45        internal Frame(IChannelOwner parent, string guid, FrameInitializer initializer) : base(parent, guid)
46        {
47            _channel = new(guid, parent.Connection, this);
48            Url = initializer.Url;
49            Name = initializer.Name;
50            ParentFrame = initializer.ParentFrame;
51            _loadStates = initializer.LoadStates;
52
53            _channel.LoadState += (_, e) =>
54            {
55                lock (_loadStates)
56                {
57                    if (e.Add.HasValue)
58                    {
59                        _loadStates.Add(e.Add.Value);
60                        LoadState?.Invoke(this, e.Add.Value);
61                    }
62
63                    if (e.Remove.HasValue)
64                    {
65                        _loadStates.Remove(e.Remove.Value);
66                    }
67                }
68            };
69
70            _channel.Navigated += (_, e) =>
71            {
72                Url = e.Url;
73                Name = e.Name;
74                Navigated?.Invoke(this, e);
75
76                if (string.IsNullOrEmpty(e.Error))
77                {
78                    ((Page)Page)?.OnFrameNavigated(this);
79                }
80            };
81        }
82
83        /// <summary>
84        /// Raised when a navigation is received.
85        /// </summary>
86        public event EventHandler<FrameNavigatedEventArgs> Navigated;
87
88        /// <summary>
89        /// Raised when a new LoadState was added.
90        /// </summary>
91        public event EventHandler<WaitUntilState> LoadState;
92
93        ChannelBase IChannelOwner.Channel => _channel;
94
95        IChannel<Frame> IChannelOwner<Frame>.Channel => _channel;
96
97        public IReadOnlyList<IFrame> ChildFrames => ChildFramesList;
98
99        public string Name { get; internal set; }
100
101        public string Url { get; internal set; }
102
103        IFrame IFrame.ParentFrame => ParentFrame;
104
105        public Frame ParentFrame { get; }
106
107        public IPage Page { get; internal set; }
108
109        public bool IsDetached { get; internal set; }
110
111        internal List<Frame> ChildFramesList { get; } = new();
112
113        public async Task<IElementHandle> FrameElementAsync()
114            => (await _channel.FrameElementAsync().ConfigureAwait(false)).Object;
115
116        public IFrameLocator FrameLocator(string selector)
117            => new FrameLocator(this, selector);
118
119        public Task<string> TitleAsync() => _channel.TitleAsync();
120
121        public Task WaitForTimeoutAsync(float timeout)
122            => _channel.WaitForTimeoutAsync(timeout);
123
124        public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, string values, FrameSelectOptionOptions options = default)
125            => SelectOptionAsync(selector, new[] { values }, options);
126
127        public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IEnumerable<string> values, FrameSelectOptionOptions options = default)
128            => SelectOptionAsync(selector, values.Select(x => new SelectOptionValue() { Value = x }), options);
129
130        public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IElementHandle values, FrameSelectOptionOptions options = default)
131            => SelectOptionAsync(selector, new[] { values }, options);
132
133        public async Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IEnumerable<IElementHandle> values, FrameSelectOptionOptions options = default)
134            => (await _channel.SelectOptionAsync(
135                selector,
136                values.Select(x => x as ElementHandle),
137                noWaitAfter: options?.NoWaitAfter,
138                strict: options?.Strict,
139                force: options?.Force,
140                timeout: options?.Timeout).ConfigureAwait(false)).ToList().AsReadOnly();
141
142        public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, SelectOptionValue values, FrameSelectOptionOptions options = default)
143            => SelectOptionAsync(selector, new[] { values }, options);
144
145        public async Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IEnumerable<SelectOptionValue> values, FrameSelectOptionOptions options = default)
146            => (await _channel.SelectOptionAsync(
147                selector,
148                values,
149                noWaitAfter: options?.NoWaitAfter,
150                strict: options?.Strict,
151                force: options?.Force,
152                timeout: options?.Timeout).ConfigureAwait(false)).ToList().AsReadOnly();
153
154        public async Task WaitForLoadStateAsync(LoadState? state = default, FrameWaitForLoadStateOptions options = default)
155        {
156            Task<WaitUntilState> task;
157            Waiter waiter = null;
158            WaitUntilState loadState = Microsoft.Playwright.WaitUntilState.Load;
159            switch (state)
160            {
161                case Microsoft.Playwright.LoadState.Load:
162                    loadState = Microsoft.Playwright.WaitUntilState.Load;
163                    break;
164                case Microsoft.Playwright.LoadState.DOMContentLoaded:
165                    loadState = Microsoft.Playwright.WaitUntilState.DOMContentLoaded;
166                    break;
167                case Microsoft.Playwright.LoadState.NetworkIdle:
168                    loadState = Microsoft.Playwright.WaitUntilState.NetworkIdle;
169                    break;
170            }
171            try
172            {
173                lock (_loadStates)
174                {
175                    if (_loadStates.Contains(loadState))
176                    {
177                        return;
178                    }
179
180                    waiter = SetupNavigationWaiter("frame.WaitForLoadStateAsync", options?.Timeout);
181                    task = waiter.WaitForEventAsync<WaitUntilState>(this, "LoadState", s =>
182                    {
183                        waiter.Log($"  \"{s}\" event fired");
184                        return s == loadState;
185                    });
186                }
187
188                await task.ConfigureAwait(false);
189            }
190            finally
191            {
192                waiter?.Dispose();
193            }
194        }
195
196        public async Task<IResponse> WaitForNavigationAsync(FrameWaitForNavigationOptions options = default)
197        {
198            WaitUntilState waitUntil2 = options?.WaitUntil ?? WaitUntilState.Load;
199            using var waiter = SetupNavigationWaiter("frame.WaitForNavigationAsync", options?.Timeout);
200            string toUrl = !string.IsNullOrEmpty(options?.UrlString) ? $" to \"{options?.UrlString}\"" : string.Empty;
201
202            waiter.Log($"waiting for navigation{toUrl} until \"{waitUntil2}\"");
203
204            var navigatedEventTask = waiter.WaitForEventAsync<FrameNavigatedEventArgs>(
205                this,
206                "Navigated",
207                e =>
208                {
209                    // Any failed navigation results in a rejection.
210                    if (e.Error != null)
211                    {
212                        return true;
213                    }
214
215                    waiter.Log($"  navigated to \"{e.Url}\"");
216                    return UrlMatches(e.Url, options?.UrlString, options?.UrlRegex, options?.UrlFunc);
217                });
218
219            var navigatedEvent = await navigatedEventTask.ConfigureAwait(false);
220
221            if (navigatedEvent.Error != null)
222            {
223                var ex = new PlaywrightException(navigatedEvent.Error);
224                await waiter.WaitForPromiseAsync(Task.FromException<object>(ex)).ConfigureAwait(false);
225            }
226
227            if (!_loadStates.Select(s => s.ToValueString()).Contains(waitUntil2.ToValueString()))
228            {
229                await waiter.WaitForEventAsync<WaitUntilState>(
230                    this,
231                    "LoadState",
232                    e =>
233                    {
234                        waiter.Log($"  \"{e}\" event fired");
235                        return e.ToValueString() == waitUntil2.ToValueString();
236                    }).ConfigureAwait(false);
237            }
238
239            var request = navigatedEvent.NewDocument?.Request?.Object;
240            var response = request != null
241                ? await waiter.WaitForPromiseAsync(request.FinalRequest.ResponseAsync()).ConfigureAwait(false)
242                : null;
243
244            return response;
245        }
246
247        public async Task<IResponse> RunAndWaitForNavigationAsync(Func<Task> action, FrameRunAndWaitForNavigationOptions options = default)
248        {
249            var result = WaitForNavigationAsync(new()
250            {
251                UrlString = options?.UrlString,
252                UrlRegex = options?.UrlRegex,
253                UrlFunc = options?.UrlFunc,
254                WaitUntil = options?.WaitUntil,
255                Timeout = options?.Timeout,
256            });
257            if (action != null)
258            {
259                await WrapApiBoundaryAsync(() => Task.WhenAll(result, action())).ConfigureAwait(false);
260            }
261
262            return await result.ConfigureAwait(false);
263        }
264
265        public Task TapAsync(string selector, FrameTapOptions options = default)
266            => _channel.TapAsync(
267                selector,
268                modifiers: options?.Modifiers,
269                position: options?.Position,
270                timeout: options?.Timeout,
271                force: options?.Force,
272                noWaitAfter: options?.NoWaitAfter,
273                trial: options?.Trial,
274                strict: options?.Strict);
275
276        internal Task<int> QueryCountAsync(string selector)
277            => _channel.QueryCountAsync(selector);
278
279        public Task<string> ContentAsync() => _channel.ContentAsync();
280
281        public Task FocusAsync(string selector, FrameFocusOptions options = default)
282            => _channel.FocusAsync(selector, options?.Timeout, options?.Strict);
283
284        public Task TypeAsync(string selector, string text, FrameTypeOptions options = default)
285            => _channel.TypeAsync(
286                selector,
287                text,
288                delay: options?.Delay,
289                timeout: options?.Timeout,
290                noWaitAfter: options?.NoWaitAfter,
291                strict: options?.Strict);
292
293        public Task<string> GetAttributeAsync(string selector, string name, FrameGetAttributeOptions options = default)
294            => _channel.GetAttributeAsync(selector, name, options?.Timeout, options?.Strict);
295
296        public Task<string> InnerHTMLAsync(string selector, FrameInnerHTMLOptions options = default)
297            => _channel.InnerHTMLAsync(selector, options?.Timeout, options?.Strict);
298
299        public Task<string> InnerTextAsync(string selector, FrameInnerTextOptions options = default)
300            => _channel.InnerTextAsync(selector, options?.Timeout, options?.Strict);
301
302        public Task<string> TextContentAsync(string selector, FrameTextContentOptions options = default)
303            => _channel.TextContentAsync(selector, options?.Timeout, options?.Strict);
304
305        public Task HoverAsync(string selector, FrameHoverOptions options = default)
306            => _channel.HoverAsync(
307                selector,
308                position: options?.Position,
309                modifiers: options?.Modifiers,
310                force: options?.Force,
311                timeout: options?.Timeout,
312                trial: options?.Trial,
313                strict: options?.Strict);
314
315        public Task PressAsync(string selector, string key, FramePressOptions options = default)
316            => _channel.PressAsync(
317                selector,
318                key,
319                delay: options?.Delay,
320                timeout: options?.Timeout,
321                noWaitAfter: options?.NoWaitAfter,
322                strict: options?.Strict);
323
324        public Task DispatchEventAsync(string selector, string type, object eventInit = default, FrameDispatchEventOptions options = default)
325            => _channel.DispatchEventAsync(
326                    selector,
327                    type,
328                    ScriptsHelper.SerializedArgument(eventInit),
329                    options?.Timeout,
330                    options?.Strict);
331
332        public Task FillAsync(string selector, string value, FrameFillOptions options = default)
333            => _channel.FillAsync(selector, value, force: options?.Force, timeout: options?.Timeout, noWaitAfter: options?.NoWaitAfter, options?.Strict);
334
335        public async Task<IElementHandle> AddScriptTagAsync(FrameAddScriptTagOptions options = default)
336        {
337            var content = options?.Content;
338            if (!string.IsNullOrEmpty(options?.Path))
339            {
340                content = File.ReadAllText(options.Path);
341                content += "//# sourceURL=" + options.Path.Replace("\n", string.Empty);
342            }
343
344            return (await _channel.AddScriptTagAsync(options?.Url, options?.Path, content, options?.Type).ConfigureAwait(false)).Object;
345        }
346
347        public async Task<IElementHandle> AddStyleTagAsync(FrameAddStyleTagOptions options = default)
348        {
349            var content = options?.Content;
350            if (!string.IsNullOrEmpty(options?.Path))
351            {
352                content = File.ReadAllText(options.Path);
353                content += "//# sourceURL=" + options.Path.Replace("\n", string.Empty);
354            }
355
356            return (await _channel.AddStyleTagAsync(options?.Url, options?.Path, content).ConfigureAwait(false)).Object;
357        }
358
359        public Task SetInputFilesAsync(string selector, string files, FrameSetInputFilesOptions options = default)
360            => SetInputFilesAsync(selector, new[] { files }, options);
361
362        public async Task SetInputFilesAsync(string selector, IEnumerable<string> files, FrameSetInputFilesOptions options = default)
363        {
364            var converted = await SetInputFilesHelpers.ConvertInputFilesAsync(files, (BrowserContext)Page.Context).ConfigureAwait(false);
365            if (converted.Files != null)
366            {
367                await _channel.SetInputFilesAsync(selector, converted.Files, options?.NoWaitAfter, options?.Timeout, options?.Strict).ConfigureAwait(false);
368            }
369            else
370            {
371                await _channel.SetInputFilePathsAsync(selector, converted?.LocalPaths, converted?.Streams, options?.NoWaitAfter, options?.Timeout, options?.Strict).ConfigureAwait(false);
372            }
373        }
374
375        public Task SetInputFilesAsync(string selector, FilePayload files, FrameSetInputFilesOptions options = default)
376            => SetInputFilesAsync(selector, new[] { files }, options);
377
378        public async Task SetInputFilesAsync(string selector, IEnumerable<FilePayload> files, FrameSetInputFilesOptions options = default)
379        {
380            var converted = SetInputFilesHelpers.ConvertInputFiles(files);
381            await _channel.SetInputFilesAsync(selector, converted.Files, noWaitAfter: options?.NoWaitAfter, timeout: options?.Timeout, options?.Strict).ConfigureAwait(false);
382        }
383
384        public Task ClickAsync(string selector, FrameClickOptions options = default)
385            => _channel.ClickAsync(
386                selector,
387                delay: options?.Delay,
388                button: options?.Button,
389                clickCount: options?.ClickCount,
390                modifiers: options?.Modifiers,
391                position: options?.Position,
392                timeout: options?.Timeout,
393                force: options?.Force,
394                noWaitAfter: options?.NoWaitAfter,
395                trial: options?.Trial,
396                strict: options?.Strict);
397
398        public Task DblClickAsync(string selector, FrameDblClickOptions options = default)
399            => _channel.DblClickAsync(
400                selector,
401                delay: options?.Delay,
402                button: options?.Button,
403                position: options?.Position,
404                modifiers: options?.Modifiers,
405                timeout: options?.Timeout,
406                force: options?.Force,
407                noWaitAfter: options?.NoWaitAfter,
408                trial: options?.Trial,
409                strict: options?.Strict);
410
411        public Task CheckAsync(string selector, FrameCheckOptions options = default)
412            => _channel.CheckAsync(
413                selector,
414                position: options?.Position,
415                timeout: options?.Timeout,
416                force: options?.Force,
417                noWaitAfter: options?.NoWaitAfter,
418                trial: options?.Trial,
419                strict: options?.Strict);
420
421        public Task UncheckAsync(string selector, FrameUncheckOptions options = default)
422            => _channel.UncheckAsync(
423                selector,
424                position: options?.Position,
425                timeout: options?.Timeout,
426                force: options?.Force,
427                noWaitAfter: options?.NoWaitAfter,
428                trial: options?.Trial,
429                strict: options?.Strict);
430
431        public Task SetCheckedAsync(string selector, bool checkedState, FrameSetCheckedOptions options = null)
432            => checkedState ?
433            _channel.CheckAsync(
434                selector,
435                position: options?.Position,
436                timeout: options?.Timeout,
437                force: options?.Force,
438                noWaitAfter: options?.NoWaitAfter,
439                trial: options?.Trial,
440                strict: options?.Strict)
441            : _channel.UncheckAsync(
442                selector,
443                position: options?.Position,
444                timeout: options?.Timeout,
445                force: options?.Force,
446                noWaitAfter: options?.NoWaitAfter,
447                trial: options?.Trial,
448                strict: options?.Strict);
449
450        public Task SetContentAsync(string html, FrameSetContentOptions options = default)
451            => _channel.SetContentAsync(html, timeout: options?.Timeout, waitUntil: options?.WaitUntil);
452
453        public Task<string> InputValueAsync(string selector, FrameInputValueOptions options = null)
454            => _channel.InputValueAsync(selector, options?.Timeout, options?.Strict);
455
456        public async Task<IElementHandle> QuerySelectorAsync(string selector)
457            => (await _channel.QuerySelectorAsync(selector).ConfigureAwait(false))?.Object;
458
459        public async Task<IReadOnlyList<IElementHandle>> QuerySelectorAllAsync(string selector)
460            => (await _channel.QuerySelectorAllAsync(selector).ConfigureAwait(false)).Select(c => ((ElementHandleChannel)c).Object).ToList().AsReadOnly();
461
462        public async Task<IJSHandle> WaitForFunctionAsync(string expression, object arg = default, FrameWaitForFunctionOptions options = default)
463             => (await _channel.WaitForFunctionAsync(
464                expression: expression,
465                arg: ScriptsHelper.SerializedArgument(arg),
466                timeout: options?.Timeout,
467                polling: options?.PollingInterval).ConfigureAwait(false)).Object;
468
469        public async Task<IElementHandle> WaitForSelectorAsync(string selector, FrameWaitForSelectorOptions options = default)
470            => (await _channel.WaitForSelectorAsync(
471                selector: selector,
472                state: options?.State,
473                timeout: options?.Timeout,
474                strict: options?.Strict,
475                omitReturnValue: false).ConfigureAwait(false))?.Object;
476
477        public async Task<IElementHandle> LocatorWaitForAsync(string selector, LocatorWaitForOptions options = default)
478            => (await _channel.WaitForSelectorAsync(
479                selector: selector,
480                state: options?.State,
481                timeout: options?.Timeout,
482                strict: true,
483                omitReturnValue: true).ConfigureAwait(false))?.Object;
484
485        public async Task<IJSHandle> EvaluateHandleAsync(string script, object args = null)
486            => (await _channel.EvaluateExpressionHandleAsync(
487                script,
488                arg: ScriptsHelper.SerializedArgument(args)).ConfigureAwait(false))?.Object;
489
490        public async Task<JsonElement?> EvaluateAsync(string script, object arg = null)
491            => ScriptsHelper.ParseEvaluateResult<JsonElement?>(await _channel.EvaluateExpressionAsync(
492                script,
493                arg: ScriptsHelper.SerializedArgument(arg)).ConfigureAwait(false));
494
495        public async Task<T> EvaluateAsync<T>(string script, object arg = null)
496            => ScriptsHelper.ParseEvaluateResult<T>(await _channel.EvaluateExpressionAsync(
497                script,
498                arg: ScriptsHelper.SerializedArgument(arg)).ConfigureAwait(false));
499
500        public async Task<JsonElement?> EvalOnSelectorAsync(string selector, string script, object arg = null)
501            => ScriptsHelper.ParseEvaluateResult<JsonElement?>(await _channel.EvalOnSelectorAsync(
502                selector: selector,
503                script,
504                arg: ScriptsHelper.SerializedArgument(arg),
505                strict: null).ConfigureAwait(false));
506
507        public async Task<T> EvalOnSelectorAsync<T>(string selector, string script, object arg = null)
508            => ScriptsHelper.ParseEvaluateResult<T>(await _channel.EvalOnSelectorAsync(
509                selector: selector,
510                script,
511                arg: ScriptsHelper.SerializedArgument(arg),
512                strict: null).ConfigureAwait(false));
513
514        public async Task<T> EvalOnSelectorAsync<T>(string selector, string expression, object arg = null, FrameEvalOnSelectorOptions options = null)
515            => ScriptsHelper.ParseEvaluateResult<T>(await _channel.EvalOnSelectorAsync(
516                selector: selector,
517                expression,
518                arg: ScriptsHelper.SerializedArgument(arg),
519                strict: options?.Strict).ConfigureAwait(false));
520
521        public async Task<JsonElement?> EvalOnSelectorAllAsync(string selector, string script, object arg = null)
522            => ScriptsHelper.ParseEvaluateResult<JsonElement?>(await _channel.EvalOnSelectorAllAsync(
523                selector: selector,
524                script,
525                arg: ScriptsHelper.SerializedArgument(arg)).ConfigureAwait(false));
526
527        public async Task<T> EvalOnSelectorAllAsync<T>(string selector, string script, object arg = null)
528            => ScriptsHelper.ParseEvaluateResult<T>(await _channel.EvalOnSelectorAllAsync(
529                selector: selector,
530                script,
531                arg: ScriptsHelper.SerializedArgument(arg)).ConfigureAwait(false));
532
533        public ILocator Locator(string selector, FrameLocatorOptions options = null) => new Locator(this, selector, new() { HasTextRegex = options?.HasTextRegex, HasTextString = options?.HasTextString, Has = options?.Has });
534
535        public async Task<IElementHandle> QuerySelectorAsync(string selector, FrameQuerySelectorOptions options = null)
536            => (await _channel.QuerySelectorAsync(selector, options?.Strict).ConfigureAwait(false))?.Object;
537
538        public async Task<IResponse> GotoAsync(string url, FrameGotoOptions options = default)
539            => (await _channel.GotoAsync(
540                url,
541                timeout: options?.Timeout,
542                waitUntil: options?.WaitUntil,
543                referer: options?.Referer).ConfigureAwait(false))?.Object;
544
545        public Task<bool> IsCheckedAsync(string selector, FrameIsCheckedOptions options = default)
546            => _channel.IsCheckedAsync(selector, timeout: options?.Timeout, options?.Strict);
547
548        public Task<bool> IsDisabledAsync(string selector, FrameIsDisabledOptions options = default)
549            => _channel.IsDisabledAsync(selector, timeout: options?.Timeout, options?.Strict);
550
551        public Task<bool> IsEditableAsync(string selector, FrameIsEditableOptions options = default)
552            => _channel.IsEditableAsync(selector, timeout: options?.Timeout, options?.Strict);
553
554        public Task<bool> IsEnabledAsync(string selector, FrameIsEnabledOptions options = default)
555            => _channel.IsEnabledAsync(selector, timeout: options?.Timeout, options?.Strict);
556
557#pragma warning disable CS0612 // Type or member is obsolete
558        public Task<bool> IsHiddenAsync(string selector, FrameIsHiddenOptions options = default)
559            => _channel.IsHiddenAsync(selector, timeout: options?.Timeout, options?.Strict);
560
561        public Task<bool> IsVisibleAsync(string selector, FrameIsVisibleOptions options = default)
562            => _channel.IsVisibleAsync(selector, timeout: options?.Timeout, options?.Strict);
563#pragma warning restore CS0612 // Type or member is obsolete
564
565        public Task WaitForURLAsync(string url, FrameWaitForURLOptions options = default)
566            => WaitForURLAsync(url, null, null, options);
567
568        public Task WaitForURLAsync(Regex url, FrameWaitForURLOptions options = default)
569            => WaitForURLAsync(null, url, null, options);
570
571        public Task WaitForURLAsync(Func<string, bool> url, FrameWaitForURLOptions options = default)
572            => WaitForURLAsync(null, null, url, options);
573
574        public Task DragAndDropAsync(string source, string target, FrameDragAndDropOptions options = null)
575            => _channel.DragAndDropAsync(source, target, options?.Force, options?.NoWaitAfter, options?.Timeout, options?.Trial, options?.Strict);
576
577        internal Task<FrameExpectResult> ExpectAsync(string selector, string expression, FrameExpectOptions options = null) =>
578            _channel.ExpectAsync(selector, expression, expressionArg: options?.ExpressionArg, expectedText: options?.ExpectedText, expectedNumber: options?.ExpectedNumber, expectedValue: options?.ExpectedValue, useInnerText: options?.UseInnerText, isNot: options?.IsNot, timeout: options?.Timeout);
579
580        private Task WaitForURLAsync(string urlString, Regex urlRegex, Func<string, bool> urlFunc, FrameWaitForURLOptions options = default)
581        {
582            if (UrlMatches(Url, urlString, urlRegex, urlFunc))
583            {
584                return WaitForLoadStateAsync(ToLoadState(options?.WaitUntil), new() { Timeout = options?.Timeout });
585            }
586
587            return WaitForNavigationAsync(
588                new()
589                {
590                    UrlString = urlString,
591                    UrlRegex = urlRegex,
592                    UrlFunc = urlFunc,
593                    Timeout = options?.Timeout,
594                    WaitUntil = options?.WaitUntil,
595                });
596        }
597
598        private LoadState? ToLoadState(WaitUntilState? waitUntilState)
599        {
600            if (waitUntilState == null)
601            {
602                return null;
603            }
604
605            return waitUntilState switch
606            {
607                WaitUntilState.Load => Microsoft.Playwright.LoadState.Load,
608                WaitUntilState.DOMContentLoaded => Microsoft.Playwright.LoadState.DOMContentLoaded,
609                WaitUntilState.NetworkIdle => Microsoft.Playwright.LoadState.NetworkIdle,
610                _ => null,
611            };
612        }
613
614        private Waiter SetupNavigationWaiter(string @event, float? timeout)
615        {
616            var waiter = new Waiter(this.Page as Page, @event);
617            if (this.Page.IsClosed)
618            {
619                waiter.RejectImmediately(new PlaywrightException("Navigation failed because page was closed!"));
620            }
621            waiter.RejectOnEvent<IPage>(Page, PageEvent.Close.Name, new("Navigation failed because page was closed!"));
622            waiter.RejectOnEvent<IPage>(Page, PageEvent.Crash.Name, new("Navigation failed because page was crashed!"));
623            waiter.RejectOnEvent<IFrame>(
624                Page,
625                "FrameDetached",
626                new("Navigating frame was detached!"),
627                e => e == this);
628            timeout ??= (Page as Page)?.DefaultNavigationTimeout ?? PlaywrightImpl.DefaultTimeout;
629            waiter.RejectOnTimeout(Convert.ToInt32(timeout), $"Timeout {timeout}ms exceeded.");
630
631            return waiter;
632        }
633
634        private bool UrlMatches(string url, string matchUrl, Regex regex, Func<string, bool> match)
635        {
636            matchUrl = (Page.Context as BrowserContext)?.CombineUrlWithBase(matchUrl);
637
638            if (matchUrl == null && regex == null && match == null)
639            {
640                return true;
641            }
642
643            if (!string.IsNullOrEmpty(matchUrl))
644            {
645                regex = new(matchUrl.GlobToRegex());
646            }
647
648            if (matchUrl != null && url == matchUrl)
649            {
650                return true;
651            }
652
653            if (regex != null)
654            {
655                return regex.IsMatch(url);
656            }
657
658            return match(url);
659        }
660
661        internal Task HighlightAsync(string selector)
662            => _channel.HighlightAsync(selector);
663    }
664}
665
Full Screen

ElementHandle.cs

Source: ElementHandle.cs Github

copy
1/*
2 * MIT License
3 *
4 * Copyright (c) 2020 Darío Kondratiuk
5 * Modifications copyright (c) Microsoft Corporation.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25using System;
26using System.Collections.Generic;
27using System.IO;
28using System.Linq;
29using System.Text.Json;
30using System.Threading.Tasks;
31using Microsoft.Playwright.Helpers;
32using Microsoft.Playwright.Transport.Channels;
33using Microsoft.Playwright.Transport.Protocol;
34
35namespace Microsoft.Playwright.Core
36{
37    internal partial class ElementHandle : JSHandle, IElementHandle, IChannelOwner<ElementHandle>
38    {
39        private readonly ElementHandleChannel _channel;
40
41        internal ElementHandle(IChannelOwner parent, string guid, ElementHandleInitializer initializer) : base(parent, guid, initializer)
42        {
43            _channel = new(guid, parent.Connection, this);
44            _channel.PreviewUpdated += (_, e) => Preview = e.Preview;
45        }
46
47        ChannelBase IChannelOwner.Channel => _channel;
48
49        IChannel<ElementHandle> IChannelOwner<ElementHandle>.Channel => _channel;
50
51        internal IChannel<ElementHandle> ElementChannel => _channel;
52
53        public async Task<IElementHandle> WaitForSelectorAsync(string selector, ElementHandleWaitForSelectorOptions options = default)
54            => (await _channel.WaitForSelectorAsync(
55                selector: selector,
56                state: options?.State,
57                timeout: options?.Timeout,
58                strict: options?.Strict).ConfigureAwait(false))?.Object;
59
60        public Task WaitForElementStateAsync(ElementState state, ElementHandleWaitForElementStateOptions options = default)
61            => _channel.WaitForElementStateAsync(state, timeout: options?.Timeout);
62
63        public Task PressAsync(string key, ElementHandlePressOptions options = default)
64            => _channel.PressAsync(
65                key,
66                delay: options?.Delay,
67                timeout: options?.Timeout,
68                noWaitAfter: options?.NoWaitAfter);
69
70        public Task TypeAsync(string text, ElementHandleTypeOptions options = default)
71            => _channel.TypeAsync(text, delay: options?.Delay, timeout: options?.Timeout, noWaitAfter: options?.NoWaitAfter);
72
73        public async Task<byte[]> ScreenshotAsync(ElementHandleScreenshotOptions options = default)
74        {
75            options ??= new();
76            if (options.Type == null && !string.IsNullOrEmpty(options.Path))
77            {
78                options.Type = DetermineScreenshotType(options.Path);
79            }
80
81            byte[] result = await _channel.ScreenshotAsync(
82                options.Path,
83                options.OmitBackground,
84                options.Type,
85                options.Quality,
86                options.Mask,
87                options.Animations,
88                options.Caret,
89                options.Scale,
90                options.Timeout).ConfigureAwait(false);
91
92            if (!string.IsNullOrEmpty(options.Path))
93            {
94                Directory.CreateDirectory(new FileInfo(options.Path).Directory.FullName);
95                File.WriteAllBytes(options.Path, result);
96            }
97
98            return result;
99        }
100
101        public Task FillAsync(string value, ElementHandleFillOptions options = default)
102            => _channel.FillAsync(
103                value,
104                noWaitAfter: options?.NoWaitAfter,
105                force: options?.Force,
106                timeout: options?.Timeout);
107
108        public async Task<IFrame> ContentFrameAsync() => (await _channel.ContentFrameAsync().ConfigureAwait(false))?.Object;
109
110        public Task HoverAsync(ElementHandleHoverOptions options = default)
111            => _channel.HoverAsync(
112                modifiers: options?.Modifiers,
113                position: options?.Position,
114                timeout: options?.Timeout,
115                force: options?.Force,
116                trial: options?.Trial);
117
118        public Task ScrollIntoViewIfNeededAsync(ElementHandleScrollIntoViewIfNeededOptions options = default)
119            => _channel.ScrollIntoViewIfNeededAsync(options?.Timeout);
120
121        public async Task<IFrame> OwnerFrameAsync() => (await _channel.OwnerFrameAsync().ConfigureAwait(false)).Object;
122
123        public Task<ElementHandleBoundingBoxResult> BoundingBoxAsync() => _channel.BoundingBoxAsync();
124
125        public Task ClickAsync(ElementHandleClickOptions options = default)
126            => _channel.ClickAsync(
127                delay: options?.Delay,
128                button: options?.Button,
129                clickCount: options?.ClickCount,
130                modifiers: options?.Modifiers,
131                position: options?.Position,
132                timeout: options?.Timeout,
133                force: options?.Force,
134                noWaitAfter: options?.NoWaitAfter,
135                trial: options?.Trial);
136
137        public Task DblClickAsync(ElementHandleDblClickOptions options = default)
138            => _channel.DblClickAsync(
139                delay: options?.Delay,
140                button: options?.Button,
141                modifiers: options?.Modifiers,
142                position: options?.Position,
143                timeout: options?.Timeout,
144                force: options?.Force,
145                noWaitAfter: options?.NoWaitAfter,
146                trial: options?.Trial);
147
148        public Task SetInputFilesAsync(string files, ElementHandleSetInputFilesOptions options = default)
149            => SetInputFilesAsync(new[] { files }, options);
150
151        public async Task SetInputFilesAsync(IEnumerable<string> files, ElementHandleSetInputFilesOptions options = default)
152        {
153            var frame = await OwnerFrameAsync().ConfigureAwait(false);
154            if (frame == null)
155            {
156                throw new PlaywrightException("Cannot set input files to detached element.");
157            }
158            var converted = await SetInputFilesHelpers.ConvertInputFilesAsync(files, (BrowserContext)frame.Page.Context).ConfigureAwait(false);
159            if (converted.Files != null)
160            {
161                await _channel.SetInputFilesAsync(converted.Files, options?.NoWaitAfter, options?.Timeout).ConfigureAwait(false);
162            }
163            else
164            {
165                await _channel.SetInputFilePathsAsync(converted?.LocalPaths, converted?.Streams, options?.NoWaitAfter, options?.Timeout).ConfigureAwait(false);
166            }
167        }
168
169        public Task SetInputFilesAsync(FilePayload files, ElementHandleSetInputFilesOptions options = default)
170            => SetInputFilesAsync(new[] { files }, options);
171
172        public async Task SetInputFilesAsync(IEnumerable<FilePayload> files, ElementHandleSetInputFilesOptions options = default)
173        {
174            var converted = SetInputFilesHelpers.ConvertInputFiles(files);
175            await _channel.SetInputFilesAsync(converted.Files, options?.NoWaitAfter, options?.Timeout).ConfigureAwait(false);
176        }
177
178        public async Task<IElementHandle> QuerySelectorAsync(string selector)
179            => (await _channel.QuerySelectorAsync(selector).ConfigureAwait(false))?.Object;
180
181        public async Task<IReadOnlyList<IElementHandle>> QuerySelectorAllAsync(string selector)
182            => (await _channel.QuerySelectorAllAsync(selector).ConfigureAwait(false)).Select(e => ((ElementHandleChannel)e).Object).ToList().AsReadOnly();
183
184        public async Task<JsonElement?> EvalOnSelectorAsync(string selector, string expression, object arg = null)
185            => ScriptsHelper.ParseEvaluateResult<JsonElement?>(await _channel.EvalOnSelectorAsync(
186                selector: selector,
187                script: expression,
188                arg: ScriptsHelper.SerializedArgument(arg)).ConfigureAwait(false));
189
190        public async Task<T> EvalOnSelectorAsync<T>(string selector, string expression, object arg = null)
191            => ScriptsHelper.ParseEvaluateResult<T>(await _channel.EvalOnSelectorAsync(
192                selector: selector,
193                script: expression,
194                arg: ScriptsHelper.SerializedArgument(arg)).ConfigureAwait(false));
195
196        public async Task<T> EvalOnSelectorAllAsync<T>(string selector, string expression, object arg = null)
197            => ScriptsHelper.ParseEvaluateResult<T>(await _channel.EvalOnSelectorAllAsync(
198                selector: selector,
199                script: expression,
200                arg: ScriptsHelper.SerializedArgument(arg)).ConfigureAwait(false));
201
202        public Task FocusAsync() => _channel.FocusAsync();
203
204        public Task DispatchEventAsync(string type, object eventInit = null)
205            => _channel.DispatchEventAsync(
206                type,
207                eventInit = ScriptsHelper.SerializedArgument(eventInit));
208
209        public Task<string> GetAttributeAsync(string name) => _channel.GetAttributeAsync(name);
210
211        public Task<string> InnerHTMLAsync() => _channel.InnerHTMLAsync();
212
213        public Task<string> InnerTextAsync() => _channel.InnerTextAsync();
214
215        public Task<string> TextContentAsync() => _channel.TextContentAsync();
216
217        public Task SelectTextAsync(ElementHandleSelectTextOptions options = default)
218            => _channel.SelectTextAsync(options?.Force, options?.Timeout);
219
220        public Task<IReadOnlyList<string>> SelectOptionAsync(string values, ElementHandleSelectOptionOptions options = default)
221            => _channel.SelectOptionAsync(new[] { new SelectOptionValue() { Value = values } }, options?.NoWaitAfter, options?.Force, options?.Timeout);
222
223        public Task<IReadOnlyList<string>> SelectOptionAsync(IElementHandle values, ElementHandleSelectOptionOptions options = default)
224            => _channel.SelectOptionAsync(new[] { values }, options?.NoWaitAfter, options?.Force, options?.Timeout);
225
226        public Task<IReadOnlyList<string>> SelectOptionAsync(IEnumerable<string> values, ElementHandleSelectOptionOptions options = default)
227            => _channel.SelectOptionAsync(values.Select(x => new SelectOptionValue() { Value = x }), options?.NoWaitAfter, options?.Force, options?.Timeout);
228
229        public Task<IReadOnlyList<string>> SelectOptionAsync(SelectOptionValue values, ElementHandleSelectOptionOptions options = default)
230            => _channel.SelectOptionAsync(new[] { values }, options?.NoWaitAfter, options?.Force, options?.Timeout);
231
232        public Task<IReadOnlyList<string>> SelectOptionAsync(IEnumerable<IElementHandle> values, ElementHandleSelectOptionOptions options = default)
233            => _channel.SelectOptionAsync(values, options?.NoWaitAfter, options?.Force, options?.Timeout);
234
235        public Task<IReadOnlyList<string>> SelectOptionAsync(IEnumerable<SelectOptionValue> values, ElementHandleSelectOptionOptions options = default)
236            => _channel.SelectOptionAsync(values, options?.NoWaitAfter, options?.Force, options?.Timeout);
237
238        public Task CheckAsync(ElementHandleCheckOptions options = default)
239            => _channel.CheckAsync(
240                position: options?.Position,
241                timeout: options?.Timeout,
242                force: options?.Force,
243                noWaitAfter: options?.NoWaitAfter,
244                trial: options?.Trial);
245
246        public Task UncheckAsync(ElementHandleUncheckOptions options = default)
247            => _channel.UncheckAsync(
248                position: options?.Position,
249                timeout: options?.Timeout,
250                force: options?.Force,
251                noWaitAfter: options?.NoWaitAfter,
252                trial: options?.Trial);
253
254        public Task TapAsync(ElementHandleTapOptions options = default)
255            => _channel.TapAsync(
256                position: options?.Position,
257                modifiers: options?.Modifiers,
258                timeout: options?.Timeout,
259                force: options?.Force,
260                noWaitAfter: options?.NoWaitAfter,
261                trial: options?.Trial);
262
263        public Task<bool> IsCheckedAsync() => _channel.IsCheckedAsync();
264
265        public Task<bool> IsDisabledAsync() => _channel.IsDisabledAsync();
266
267        public Task<bool> IsEditableAsync() => _channel.IsEditableAsync();
268
269        public Task<bool> IsEnabledAsync() => _channel.IsEnabledAsync();
270
271        public Task<bool> IsHiddenAsync() => _channel.IsHiddenAsync();
272
273        public Task<bool> IsVisibleAsync() => _channel.IsVisibleAsync();
274
275        public Task<string> InputValueAsync(ElementHandleInputValueOptions options = null)
276            => _channel.InputValueAsync(options?.Timeout);
277
278        public Task SetCheckedAsync(bool checkedState, ElementHandleSetCheckedOptions options = null)
279             => checkedState
280             ? _channel.CheckAsync(
281                 position: options?.Position,
282                 timeout: options?.Timeout,
283                 force: options?.Force,
284                 noWaitAfter: options?.NoWaitAfter,
285                 trial: options?.Trial)
286             : _channel.UncheckAsync(
287                 position: options?.Position,
288                 timeout: options?.Timeout,
289                 force: options?.Force,
290                 noWaitAfter: options?.NoWaitAfter,
291                 trial: options?.Trial);
292
293        internal static ScreenshotType DetermineScreenshotType(string path)
294        {
295            string mimeType = path.MimeType();
296            return mimeType switch
297            {
298                "image/png" => ScreenshotType.Png,
299                "image/jpeg" => ScreenshotType.Jpeg,
300                _ => throw new ArgumentException($"path: unsupported mime type \"{mimeType}\""),
301            };
302        }
303    }
304}
305
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)