How to use DrainAsync method of PuppeteerSharp.Helpers.DeferredTaskQueue class

Best Puppeteer-sharp code snippet using PuppeteerSharp.Helpers.DeferredTaskQueue.DrainAsync

Run Puppeteer-sharp automation tests on LambdaTest cloud grid

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

DeferredTaskQueue.cs

Source: DeferredTaskQueue.cs Github

copy
1using System;
2using System.Collections.Generic;
3using System.Threading;
4using System.Threading.Tasks;
5
6namespace PuppeteerSharp.Helpers
7{
8    /// <summary>
9    /// An async queue that accepts a task but defers its execution to be handled by a consumer queue.
10    /// </summary>
11    internal class DeferredTaskQueue
12    {
13        private readonly List<Task> _pendingTasks;
14
15        public DeferredTaskQueue()
16        {
17            _pendingTasks = new List<Task>();
18        }
19
20        public async Task Enqueue(Func<Task> taskGenerator)
21        {
22            var task = taskGenerator();
23            if (task.IsCompleted)
24            {
25                // Don't need to do anything.
26                return;
27            }
28
29            try
30            {
31                lock (_pendingTasks)
32                {
33                    _pendingTasks.Add(task);
34                }
35
36                await task.ConfigureAwait(false);
37            }
38            finally
39            {
40                lock (_pendingTasks)
41                {
42                    _pendingTasks.Remove(task);
43                }
44            }
45        }
46
47        public async Task DrainAsync(CancellationToken cancellationToken = default)
48        {
49            while (!cancellationToken.IsCancellationRequested)
50            {
51                Task task;
52                lock (_pendingTasks)
53                {
54                    if (_pendingTasks.Count == 0)
55                    {
56                        break;
57                    }
58
59                    task = _pendingTasks[0];
60                }
61
62                try
63                {
64                    await task.ConfigureAwait(false);
65                }
66                finally
67                {
68                    lock (_pendingTasks)
69                    {
70                        _pendingTasks.Remove(task);
71                    }
72                }
73            }
74
75            cancellationToken.ThrowIfCancellationRequested();
76        }
77    }
78}
79
Full Screen

CSSCoverage.cs

Source: CSSCoverage.cs Github

copy
1using System;
2using System.Collections.Concurrent;
3using System.Collections.Generic;
4using System.Threading.Tasks;
5using Microsoft.Extensions.Logging;
6using PuppeteerSharp.Helpers;
7using PuppeteerSharp.Helpers.Json;
8using PuppeteerSharp.Messaging;
9
10namespace PuppeteerSharp.PageCoverage
11{
12    internal class CSSCoverage
13    {
14        private readonly CDPSession _client;
15        private readonly ConcurrentDictionary<string, (string Url, string Source)> _stylesheets;
16        private readonly DeferredTaskQueue _callbackQueue;
17        private readonly ILogger _logger;
18
19        private bool _enabled;
20        private bool _resetOnNavigation;
21
22        public CSSCoverage(CDPSession client)
23        {
24            _client = client;
25            _enabled = false;
26            _stylesheets = new ConcurrentDictionary<string, (string Url, string Source)>();
27            _logger = _client.Connection.LoggerFactory.CreateLogger<CSSCoverage>();
28            _callbackQueue = new DeferredTaskQueue();
29
30            _resetOnNavigation = false;
31        }
32
33        internal Task StartAsync(CoverageStartOptions options)
34        {
35            if (_enabled)
36            {
37                throw new InvalidOperationException("CSSCoverage is already enabled");
38            }
39
40            _resetOnNavigation = options.ResetOnNavigation;
41            _enabled = true;
42            _stylesheets.Clear();
43
44            _client.MessageReceived += Client_MessageReceived;
45
46            return Task.WhenAll(
47                _client.SendAsync("DOM.enable"),
48                _client.SendAsync("CSS.enable"),
49                _client.SendAsync("CSS.startRuleUsageTracking"));
50        }
51
52        internal async Task<CoverageEntry[]> StopAsync()
53        {
54            if (!_enabled)
55            {
56                throw new InvalidOperationException("CSSCoverage is not enabled");
57            }
58            _enabled = false;
59
60            var trackingResponse = await _client.SendAsync<CSSStopRuleUsageTrackingResponse>("CSS.stopRuleUsageTracking").ConfigureAwait(false);
61
62            // Wait until we've stopped CSS tracking before stopping listening for messages and finishing up, so that
63            // any pending OnStyleSheetAddedAsync tasks can collect the remaining style sheet coverage.
64            _client.MessageReceived -= Client_MessageReceived;
65            await _callbackQueue.DrainAsync().ConfigureAwait(false);
66
67            await Task.WhenAll(
68                _client.SendAsync("CSS.disable"),
69                _client.SendAsync("DOM.disable")).ConfigureAwait(false);
70
71            var styleSheetIdToCoverage = new Dictionary<string, List<CoverageResponseRange>>();
72            foreach (var entry in trackingResponse.RuleUsage)
73            {
74                styleSheetIdToCoverage.TryGetValue(entry.StyleSheetId, out var ranges);
75                if (ranges == null)
76                {
77                    ranges = new List<CoverageResponseRange>();
78                    styleSheetIdToCoverage[entry.StyleSheetId] = ranges;
79                }
80                ranges.Add(new CoverageResponseRange
81                {
82                    StartOffset = entry.StartOffset,
83                    EndOffset = entry.EndOffset,
84                    Count = entry.Used ? 1 : 0,
85                });
86            }
87
88            var coverage = new List<CoverageEntry>();
89            foreach (var kv in _stylesheets.ToArray())
90            {
91                var styleSheetId = kv.Key;
92                var url = kv.Value.Url;
93                var text = kv.Value.Source;
94                styleSheetIdToCoverage.TryGetValue(styleSheetId, out var responseRanges);
95                var ranges = Coverage.ConvertToDisjointRanges(responseRanges ?? new List<CoverageResponseRange>());
96                coverage.Add(new CoverageEntry
97                {
98                    Url = url,
99                    Ranges = ranges,
100                    Text = text
101                });
102            }
103            return coverage.ToArray();
104        }
105
106        private async void Client_MessageReceived(object sender, MessageEventArgs e)
107        {
108            try
109            {
110                switch (e.MessageID)
111                {
112                    case "CSS.styleSheetAdded":
113                        await _callbackQueue.Enqueue(() => OnStyleSheetAddedAsync(e.MessageData.ToObject<CSSStyleSheetAddedResponse>(true))).ConfigureAwait(false);
114                        break;
115                    case "Runtime.executionContextsCleared":
116                        OnExecutionContextsCleared();
117                        break;
118                }
119            }
120            catch (Exception ex)
121            {
122                var message = $"CSSCoverage failed to process {e.MessageID}. {ex.Message}. {ex.StackTrace}";
123                _logger.LogError(ex, message);
124                _client.Close(message);
125            }
126        }
127
128        private async Task OnStyleSheetAddedAsync(CSSStyleSheetAddedResponse styleSheetAddedResponse)
129        {
130            if (string.IsNullOrEmpty(styleSheetAddedResponse.Header.SourceURL))
131            {
132                return;
133            }
134
135            try
136            {
137                var response = await _client.SendAsync<CssGetStyleSheetTextResponse>("CSS.getStyleSheetText", new CssGetStyleSheetTextRequest
138                {
139                    StyleSheetId = styleSheetAddedResponse.Header.StyleSheetId
140                }).ConfigureAwait(false);
141
142                _stylesheets.TryAdd(styleSheetAddedResponse.Header.StyleSheetId, (styleSheetAddedResponse.Header.SourceURL, response.Text));
143            }
144            catch (Exception ex)
145            {
146                _logger.LogError(ex.ToString());
147            }
148        }
149
150        private void OnExecutionContextsCleared()
151        {
152            if (!_resetOnNavigation)
153            {
154                return;
155            }
156
157            _stylesheets.Clear();
158        }
159    }
160}
161
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 DeferredTaskQueue

Trigger DrainAsync code on LambdaTest Cloud Grid

Execute automation tests with DrainAsync 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)