How to use EvaluateHandleAsync method of Microsoft.Playwright.Core.Locator class

Best Playwright-dotnet code snippet using Microsoft.Playwright.Core.Locator.EvaluateHandleAsync

Run Playwright-dotnet automation tests on LambdaTest cloud grid

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

Locator.cs

Source: Locator.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.Text.Json;
29using System.Threading.Tasks;
30using Microsoft.Playwright.Helpers;
31using Microsoft.Playwright.Transport.Protocol;
32
33namespace Microsoft.Playwright.Core
34{
35    internal class Locator : ILocator
36    {
37        internal readonly Frame _frame;
38        internal readonly string _selector;
39
40        private readonly LocatorLocatorOptions _options;
41
42        public Locator(Frame parent, string selector, LocatorLocatorOptions options = null)
43        {
44            _frame = parent;
45            _selector = selector;
46            _options = options;
47
48            if (options?.HasTextRegex != null)
49            {
50                _selector += $" >> :scope:text-matches({options.HasTextRegex.ToString().EscapeWithQuotes("\"")}, {options.HasTextRegex.Options.GetInlineFlags().EscapeWithQuotes("\"")})";
51            }
52            if (options?.HasTextString != null)
53            {
54                _selector += $" >> :scope:has-text({options.HasTextString.EscapeWithQuotes("\"")})";
55            }
56
57            if (options?.Has != null)
58            {
59                var has = (Locator)options.Has;
60                if (has._frame != _frame)
61                {
62                    throw new ArgumentException("Inner \"has\" locator must belong to the same frame.");
63                }
64                _selector += " >> has=" + JsonSerializer.Serialize(has._selector);
65            }
66        }
67
68        public ILocator First => new Locator(_frame, $"{_selector} >> nth=0");
69
70        public ILocator Last => new Locator(_frame, $"{_selector} >> nth=-1");
71
72        IPage ILocator.Page => _frame.Page;
73
74        public async Task<IReadOnlyList<string>> AllInnerTextsAsync()
75            => await EvaluateAllAsync<string[]>("ee => ee.map(e => e.innerText)").ConfigureAwait(false);
76
77        public async Task<IReadOnlyList<string>> AllTextContentsAsync()
78            => await EvaluateAllAsync<string[]>("ee => ee.map(e => e.textContent || '')").ConfigureAwait(false);
79
80        public async Task<LocatorBoundingBoxResult> BoundingBoxAsync(LocatorBoundingBoxOptions options = null)
81            => await WithElementAsync(
82                async (h, _) =>
83                {
84                    var bb = await h.BoundingBoxAsync().ConfigureAwait(false);
85                    if (bb == null)
86                    {
87                        return null;
88                    }
89
90                    return new LocatorBoundingBoxResult()
91                    {
92                        Height = bb.Height,
93                        Width = bb.Width,
94                        X = bb.X,
95                        Y = bb.Y,
96                    };
97                },
98                options).ConfigureAwait(false);
99
100        public Task CheckAsync(LocatorCheckOptions options = null)
101            => _frame.CheckAsync(
102                _selector,
103                ConvertOptions<FrameCheckOptions>(options));
104
105        public Task ClickAsync(LocatorClickOptions options = null)
106            => _frame.ClickAsync(
107                _selector,
108                ConvertOptions<FrameClickOptions>(options));
109
110        public Task SetCheckedAsync(bool checkedState, LocatorSetCheckedOptions options = null)
111            => checkedState ?
112                CheckAsync(ConvertOptions<LocatorCheckOptions>(options))
113                : UncheckAsync(ConvertOptions<LocatorUncheckOptions>(options));
114
115        public Task<int> CountAsync()
116            => _frame.QueryCountAsync(_selector);
117
118        public Task DblClickAsync(LocatorDblClickOptions options = null)
119            => _frame.DblClickAsync(_selector, ConvertOptions<FrameDblClickOptions>(options));
120
121        public Task DispatchEventAsync(string type, object eventInit = null, LocatorDispatchEventOptions options = null)
122            => _frame.DispatchEventAsync(_selector, type, eventInit, ConvertOptions<FrameDispatchEventOptions>(options));
123
124        public Task DragToAsync(ILocator target, LocatorDragToOptions options = null)
125            => _frame.DragAndDropAsync(_selector, ((Locator)target)._selector, ConvertOptions<FrameDragAndDropOptions>(options));
126
127        public async Task<IElementHandle> ElementHandleAsync(LocatorElementHandleOptions options = null)
128            => await _frame.WaitForSelectorAsync(
129                _selector,
130                ConvertOptions<FrameWaitForSelectorOptions>(options)).ConfigureAwait(false);
131
132        public Task<IReadOnlyList<IElementHandle>> ElementHandlesAsync()
133            => _frame.QuerySelectorAllAsync(_selector);
134
135        public Task<T> EvaluateAllAsync<T>(string expression, object arg = null)
136            => _frame.EvalOnSelectorAllAsync<T>(_selector, expression, arg);
137
138        public Task<JsonElement?> EvaluateAsync(string expression, object arg = null, LocatorEvaluateOptions options = null)
139            => EvaluateAsync<JsonElement?>(expression, arg, options);
140
141        public Task<T> EvaluateAsync<T>(string expression, object arg = null, LocatorEvaluateOptions options = null)
142            => _frame.EvalOnSelectorAsync<T>(_selector, expression, arg, ConvertOptions<FrameEvalOnSelectorOptions>(options));
143
144        public async Task<IJSHandle> EvaluateHandleAsync(string expression, object arg = null, LocatorEvaluateHandleOptions options = null)
145            => await WithElementAsync(async (e, _) => await e.EvaluateHandleAsync(expression, arg).ConfigureAwait(false), options).ConfigureAwait(false);
146
147        public async Task FillAsync(string value, LocatorFillOptions options = null)
148            => await _frame.FillAsync(_selector, value, ConvertOptions<FrameFillOptions>(options)).ConfigureAwait(false);
149
150        public Task FocusAsync(LocatorFocusOptions options = null)
151            => _frame.FocusAsync(_selector, ConvertOptions<FrameFocusOptions>(options));
152
153        IFrameLocator ILocator.FrameLocator(string selector) =>
154            new FrameLocator(_frame, $"{_selector} >> {selector}");
155
156        public Task<string> GetAttributeAsync(string name, LocatorGetAttributeOptions options = null)
157            => _frame.GetAttributeAsync(_selector, name, ConvertOptions<FrameGetAttributeOptions>(options));
158
159        public Task HoverAsync(LocatorHoverOptions options = null)
160            => _frame.HoverAsync(_selector, ConvertOptions<FrameHoverOptions>(options));
161
162        public Task<string> InnerHTMLAsync(LocatorInnerHTMLOptions options = null)
163            => _frame.InnerHTMLAsync(_selector, ConvertOptions<FrameInnerHTMLOptions>(options));
164
165        public Task<string> InnerTextAsync(LocatorInnerTextOptions options = null)
166            => _frame.InnerTextAsync(_selector, ConvertOptions<FrameInnerTextOptions>(options));
167
168        public Task<string> InputValueAsync(LocatorInputValueOptions options = null)
169            => _frame.InputValueAsync(_selector, ConvertOptions<FrameInputValueOptions>(options));
170
171        public Task<bool> IsCheckedAsync(LocatorIsCheckedOptions options = null)
172            => _frame.IsCheckedAsync(_selector, ConvertOptions<FrameIsCheckedOptions>(options));
173
174        public Task<bool> IsDisabledAsync(LocatorIsDisabledOptions options = null)
175            => _frame.IsDisabledAsync(_selector, ConvertOptions<FrameIsDisabledOptions>(options));
176
177        public Task<bool> IsEditableAsync(LocatorIsEditableOptions options = null)
178            => _frame.IsEditableAsync(_selector, ConvertOptions<FrameIsEditableOptions>(options));
179
180        public Task<bool> IsEnabledAsync(LocatorIsEnabledOptions options = null)
181            => _frame.IsEnabledAsync(_selector, ConvertOptions<FrameIsEnabledOptions>(options));
182
183        public Task<bool> IsHiddenAsync(LocatorIsHiddenOptions options = null)
184            => _frame.IsHiddenAsync(_selector, ConvertOptions<FrameIsHiddenOptions>(options));
185
186        public Task<bool> IsVisibleAsync(LocatorIsVisibleOptions options = null)
187            => _frame.IsVisibleAsync(_selector, ConvertOptions<FrameIsVisibleOptions>(options));
188
189        public ILocator Nth(int index)
190            => new Locator(_frame, $"{_selector} >> nth={index}");
191
192        public Task PressAsync(string key, LocatorPressOptions options = null)
193            => _frame.PressAsync(_selector, key, ConvertOptions<FramePressOptions>(options));
194
195        public Task<byte[]> ScreenshotAsync(LocatorScreenshotOptions options = null)
196            => WithElementAsync(async (h, o) => await h.ScreenshotAsync(ConvertOptions<ElementHandleScreenshotOptions>(o)).ConfigureAwait(false), options);
197
198        public Task ScrollIntoViewIfNeededAsync(LocatorScrollIntoViewIfNeededOptions options = null)
199            => WithElementAsync(async (h, o) => await h.ScrollIntoViewIfNeededAsync(ConvertOptions<ElementHandleScrollIntoViewIfNeededOptions>(o)).ConfigureAwait(false), options);
200
201        public Task<IReadOnlyList<string>> SelectOptionAsync(string values, LocatorSelectOptionOptions options = null)
202            => _frame.SelectOptionAsync(_selector, values, ConvertOptions<FrameSelectOptionOptions>(options));
203
204        public Task<IReadOnlyList<string>> SelectOptionAsync(IElementHandle values, LocatorSelectOptionOptions options = null)
205            => _frame.SelectOptionAsync(_selector, values, ConvertOptions<FrameSelectOptionOptions>(options));
206
207        public Task<IReadOnlyList<string>> SelectOptionAsync(IEnumerable<string> values, LocatorSelectOptionOptions options = null)
208            => _frame.SelectOptionAsync(_selector, values, ConvertOptions<FrameSelectOptionOptions>(options));
209
210        public Task<IReadOnlyList<string>> SelectOptionAsync(SelectOptionValue values, LocatorSelectOptionOptions options = null)
211            => _frame.SelectOptionAsync(_selector, values, ConvertOptions<FrameSelectOptionOptions>(options));
212
213        public Task<IReadOnlyList<string>> SelectOptionAsync(IEnumerable<IElementHandle> values, LocatorSelectOptionOptions options = null)
214            => _frame.SelectOptionAsync(_selector, values, ConvertOptions<FrameSelectOptionOptions>(options));
215
216        public Task<IReadOnlyList<string>> SelectOptionAsync(IEnumerable<SelectOptionValue> values, LocatorSelectOptionOptions options = null)
217            => _frame.SelectOptionAsync(_selector, values, ConvertOptions<FrameSelectOptionOptions>(options));
218
219        public Task SelectTextAsync(LocatorSelectTextOptions options = null)
220            => WithElementAsync((h, o) => h.SelectTextAsync(ConvertOptions<ElementHandleSelectTextOptions>(o)), options);
221
222        public Task SetInputFilesAsync(string files, LocatorSetInputFilesOptions options = null)
223            => _frame.SetInputFilesAsync(_selector, files, ConvertOptions<FrameSetInputFilesOptions>(options));
224
225        public Task SetInputFilesAsync(IEnumerable<string> files, LocatorSetInputFilesOptions options = null)
226            => _frame.SetInputFilesAsync(_selector, files, ConvertOptions<FrameSetInputFilesOptions>(options));
227
228        public Task SetInputFilesAsync(FilePayload files, LocatorSetInputFilesOptions options = null)
229            => _frame.SetInputFilesAsync(_selector, files, ConvertOptions<FrameSetInputFilesOptions>(options));
230
231        public Task SetInputFilesAsync(IEnumerable<FilePayload> files, LocatorSetInputFilesOptions options = null)
232            => _frame.SetInputFilesAsync(_selector, files, ConvertOptions<FrameSetInputFilesOptions>(options));
233
234        public Task TapAsync(LocatorTapOptions options = null)
235            => _frame.TapAsync(_selector, ConvertOptions<FrameTapOptions>(options));
236
237        public Task<string> TextContentAsync(LocatorTextContentOptions options = null)
238            => _frame.TextContentAsync(_selector, ConvertOptions<FrameTextContentOptions>(options));
239
240        public Task TypeAsync(string text, LocatorTypeOptions options = null)
241            => _frame.TypeAsync(_selector, text, ConvertOptions<FrameTypeOptions>(options));
242
243        public Task UncheckAsync(LocatorUncheckOptions options = null)
244            => _frame.UncheckAsync(_selector, ConvertOptions<FrameUncheckOptions>(options));
245
246        ILocator ILocator.Locator(string selector, LocatorLocatorOptions options)
247            => new Locator(_frame, $"{_selector} >> {selector}", options);
248
249        public Task WaitForAsync(LocatorWaitForOptions options = null)
250            => _frame.LocatorWaitForAsync(_selector, ConvertOptions<LocatorWaitForOptions>(options));
251
252        internal Task<FrameExpectResult> ExpectAsync(string expression, FrameExpectOptions options = null)
253            => _frame.ExpectAsync(
254                _selector,
255                expression,
256                options);
257
258        public override string ToString() => "[email protected]" + _selector;
259
260        private T ConvertOptions<T>(object source)
261            where T : class, new()
262        {
263            T target = new();
264            var targetType = target.GetType();
265            if (source != null)
266            {
267                var sourceType = source.GetType();
268                foreach (var sourceProperty in sourceType.GetProperties())
269                {
270                    var targetProperty = targetType.GetProperty(sourceProperty.Name);
271                    if (targetProperty != null)
272                    {
273                        targetProperty.SetValue(target, sourceProperty.GetValue(source));
274                    }
275                }
276            }
277            var strictProperty = targetType.GetProperty("Strict");
278            if (strictProperty != null && strictProperty.GetValue(target) == null)
279            {
280                strictProperty.SetValue(target, true);
281            }
282            return target;
283        }
284
285        private async Task<TResult> WithElementAsync<TOptions, TResult>(Func<IElementHandle, TOptions, Task<TResult>> callback, TOptions options)
286            where TOptions : class
287            where TResult : class
288        {
289            IElementHandle handle = await ElementHandleAsync(ConvertOptions<LocatorElementHandleOptions>(options)).ConfigureAwait(false);
290            try
291            {
292                return await callback(handle, options).ConfigureAwait(false);
293            }
294            finally
295            {
296                await handle.DisposeAsync().ConfigureAwait(false);
297            }
298        }
299
300        private async Task WithElementAsync<TOptions>(Func<IElementHandle, TOptions, Task> callback, TOptions options)
301            where TOptions : class
302        {
303            IElementHandle handle = await ElementHandleAsync(ConvertOptions<LocatorElementHandleOptions>(options)).ConfigureAwait(false);
304            try
305            {
306                await callback(handle, options).ConfigureAwait(false);
307            }
308            finally
309            {
310                await handle.DisposeAsync().ConfigureAwait(false);
311            }
312        }
313
314        public Task HighlightAsync() => _frame.HighlightAsync(_selector);
315    }
316}
317
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

BrowserTypeConnectTests.cs

Source: BrowserTypeConnectTests.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.Diagnostics;
28using System.IO;
29using System.IO.Compression;
30using System.Text;
31using System.Threading;
32using System.Threading.Tasks;
33using Microsoft.AspNetCore.Http;
34using Microsoft.Playwright.Helpers;
35using Microsoft.Playwright.NUnit;
36using NUnit.Framework;
37
38namespace Microsoft.Playwright.Tests
39{
40    ///<playwright-file>browsertype-connect.spec.ts</playwright-file>
41    public class BrowserTypeConnectTests : PlaywrightTestEx
42    {
43        private RemoteServer _remoteServer;
44
45        [SetUp]
46        public void SetUpRemoteServer()
47        {
48            _remoteServer = new(BrowserType.Name);
49        }
50
51        [TearDown]
52        public void TearDownRemoteServer()
53        {
54            _remoteServer.Close();
55        }
56
57        [PlaywrightTest("browsertype-connect.spec.ts", "should be able to reconnect to a browser")]
58        public async Task ShouldBeAbleToReconnectToABrowser()
59        {
60            {
61                var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
62                var browserContext = await browser.NewContextAsync();
63                Assert.AreEqual(browserContext.Pages.Count, 0);
64                var page = await browserContext.NewPageAsync();
65                Assert.AreEqual(await page.EvaluateAsync<int>("11 * 11"), 121);
66                await page.GotoAsync(Server.EmptyPage);
67                await browser.CloseAsync();
68            }
69            {
70                var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
71                var browserContext = await browser.NewContextAsync();
72                var page = await browserContext.NewPageAsync();
73                await page.GotoAsync(Server.EmptyPage);
74                await browser.CloseAsync();
75            }
76        }
77
78        [PlaywrightTest("browsertype-connect.spec.ts", "should send default User-Agent and X-Playwright-Browser headers with connect request")]
79        public async Task ShouldSendDefaultUserAgentAndPlaywrightBrowserHeadersWithConnectRequest()
80        {
81            var connectionRequest = Server.WaitForWebSocketConnectionRequest();
82            BrowserType.ConnectAsync($"ws://localhost:{Server.Port}/ws", new()
83            {
84                Headers = new Dictionary<string, string>()
85                {
86                    ["hello-foo"] = "i-am-bar",
87                }
88            }).IgnoreException();
89            var request = await connectionRequest;
90            StringAssert.Contains("Playwright", request.Headers["User-Agent"]);
91            Assert.AreEqual(request.Headers["hello-foo"], "i-am-bar");
92            Assert.AreEqual(request.Headers["x-playwright-browser"], BrowserType.Name);
93        }
94
95        [PlaywrightTest("browsertype-connect.spec.ts", "should be able to connect two browsers at the same time")]
96        public async Task ShouldBeAbleToConnectTwoBrowsersAtTheSameTime()
97        {
98            var browser1 = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
99            Assert.AreEqual(browser1.Contexts.Count, 0);
100            await browser1.NewContextAsync();
101            Assert.AreEqual(browser1.Contexts.Count, 1);
102
103            var browser2 = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
104            Assert.AreEqual(browser2.Contexts.Count, 0);
105            await browser2.NewContextAsync();
106            Assert.AreEqual(browser2.Contexts.Count, 1);
107            Assert.AreEqual(browser1.Contexts.Count, 1);
108
109            await browser1.CloseAsync();
110            Assert.AreEqual(browser2.Contexts.Count, 1);
111
112            var page2 = await browser2.NewPageAsync();
113            Assert.AreEqual(await page2.EvaluateAsync<int>("7 * 6"), 42); // original browser should still work
114
115            await browser2.CloseAsync();
116        }
117
118        [PlaywrightTest("browsertype-connect.spec.ts", "should timeout in connect while connecting")]
119        [Skip(SkipAttribute.Targets.Windows)]
120        public async Task ShouldTimeoutInConnectWhileConnecting()
121        {
122            var exception = await PlaywrightAssert.ThrowsAsync<TimeoutException>(async () => await BrowserType.ConnectAsync($"ws://localhost:{Server.Port}/ws", new BrowserTypeConnectOptions { Timeout = 100 }));
123            StringAssert.Contains("BrowserType.ConnectAsync: Timeout 100ms exceeded", exception.Message);
124        }
125
126        [PlaywrightTest("browsertype-connect.spec.ts", "should support slowmo option")]
127        public async Task ShouldSupportSlowMo()
128        {
129            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint, new BrowserTypeConnectOptions { SlowMo = 200 });
130            var start = DateTime.Now;
131            var context = await browser.NewContextAsync();
132            await browser.CloseAsync();
133            Assert.Greater((DateTime.Now - start).TotalMilliseconds, 199);
134        }
135
136        [PlaywrightTest("browsertype-connect.spec.ts", "disconnected event should be emitted when browser is closed or server is closed")]
137        public async Task DisconnectedEventShouldBeEmittedWhenBrowserIsClosedOrServerIsClosed()
138        {
139            var browser1 = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
140            await browser1.NewPageAsync();
141
142            var browser2 = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
143            await browser2.NewPageAsync();
144
145            int disconnected1 = 0;
146            int disconnected2 = 0;
147            browser1.Disconnected += (_, e) => disconnected1++;
148            browser2.Disconnected += (_, e) => disconnected2++;
149
150            var tsc1 = new TaskCompletionSource<object>();
151            browser1.Disconnected += (_, e) => tsc1.SetResult(null);
152            await browser1.CloseAsync();
153            await tsc1.Task;
154            Assert.AreEqual(disconnected1, 1);
155            Assert.AreEqual(disconnected2, 0);
156
157            var tsc2 = new TaskCompletionSource<object>();
158            browser2.Disconnected += (_, e) => tsc2.SetResult(null);
159            await browser2.CloseAsync();
160            await tsc2.Task;
161            Assert.AreEqual(disconnected1, 1);
162            Assert.AreEqual(disconnected2, 1);
163        }
164
165        [PlaywrightTest("browsertype-connect.spec.ts", "disconnected event should have browser as argument")]
166        public async Task DisconnectedEventShouldHaveBrowserAsArguments()
167        {
168            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
169            IBrowser disconneced = null;
170            var tsc = new TaskCompletionSource<object>();
171            browser.Disconnected += (_, browser) =>
172            {
173                disconneced = browser;
174                tsc.SetResult(null);
175            };
176            await browser.CloseAsync();
177            await tsc.Task;
178            Assert.AreEqual(browser, disconneced);
179        }
180
181        [PlaywrightTest("browsertype-connect.spec.ts", "should set the browser connected state")]
182        public async Task ShouldSetTheBrowserConnectedState()
183        {
184            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
185            Assert.AreEqual(browser.IsConnected, true);
186            var tsc = new TaskCompletionSource<bool>();
187            browser.Disconnected += (_, e) => tsc.SetResult(false);
188            _remoteServer.Close();
189            await tsc.Task;
190            Assert.AreEqual(browser.IsConnected, false);
191        }
192
193        [PlaywrightTest("browsertype-connect.spec.ts", "should throw when used after isConnected returns false")]
194        public async Task ShouldThrowWhenUsedAfterIsConnectedReturnsFalse()
195        {
196            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
197            var page = await browser.NewPageAsync();
198            var tsc = new TaskCompletionSource<bool>();
199            browser.Disconnected += (_, e) => tsc.SetResult(false);
200            _remoteServer.Close();
201            await tsc.Task;
202            Assert.AreEqual(browser.IsConnected, false);
203            var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(async () => await page.EvaluateAsync("1 + 1"));
204            StringAssert.Contains("has been closed", exception.Message);
205        }
206
207        [PlaywrightTest("browsertype-connect.spec.ts", "should throw when calling waitForNavigation after disconnect")]
208        public async Task ShouldThrowWhenWhenCallingWaitForNavigationAfterDisconnect()
209        {
210            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
211            var page = await browser.NewPageAsync();
212            var tsc = new TaskCompletionSource<bool>();
213            browser.Disconnected += (_, e) => tsc.SetResult(false);
214            _remoteServer.Close();
215            await tsc.Task;
216
217            Assert.AreEqual(browser.IsConnected, false);
218            var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(async () => await page.WaitForNavigationAsync());
219            StringAssert.Contains("Navigation failed because page was closed", exception.Message);
220        }
221
222        [PlaywrightTest("browsertype-connect.spec.ts", "should reject navigation when browser closes")]
223        public async Task ShouldRejectNavigationWhenBrowserCloses()
224        {
225            Server.SetRoute("/one-style.css", context =>
226            {
227                context.Response.Redirect("/one-style.css");
228                return Task.CompletedTask;
229            });
230
231            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
232            var page = await browser.NewPageAsync();
233            var PageGoto = page.GotoAsync(Server.Prefix + "/one-style.html", new PageGotoOptions { Timeout = 60000 });
234            await Server.WaitForRequest("/one-style.css");
235            await browser.CloseAsync();
236
237            Assert.AreEqual(browser.IsConnected, false);
238            var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(async () => await PageGoto);
239            StringAssert.Contains("has been closed", exception.Message);
240        }
241
242        [PlaywrightTest("browsertype-connect.spec.ts", "should reject waitForSelector when browser closes")]
243        public async Task ShouldRejectWaitForSelectorWhenBrowserCloses()
244        {
245            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
246            var page = await browser.NewPageAsync();
247            var watchdog = page.WaitForSelectorAsync("div");
248            await browser.CloseAsync();
249
250            var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(async () => await watchdog);
251            Assert.That(exception.Message, Contains.Substring("has been closed"));
252        }
253
254        [PlaywrightTest("browsertype-connect.spec.ts", "should emit close events on pages and contexts")]
255        public async Task ShouldEmitCloseEventsOnPagesAndContexts()
256        {
257            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
258            var context = await browser.NewContextAsync();
259            var tsc = new TaskCompletionSource<object>();
260            context.Close += (_, e) => tsc.SetResult(null);
261            var page = await context.NewPageAsync();
262            bool pageClosed = false;
263            page.Close += (_, e) => pageClosed = true;
264
265            _remoteServer.Close();
266            await tsc.Task;
267            Assert.AreEqual(pageClosed, true);
268        }
269
270        [PlaywrightTest("browsertype-connect.spec.ts", "should terminate network waiters")]
271        public async Task ShouldTerminateNetworkWaiters()
272        {
273            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
274            var page = await browser.NewPageAsync();
275            var requestWatchdog = page.WaitForRequestAsync(Server.EmptyPage);
276            var responseWatchog = page.WaitForResponseAsync(Server.EmptyPage);
277            _remoteServer.Close();
278            async Task CheckTaskHasException(Task task)
279            {
280                var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(async () => await task);
281                StringAssert.Contains("Page closed", exception.Message);
282                StringAssert.DoesNotContain("Timeout", exception.Message);
283
284            }
285            await CheckTaskHasException(requestWatchdog);
286            await CheckTaskHasException(responseWatchog);
287        }
288
289        [PlaywrightTest("browsertype-connect.spec.ts", "should not throw on close after disconnect")]
290        public async Task ShouldNotThrowOnCloseAfterDisconnect()
291        {
292            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
293            var page = await browser.NewPageAsync();
294
295            var tcs = new TaskCompletionSource<bool>();
296            browser.Disconnected += (_, e) => tcs.SetResult(true);
297            _remoteServer.Close();
298            await tcs.Task;
299            await browser.CloseAsync();
300        }
301
302        [PlaywrightTest("browsertype-connect.spec.ts", "should not throw on context.close after disconnect")]
303        public async Task ShouldNotThrowOnContextCloseAfterDisconnect()
304        {
305            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
306            var context = await browser.NewContextAsync();
307            await context.NewPageAsync();
308
309            var tcs = new TaskCompletionSource<bool>();
310            browser.Disconnected += (_, e) => tcs.SetResult(true);
311            _remoteServer.Close();
312            await tcs.Task;
313            await context.CloseAsync();
314        }
315
316        [PlaywrightTest("browsertype-connect.spec.ts", "should not throw on page.close after disconnect")]
317        public async Task ShouldNotThrowOnPageCloseAfterDisconnect()
318        {
319            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
320            var context = await browser.NewContextAsync();
321            var page = await context.NewPageAsync();
322
323            var tcs = new TaskCompletionSource<bool>();
324            browser.Disconnected += (_, e) => tcs.SetResult(true);
325            _remoteServer.Close();
326            await tcs.Task;
327            await page.CloseAsync();
328        }
329
330        [PlaywrightTest("browsertype-connect.spec.ts", "should saveAs videos from remote browser")]
331        public async Task ShouldSaveAsVideosFromRemoteBrowser()
332        {
333            using var tempDirectory = new TempDirectory();
334            var videoPath = tempDirectory.Path;
335            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
336            var context = await browser.NewContextAsync(new()
337            {
338                RecordVideoDir = videoPath,
339                RecordVideoSize = new() { Height = 320, Width = 240 }
340            });
341
342            var page = await context.NewPageAsync();
343            await page.EvaluateAsync("() => document.body.style.backgroundColor = 'red'");
344            await Task.Delay(1000);
345            await context.CloseAsync();
346
347            var videoSavePath = tempDirectory.Path + "my-video.webm";
348            await page.Video.SaveAsAsync(videoSavePath);
349            Assert.That(videoSavePath, Does.Exist);
350
351            var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(async () => await page.Video.PathAsync());
352            StringAssert.Contains("Path is not available when connecting remotely. Use SaveAsAsync() to save a local copy", exception.Message);
353        }
354
355
356        [PlaywrightTest("browsertype-connect.spec.ts", "should save download")]
357        public async Task ShouldSaveDownload()
358        {
359            Server.SetRoute("/download", context =>
360            {
361                context.Response.Headers["Content-Type"] = "application/octet-stream";
362                context.Response.Headers["Content-Disposition"] = "attachment";
363                return context.Response.WriteAsync("Hello world");
364            });
365
366            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
367            var page = await browser.NewPageAsync(new() { AcceptDownloads = true });
368            await page.SetContentAsync($"<a href=\"{Server.Prefix}/download\">download</a>");
369            var downloadTask = page.WaitForDownloadAsync();
370
371            await TaskUtils.WhenAll(
372                downloadTask,
373                page.ClickAsync("a"));
374
375            using var tmpDir = new TempDirectory();
376            string userPath = Path.Combine(tmpDir.Path, "these", "are", "directories", "download.txt");
377            var download = downloadTask.Result;
378            await download.SaveAsAsync(userPath);
379            Assert.True(new FileInfo(userPath).Exists);
380            Assert.AreEqual("Hello world", File.ReadAllText(userPath));
381            var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => download.PathAsync());
382            Assert.AreEqual("Path is not available when connecting remotely. Use SaveAsAsync() to save a local copy.", exception.Message);
383            await browser.CloseAsync();
384        }
385
386        [PlaywrightTest("browsertype-connect.spec.ts", "should error when saving download after deletion")]
387        public async Task ShouldErrorWhenSavingDownloadAfterDeletion()
388        {
389            Server.SetRoute("/download", context =>
390            {
391                context.Response.Headers["Content-Type"] = "application/octet-stream";
392                context.Response.Headers["Content-Disposition"] = "attachment";
393                return context.Response.WriteAsync("Hello world");
394            });
395
396            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
397            var page = await browser.NewPageAsync(new() { AcceptDownloads = true });
398            await page.SetContentAsync($"<a href=\"{Server.Prefix}/download\">download</a>");
399            var downloadTask = page.WaitForDownloadAsync();
400
401            await TaskUtils.WhenAll(
402                downloadTask,
403                page.ClickAsync("a"));
404
405            using var tmpDir = new TempDirectory();
406            string userPath = Path.Combine(tmpDir.Path, "download.txt");
407            var download = downloadTask.Result;
408            await download.DeleteAsync();
409            var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => download.SaveAsAsync(userPath));
410            StringAssert.Contains("Target page, context or browser has been closed", exception.Message);
411            await browser.CloseAsync();
412        }
413
414        [PlaywrightTest("browsertype-connect.spec.ts", "should save har")]
415        public async Task ShouldSaveHar()
416        {
417            using var tempDirectory = new TempDirectory();
418            var harPath = tempDirectory.Path + "/test.har";
419            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
420            var context = await browser.NewContextAsync(new()
421            {
422                RecordHarPath = harPath
423            });
424
425            var page = await context.NewPageAsync();
426            await page.GotoAsync(Server.EmptyPage);
427            await context.CloseAsync();
428            await browser.CloseAsync();
429
430            Assert.That(harPath, Does.Exist);
431            var logString = System.IO.File.ReadAllText(harPath);
432            StringAssert.Contains(Server.EmptyPage, logString);
433        }
434
435        [PlaywrightTest("browsertype-connect.spec.ts", "should record trace with sources")]
436        public async Task ShouldRecordContextTraces()
437        {
438            using var tempDirectory = new TempDirectory();
439            var tracePath = tempDirectory.Path + "/trace.zip";
440            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
441            var context = await browser.NewContextAsync();
442            var page = await context.NewPageAsync();
443
444            await context.Tracing.StartAsync(new() { Sources = true });
445            await page.GotoAsync(Server.EmptyPage);
446            await page.SetContentAsync("<button>Click</button>");
447            await page.ClickAsync("button");
448            await context.Tracing.StopAsync(new TracingStopOptions { Path = tracePath });
449
450            await browser.CloseAsync();
451
452            Assert.That(tracePath, Does.Exist);
453            ZipFile.ExtractToDirectory(tracePath, tempDirectory.Path);
454            Assert.That(tempDirectory.Path + "/trace.trace", Does.Exist);
455            Assert.That(tempDirectory.Path + "/trace.network", Does.Exist);
456            Assert.AreEqual(1, Directory.GetFiles(Path.Join(tempDirectory.Path, "resources"), "*.txt").Length);
457        }
458
459        [PlaywrightTest("browsertype-connect.spec.ts", "should upload large file")]
460        [Skip(SkipAttribute.Targets.Firefox, SkipAttribute.Targets.Webkit)]
461        public async Task ShouldUploadLargeFile()
462        {
463            var browser = await BrowserType.ConnectAsync(_remoteServer.WSEndpoint);
464            var context = await browser.NewContextAsync();
465            var page = await context.NewPageAsync();
466
467            await page.GotoAsync(Server.Prefix + "/input/fileupload.html");
468            using var tmpDir = new TempDirectory();
469            var filePath = Path.Combine(tmpDir.Path, "200MB");
470            using (var stream = File.OpenWrite(filePath))
471            {
472                var str = new string('a', 4 * 1024);
473                for (var i = 0; i < 50 * 1024; i++)
474                {
475                    await stream.WriteAsync(Encoding.UTF8.GetBytes(str));
476                }
477            }
478            var input = page.Locator("input[type=file]");
479            var events = await input.EvaluateHandleAsync(@"e => {
480                const events = [];
481                e.addEventListener('input', () => events.push('input'));
482                e.addEventListener('change', () => events.push('change'));
483                return events;
484            }");
485            await input.SetInputFilesAsync(filePath);
486            Assert.AreEqual(await input.EvaluateAsync<string>("e => e.files[0].name"), "200MB");
487            Assert.AreEqual(await events.EvaluateAsync<string[]>("e => e"), new[] { "input", "change" });
488
489            var (file0Name, file0Size) = await TaskUtils.WhenAll(
490               Server.WaitForRequest("/upload", request => (request.Form.Files[0].FileName, request.Form.Files[0].Length)),
491               page.ClickAsync("input[type=submit]")
492            );
493            Assert.AreEqual("200MB", file0Name);
494            Assert.AreEqual(200 * 1024 * 1024, file0Size);
495        }
496
497        private class RemoteServer
498        {
499            private Process Process { get; set; }
500            public string WSEndpoint { get; set; }
501
502            internal RemoteServer(string browserName)
503            {
504                try
505                {
506                    var startInfo = new ProcessStartInfo(Driver.GetExecutablePath(), $"launch-server --browser {browserName}")
507                    {
508                        UseShellExecute = false,
509                        RedirectStandardOutput = true,
510                    };
511                    foreach (var pair in Driver.GetEnvironmentVariables())
512                    {
513                        startInfo.EnvironmentVariables[pair.Key] = pair.Value;
514                    }
515                    Process = new()
516                    {
517                        StartInfo = startInfo,
518                    };
519                    Process.Start();
520                    WSEndpoint = Process.StandardOutput.ReadLine();
521
522                    if (WSEndpoint != null && !WSEndpoint.StartsWith("ws://"))
523                    {
524                        throw new PlaywrightException("Invalid web socket address: " + WSEndpoint);
525                    }
526                }
527                catch (IOException ex)
528                {
529                    throw new PlaywrightException("Failed to launch server", ex);
530                }
531            }
532
533            internal void Close()
534            {
535                Process.Kill(true);
536                Process.WaitForExit();
537                WSEndpoint = null;
538            }
539        }
540    }
541}
542
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)