How to use ElementHandleClickOptions method of Microsoft.Playwright.ElementHandleClickOptions class

Best Playwright-dotnet code snippet using Microsoft.Playwright.ElementHandleClickOptions.ElementHandleClickOptions

Run Playwright-dotnet automation tests on LambdaTest cloud grid

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

ElementHandleClickOptions.cs

Source: ElementHandleClickOptions.cs Github

copy
1/*
2 * MIT License
3 *
4 * Copyright (c) Microsoft Corporation.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25using System;
26using System.Collections.Generic;
27using System.ComponentModel.DataAnnotations;
28using System.Drawing;
29using System.Globalization;
30using System.IO;
31using System.Runtime.Serialization;
32using System.Text.Json;
33using System.Text.Json.Serialization;
34using System.Text.RegularExpressions;
35using System.Threading;
36using System.Threading.Tasks;
37
38#nullable enable
39
40namespace Microsoft.Playwright
41{
42    public class ElementHandleClickOptions
43    {
44        public ElementHandleClickOptions() { }
45
46        public ElementHandleClickOptions(ElementHandleClickOptions clone)
47        {
48            if (clone == null)
49            {
50                return;
51            }
52
53            Button = clone.Button;
54            ClickCount = clone.ClickCount;
55            Delay = clone.Delay;
56            Force = clone.Force;
57            Modifiers = clone.Modifiers;
58            NoWaitAfter = clone.NoWaitAfter;
59            Position = clone.Position;
60            Timeout = clone.Timeout;
61            Trial = clone.Trial;
62        }
63
64        /// <summary><para>Defaults to <c>left</c>.</para></summary>
65        [JsonPropertyName("button")]
66        public MouseButton? Button { get; set; }
67
68        /// <summary><para>defaults to 1. See <see cref="UIEvent.detail"/>.</para></summary>
69        [JsonPropertyName("clickCount")]
70        public int? ClickCount { get; set; }
71
72        /// <summary>
73        /// <para>
74        /// Time to wait between <c>mousedown</c> and <c>mouseup</c> in milliseconds. Defaults
75        /// to 0.
76        /// </para>
77        /// </summary>
78        [JsonPropertyName("delay")]
79        public float? Delay { get; set; }
80
81        /// <summary>
82        /// <para>
83        /// Whether to bypass the <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a>
84        /// checks. Defaults to <c>false</c>.
85        /// </para>
86        /// </summary>
87        [JsonPropertyName("force")]
88        public bool? Force { get; set; }
89
90        /// <summary>
91        /// <para>
92        /// Modifier keys to press. Ensures that only these modifiers are pressed during the
93        /// operation, and then restores current modifiers back. If not specified, currently
94        /// pressed modifiers are used.
95        /// </para>
96        /// </summary>
97        [JsonPropertyName("modifiers")]
98        public IEnumerable<KeyboardModifier>? Modifiers { get; set; }
99
100        /// <summary>
101        /// <para>
102        /// Actions that initiate navigations are waiting for these navigations to happen and
103        /// for pages to start loading. You can opt out of waiting via setting this flag. You
104        /// would only need this option in the exceptional cases such as navigating to inaccessible
105        /// pages. Defaults to <c>false</c>.
106        /// </para>
107        /// </summary>
108        [JsonPropertyName("noWaitAfter")]
109        public bool? NoWaitAfter { get; set; }
110
111        /// <summary>
112        /// <para>
113        /// A point to use relative to the top-left corner of element padding box. If not specified,
114        /// uses some visible point of the element.
115        /// </para>
116        /// </summary>
117        [JsonPropertyName("position")]
118        public Position? Position { get; set; }
119
120        /// <summary>
121        /// <para>
122        /// Maximum time in milliseconds, defaults to 30 seconds, pass <c>0</c> to disable timeout.
123        /// The default value can be changed by using the <see cref="IBrowserContext.SetDefaultTimeout"/>
124        /// or <see cref="IPage.SetDefaultTimeout"/> methods.
125        /// </para>
126        /// </summary>
127        [JsonPropertyName("timeout")]
128        public float? Timeout { get; set; }
129
130        /// <summary>
131        /// <para>
132        /// When set, this method only performs the <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a>
133        /// checks and skips the action. Defaults to <c>false</c>. Useful to wait until the
134        /// element is ready for the action without performing it.
135        /// </para>
136        /// </summary>
137        [JsonPropertyName("trial")]
138        public bool? Trial { get; set; }
139    }
140}
141
142#nullable disable
143
Full Screen

QualysWrapperPW.cs

Source: QualysWrapperPW.cs Github

copy
1using Microsoft.Playwright;
2using System.Threading.Tasks;
3
4namespace QualysPlaywright
5{
6    public class QualysWrapperPW
7    {
8        private readonly IPage _page;
9
10        public QualysWrapperPW(IBrowser browser)
11        {
12            _page = browser.NewPageAsync().Result;
13        }
14
15        public async Task OpenExtension()
16        {
17            await _page.GotoAsync("chrome-extension://abnnemjpaacaimkkepphpkaiomnafldi/panel/index.html");
18        }
19
20        public async Task StartCapture(string testCaseName)
21        {
22            _page.Dialog += async (object sender, IDialog dialog) => await dialog.AcceptAsync(testCaseName);
23            var untitledTestCaseElement = await _page.QuerySelectorAsync("//*[@id='testCase-grid']//*[text()='Untitled Test Case']");
24            await untitledTestCaseElement.ClickAsync(new ElementHandleClickOptions { Button = Microsoft.Playwright.MouseButton.Right });
25            await _page.ClickAsync("//a[text()='Rename Test Case']");
26            await ClickRecord();
27        }
28
29        public async Task AddWait()
30        {
31            // you could provide some logic to insert waiting between steps statically,
32            // or alternatively use driver events to insert these commands or overwrite the edited ones instead to make the script less brittle
33            // obviously if the tests have to take into account that the driver could have qualys attached or not is not a good idea
34            // so it would be up to you to figure it out,
35            // if you have many loaders you could just use a post click event to insert waiting for the loader to appear and disappear, same with navigation
36        }
37
38        public async Task StopCapture(string fileName)
39        {
40            await ClickRecord();
41            await _page.ClickAsync("#download");
42            _page.Dialog += async (object sender, IDialog dialog) => await dialog.AcceptAsync(fileName);
43        }
44
45        private async Task ClickRecord() =>
46            await _page.ClickAsync("#record");
47    }
48}
49
Full Screen

Train.cs

Source: Train.cs Github

copy
1using Microsoft.Playwright;
2using System;
3using System.Collections.Generic;
4using System.Configuration;
5using System.Linq;
6using System.Threading;
7using System.Threading.Tasks;
8
9namespace train12306
10{
11    public class Train
12    {
13        private readonly string _fromStation = ConfigurationManager.AppSettings["fromStation"];
14
15        private readonly string _toStation = ConfigurationManager.AppSettings["toStation"];
16
17        private readonly string _date = ConfigurationManager.AppSettings["date"];
18
19        private readonly string[] _trainNos;
20
21        private readonly string[] _passengerNames;
22
23        private readonly (int, string)[] _seatTypes;
24
25        private readonly int _refreshTimes = int.Parse(ConfigurationManager.AppSettings["refreshTimes"]);
26
27        private readonly bool _headless = bool.Parse(ConfigurationManager.AppSettings["Headless"]);
28
29        private IPage _page;
30
31        // 座位td单元格起始位置
32        private const int _startTdNumber = 2;
33
34        private readonly Dictionary<string, (int, string)> _seatDict = new Dictionary<string, (int, string)>
35        {
36            {"business_seat",(_startTdNumber,"9") },
37            {"first_class_seat",(_startTdNumber+1,"M") },
38            {"second_class_seat",(_startTdNumber+2,"O") },
39            {"senior_soft_sleeper",(_startTdNumber+3,"6") },
40            {"soft_sleeper",(_startTdNumber+4,"4") },
41            {"move_sleeper",(_startTdNumber+5,"F") },
42            {"hard_sleeper",(_startTdNumber+6,"3") },
43            {"soft_seat",(_startTdNumber+7,"2") },
44            {"hard_seat",(_startTdNumber+8,"1") },
45            {"no_seat",(_startTdNumber+9,"1") }
46        };
47
48        private const char _separator = ',';
49
50        public Train()
51        {
52            _trainNos = ConfigurationManager.AppSettings["trainNo"].Split(_separator);
53
54            _passengerNames = ConfigurationManager.AppSettings["passengerName"].Split(_separator);
55
56            var seatTypes = ConfigurationManager.AppSettings["seatType"].Split(_separator);
57            _seatTypes = new (int, string)[seatTypes.Length];
58            for (int i = 0; i < seatTypes.Length; i++)
59            {
60                _seatTypes[i] = _seatDict[seatTypes[i]];
61            }
62        }
63
64        /// <summary>
65        /// 开始
66        /// </summary>
67        /// <returns></returns>
68        public async Task StartAsync()
69        {
70            try
71            {
72                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  初始化浏览器。");
73                using var playwright = await Playwright.CreateAsync();
74                await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
75                {
76                    Headless = _headless
77                });
78
79                // 设置默认窗口大小
80                var context = await browser.NewContextAsync(new BrowserNewContextOptions
81                {
82                    ViewportSize = new ViewportSize() { Width = 1920, Height = 1080 }
83                });
84
85                _page = await context.NewPageAsync();
86                await LoginAsync();
87            }
88            catch (Exception ex)
89            {
90                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  ${ex.Message}");
91            }
92        }
93
94        /// <summary>
95        /// 登录
96        /// </summary>
97        /// <returns></returns>
98        private async Task LoginAsync()
99        {
100            Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  打开登录页面,等待扫码。");
101            await _page.GotoAsync("https://kyfw.12306.cn/otn/resources/login.html");
102
103            // 等待用户登录
104            await _page.WaitForURLAsync("**/otn/view/index.html", new PageWaitForURLOptions
105            {
106                Timeout = 60 * 1000
107            });
108
109            Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  扫码登录成功。");
110
111            // 用户登陆后直接跳转买票界面
112            await _page.GotoAsync("https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc");
113
114            await SetTicketFormAsync();
115        }
116
117        /// <summary>
118        ///  设置买票的表单
119        /// </summary>
120        /// <returns></returns>
121        private async Task SetTicketFormAsync()
122        {
123            Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  开始设置抢票表单。");
124            // 关闭弹窗
125            await _page.ClickAsync("#gb_closeDefaultWarningWindowDialog_id");
126
127            // 1、清除出发站输入框,设置焦点
128            var fromStationDom = await _page.QuerySelectorAsync("#fromStationText");
129            await fromStationDom.FillAsync("");
130            await fromStationDom.HoverAsync();
131            await fromStationDom.FocusAsync();
132
133            // 输入出发站
134            await _page.Keyboard.TypeAsync(_fromStation, new KeyboardTypeOptions { Delay = 100 });
135            await _page.ClickAsync($"#panel_cities span.ralign:text-is('{_fromStation}')");
136
137            // 2、清除目的地输入框,设置焦点
138            var toStationDom = await _page.QuerySelectorAsync("#toStationText");
139            await toStationDom.FillAsync("");
140            await toStationDom.HoverAsync();
141            await toStationDom.FocusAsync();
142
143            // 输入目的地
144            await _page.Keyboard.TypeAsync(_toStation, new KeyboardTypeOptions { Delay = 100 });
145            await _page.ClickAsync($"#panel_cities span.ralign:text-is('{_toStation}')");
146
147            // 3、输入日期
148            var trainDateDom = await _page.QuerySelectorAsync("#train_date");
149            await trainDateDom.FillAsync("");
150            await trainDateDom.HoverAsync();
151            await trainDateDom.FocusAsync();
152
153            // 输入目的地
154            await _page.Keyboard.TypeAsync(_date, new KeyboardTypeOptions { Delay = 100 });
155            await _page.Keyboard.PressAsync("Enter");
156
157            await QueryTicketAsync();
158        }
159
160        /// <summary>
161        /// 查票
162        /// </summary>
163        /// <returns></returns>
164        private async Task QueryTicketAsync()
165        {
166            Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  开始查询余票。");
167
168            await _page.ClickAsync("#query_ticket");
169
170            // 等待ajax请求
171            await _page.WaitForRequestFinishedAsync();
172
173            var queryLeftTrDoms = await _page.QuerySelectorAllAsync("#queryLeftTable tr:visible");
174
175            Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  一共搜索到{queryLeftTrDoms.Count}条信息。");
176
177            foreach (var tr in queryLeftTrDoms)
178            {
179                var trainNoDom = await tr.QuerySelectorAsync("td:nth-child(1) a.number");
180                var trainNo = await trainNoDom.InnerTextAsync();
181
182                if (_trainNos.Contains(trainNo))
183                {
184                    // 校验座位有没有票
185                    foreach (var seatType in _seatTypes)
186                    {
187                        // var test = await tr.QuerySelectorAsync("td:nth-child(2)");
188
189                        var seatTypeDom = await tr.QuerySelectorAsync($"td:nth-child({seatType.Item1})");
190
191                        var ticketText = await seatTypeDom.InnerTextAsync();
192                        if (HasTicket(ticketText))
193                        {
194                            var result = await BuyTicketAsync(tr, seatType.Item2);
195                            if (result) return;
196                        }
197                    }
198                }
199            }
200
201            Thread.Sleep(_refreshTimes);
202            await QueryTicketAsync();
203        }
204
205        private async Task<bool> BuyTicketAsync(IElementHandle tr, string seatType)
206        {
207            Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  开始买票。");
208            var buyTicketDom = await tr.QuerySelectorAsync("a.btn72");
209            if (buyTicketDom != null)
210            {
211                await buyTicketDom.ClickAsync();
212
213                // 等待跳转待确认界面
214                await _page.WaitForURLAsync("**/otn/confirmPassenger/initDc", new PageWaitForURLOptions
215                {
216                    Timeout = 60 * 1000
217                });
218
219
220                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  加载乘客信息成功!。");
221
222                // 选择乘车人
223                foreach (var passengerName in _passengerNames)
224                {
225                    await _page.CheckAsync($"#normal_passenger_id label:text-is('{passengerName}')");
226                }
227
228                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  选择乘客成功!。");
229
230                // 选择座位类型
231                var ticketInfoDoms = await _page.QuerySelectorAllAsync("#ticketInfo_id tr:visible");
232                int index = 1;
233                foreach (var ticketInfo in ticketInfoDoms)
234                {
235                    var seatTypeDom = await ticketInfo.QuerySelectorAsync($"#seatType_{index}");
236                    await seatTypeDom.SelectOptionAsync(seatType);
237                    index++;
238                }
239
240                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  选择座位成功!。");
241
242                // 提交订单
243                await _page.ClickAsync("#submitOrder_id");
244
245                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  提交订单成功!。");
246
247                // 确认订单
248                var submitDom = await _page.WaitForSelectorAsync("#qr_submit_id");
249
250                // 延迟5s再点
251                await submitDom.ClickAsync(new ElementHandleClickOptions { Delay = 5 * 1000 });
252
253                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  确认订单成功!。");
254
255                // 等待出票、支付
256                await _page.WaitForURLAsync("**/otn//payOrder/init", new PageWaitForURLOptions
257                {
258                    Timeout = 60 * 1000
259                });
260
261                Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ---->  出票成功。恭喜你,抢票成功,请在30分钟登录12306支付。!。");
262
263                return true;
264            }
265            else
266                return false;
267        }
268
269        private bool HasTicket(string ticketText)
270        {
271            if (string.IsNullOrEmpty(ticketText))
272                return false;
273            else if (ticketText == "有")
274                return true;
275            else if (int.TryParse(ticketText, out int number))
276                return number > _passengerNames.Length;
277            else
278                return false;
279        }
280    }
281}
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

Most used method in ElementHandleClickOptions

Trigger ElementHandleClickOptions code on LambdaTest Cloud Grid

Execute automation tests with ElementHandleClickOptions on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
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)