From 01afbd15641d5e28723edec6f5d5645b88c844e1 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 1 Feb 2022 10:51:21 +0100 Subject: [PATCH] chore: roll Playwright to 1.19.0-alpha-jan-31-2022 --- README.md | 4 +- src/Common/Version.props | 2 +- .../BrowserContextAddCookiesTests.cs | 19 +--- .../BrowserContextCookiesTests.cs | 8 +- .../DefaultBrowserContext1Tests.cs | 21 +---- src/Playwright.Tests/HeadfulTests.cs | 21 +---- .../Locator/LocatorConvenienceTests.cs | 14 +++ src/Playwright.Tests/PageGotoTests.cs | 2 +- src/Playwright/API/Generated/ILocator.cs | 3 + src/Playwright/Core/Browser.cs | 2 +- src/Playwright/Core/BrowserContext.cs | 4 +- src/Playwright/Core/BrowserType.cs | 2 +- src/Playwright/Core/Locator.cs | 2 + src/Playwright/Core/Tracing.cs | 31 ++++--- src/Playwright/Helpers/Driver.cs | 4 +- .../Channels/BrowserContextChannel.cs | 48 ---------- .../Transport/Channels/ChannelOwnerType.cs | 3 + .../Transport/Channels/TracingChannel.cs | 87 +++++++++++++++++++ src/Playwright/Transport/Connection.cs | 3 + .../Generated/APIRequestContextInitializer.cs | 1 + .../Generated/BrowserContextInitializer.cs | 2 + .../Protocol/Generated/TracingInitializer.cs | 32 +++++++ 22 files changed, 185 insertions(+), 130 deletions(-) create mode 100644 src/Playwright/Transport/Channels/TracingChannel.cs create mode 100644 src/Playwright/Transport/Protocol/Generated/TracingInitializer.cs diff --git a/README.md b/README.md index 3542565f0c..de0340659f 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 99.0.4812.0 | ✅ | ✅ | ✅ | +| Chromium 99.0.4837.0 | ✅ | ✅ | ✅ | | WebKit 15.4 | ✅ | ✅ | ✅ | -| Firefox 95.0 | ✅ | ✅ | ✅ | +| Firefox 96.0.1 | ✅ | ✅ | ✅ | Playwright for .NET is the official language port of [Playwright](https://playwright.dev), the library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) with a single API. Playwright is built to enable cross-browser web automation that is **ever-green**, **capable**, **reliable** and **fast**. diff --git a/src/Common/Version.props b/src/Common/Version.props index c83359e063..098483dce3 100644 --- a/src/Common/Version.props +++ b/src/Common/Version.props @@ -2,7 +2,7 @@ 1.18.0 $(AssemblyVersion) - 1.18.0-beta-1642620709000 + 1.19.0-alpha-jan-31-2022 $(AssemblyVersion) $(AssemblyVersion) true diff --git a/src/Playwright.Tests/BrowserContextAddCookiesTests.cs b/src/Playwright.Tests/BrowserContextAddCookiesTests.cs index a3f4088f90..285976f1b5 100644 --- a/src/Playwright.Tests/BrowserContextAddCookiesTests.cs +++ b/src/Playwright.Tests/BrowserContextAddCookiesTests.cs @@ -511,26 +511,9 @@ await Page.EvaluateAsync(@"src => { await Page.FirstChildFrame().EvaluateAsync("document.cookie = 'username=John Doe'"); await Page.WaitForTimeoutAsync(2000); - bool allowsThirdParty = TestConstants.IsFirefox; var cookies = await Context.CookiesAsync(new[] { Server.CrossProcessPrefix + "/grid.html" }); - if (allowsThirdParty) - { - Assert.That(cookies, Has.Count.EqualTo(1)); - var cookie = cookies[0]; - Assert.AreEqual("127.0.0.1", cookie.Domain); - Assert.AreEqual(cookie.Expires, -1); - Assert.IsFalse(cookie.HttpOnly); - Assert.AreEqual("username", cookie.Name); - Assert.AreEqual("/", cookie.Path); - Assert.AreEqual(SameSiteAttribute.None, cookie.SameSite); - Assert.IsFalse(cookie.Secure); - Assert.AreEqual("John Doe", cookie.Value); - } - else - { - Assert.That(cookies, Is.Empty); - } + Assert.That(cookies, Is.Empty); } static void AssertEqual(IEnumerable ea, IEnumerable eb) diff --git a/src/Playwright.Tests/BrowserContextCookiesTests.cs b/src/Playwright.Tests/BrowserContextCookiesTests.cs index 93bbbfd874..c07021528a 100644 --- a/src/Playwright.Tests/BrowserContextCookiesTests.cs +++ b/src/Playwright.Tests/BrowserContextCookiesTests.cs @@ -54,7 +54,7 @@ public async Task ShouldGetACookie() Assert.AreEqual(-1, cookie.Expires); Assert.IsFalse(cookie.HttpOnly); Assert.IsFalse(cookie.Secure); - Assert.AreEqual(TestConstants.IsChromium ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); + Assert.AreEqual((TestConstants.IsChromium || TestConstants.IsFirefox) ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); } [PlaywrightTest("browsercontext-cookies.spec.ts", "should get a non-session cookie")] @@ -76,7 +76,7 @@ public async Task ShouldGetANonSessionCookie() Assert.AreEqual(new DateTimeOffset(date).ToUnixTimeSeconds(), cookie.Expires); Assert.IsFalse(cookie.HttpOnly); Assert.IsFalse(cookie.Secure); - Assert.AreEqual(TestConstants.IsChromium ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); + Assert.AreEqual((TestConstants.IsChromium || TestConstants.IsFirefox) ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); } [PlaywrightTest("browsercontext-cookies.spec.ts", "should properly report httpOnly cookie")] @@ -144,7 +144,7 @@ public async Task ShouldGetMultipleCookies() Assert.AreEqual(cookie.Expires, -1); Assert.IsFalse(cookie.HttpOnly); Assert.IsFalse(cookie.Secure); - Assert.AreEqual(TestConstants.IsChromium ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); + Assert.AreEqual((TestConstants.IsChromium || TestConstants.IsFirefox) ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); cookie = cookies[1]; Assert.AreEqual("username", cookie.Name); @@ -154,7 +154,7 @@ public async Task ShouldGetMultipleCookies() Assert.AreEqual(cookie.Expires, -1); Assert.IsFalse(cookie.HttpOnly); Assert.IsFalse(cookie.Secure); - Assert.AreEqual(TestConstants.IsChromium ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); + Assert.AreEqual((TestConstants.IsChromium || TestConstants.IsFirefox) ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); } [PlaywrightTest("browsercontext-cookies.spec.ts", "should get cookies from multiple urls")] diff --git a/src/Playwright.Tests/DefaultBrowserContext1Tests.cs b/src/Playwright.Tests/DefaultBrowserContext1Tests.cs index 90e5ae0df1..27411837ca 100644 --- a/src/Playwright.Tests/DefaultBrowserContext1Tests.cs +++ b/src/Playwright.Tests/DefaultBrowserContext1Tests.cs @@ -52,7 +52,7 @@ public async Task ContextCookiesShouldWork() Assert.AreEqual(-1, cookie.Expires); Assert.IsFalse(cookie.HttpOnly); Assert.IsFalse(cookie.Secure); - Assert.AreEqual(TestConstants.IsChromium ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); + Assert.AreEqual((TestConstants.IsChromium || TestConstants.IsFirefox) ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); await context.DisposeAsync(); tmp.Dispose(); @@ -141,26 +141,9 @@ await page.EvaluateAsync(@"src => { await page.FirstChildFrame().EvaluateAsync("document.cookie = 'username=John Doe'"); await page.WaitForTimeoutAsync(2000); - bool allowsThirdParty = TestConstants.IsFirefox; var cookies = await context.CookiesAsync(new[] { Server.CrossProcessPrefix + "/grid.html" }); - if (allowsThirdParty) - { - Assert.That(cookies, Has.Count.EqualTo(1)); - var cookie = cookies.First(); - Assert.AreEqual("127.0.0.1", cookie.Domain); - Assert.AreEqual(cookie.Expires, -1); - Assert.IsFalse(cookie.HttpOnly); - Assert.AreEqual("username", cookie.Name); - Assert.AreEqual("/", cookie.Path); - Assert.AreEqual(TestConstants.IsChromium ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); - Assert.IsFalse(cookie.Secure); - Assert.AreEqual("John Doe", cookie.Value); - } - else - { - Assert.That(cookies, Is.Empty); - } + Assert.That(cookies, Is.Empty); await context.DisposeAsync(); tmp.Dispose(); diff --git a/src/Playwright.Tests/HeadfulTests.cs b/src/Playwright.Tests/HeadfulTests.cs index 894ed9869f..13ca13873b 100644 --- a/src/Playwright.Tests/HeadfulTests.cs +++ b/src/Playwright.Tests/HeadfulTests.cs @@ -136,27 +136,10 @@ await page.EvaluateAsync(@"src => { }"); await page.WaitForTimeoutAsync(2000); - bool allowsThirdParty = TestConstants.IsFirefox; - Assert.AreEqual(allowsThirdParty ? "username=John Doe" : string.Empty, documentCookie); + Assert.AreEqual(string.Empty, documentCookie); var cookies = await page.Context.CookiesAsync(new[] { Server.CrossProcessPrefix + "/grid.html" }); - if (allowsThirdParty) - { - Assert.That(cookies, Has.Count.EqualTo(1)); - var cookie = cookies.First(); - Assert.AreEqual("127.0.0.1", cookie.Domain); - Assert.AreEqual(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.AreEqual("username", cookie.Name); - Assert.AreEqual("/", cookie.Path); - Assert.AreEqual(SameSiteAttribute.None, cookie.SameSite); - Assert.False(cookie.Secure); - Assert.AreEqual("John Doe", cookie.Value); - } - else - { - Assert.IsEmpty(cookies); - } + Assert.IsEmpty(cookies); } [PlaywrightTest("headful.spec.ts", "should not override viewport size when passed null")] diff --git a/src/Playwright.Tests/Locator/LocatorConvenienceTests.cs b/src/Playwright.Tests/Locator/LocatorConvenienceTests.cs index 940d4906ac..de682e96e9 100644 --- a/src/Playwright.Tests/Locator/LocatorConvenienceTests.cs +++ b/src/Playwright.Tests/Locator/LocatorConvenienceTests.cs @@ -247,5 +247,19 @@ public async Task AllInnerTextsShouldWork() await Page.SetContentAsync("
A
B
C
"); CollectionAssert.AreEqual(new string[] { "A", "B", "C" }, (await Page.Locator("div").AllInnerTextsAsync()).ToArray()); } + + [PlaywrightTest("locator-convenience.spec.ts", "should return page")] + public async Task ShouldReturnPageInstance() + { + await Page.GotoAsync(Server.Prefix + "/frames/two-frames.html"); + var outer = Page.Locator("#outer"); + Assert.AreEqual(outer.Page, Page); + + var inner = outer.Locator("#inner"); + Assert.AreEqual(inner.Page, Page); + + var inFrame = Page.Frames[1].Locator("div"); + Assert.AreEqual(inFrame.Page, Page); + } } } diff --git a/src/Playwright.Tests/PageGotoTests.cs b/src/Playwright.Tests/PageGotoTests.cs index a4406a2e2d..ada4ca6834 100644 --- a/src/Playwright.Tests/PageGotoTests.cs +++ b/src/Playwright.Tests/PageGotoTests.cs @@ -396,7 +396,7 @@ public async Task ShouldFailWhenReplacedByAnotherNavigation() } else if (TestConstants.IsWebKit) { - StringAssert.Contains("cancelled", exception.Message); + StringAssert.Contains("Navigation interrupted by another one", exception.Message); } else { diff --git a/src/Playwright/API/Generated/ILocator.cs b/src/Playwright/API/Generated/ILocator.cs index 451ba246ca..0804629866 100644 --- a/src/Playwright/API/Generated/ILocator.cs +++ b/src/Playwright/API/Generated/ILocator.cs @@ -462,6 +462,9 @@ public partial interface ILocator /// ILocator Nth(int index); + /// A page this locator belongs to. + IPage Page { get; } + /// /// Focuses the element, and then uses and . /// diff --git a/src/Playwright/Core/Browser.cs b/src/Playwright/Core/Browser.cs index 18fd6be6a5..4107c1afa6 100644 --- a/src/Playwright/Core/Browser.cs +++ b/src/Playwright/Core/Browser.cs @@ -118,7 +118,7 @@ public async Task NewContextAsync(BrowserNewContextOptions opti forcedColors: options.ForcedColors).ConfigureAwait(false)).Object; context.Options = options; - context.LocalUtils = LocalUtils; + ((Tracing)context.Tracing).LocalUtils = LocalUtils; BrowserContextsList.Add(context); return context; diff --git a/src/Playwright/Core/BrowserContext.cs b/src/Playwright/Core/BrowserContext.cs index 3209dbfb58..1d36f93ccd 100644 --- a/src/Playwright/Core/BrowserContext.cs +++ b/src/Playwright/Core/BrowserContext.cs @@ -83,7 +83,7 @@ internal BrowserContext(IChannelOwner parent, string guid, BrowserContextInitial e.Page?.FireResponse(e.Response); }; - _tracing = new Tracing(this); + _tracing = initializer.Tracing; _initializer = initializer; Browser = parent as IBrowser; } @@ -112,8 +112,6 @@ public ITracing Tracing public IBrowser Browser { get; } - internal LocalUtils LocalUtils { get; set; } - public IReadOnlyList Pages => PagesList; internal float DefaultNavigationTimeout diff --git a/src/Playwright/Core/BrowserType.cs b/src/Playwright/Core/BrowserType.cs index d4c56fd427..1c0e99a6a2 100644 --- a/src/Playwright/Core/BrowserType.cs +++ b/src/Playwright/Core/BrowserType.cs @@ -134,7 +134,7 @@ public async Task LaunchPersistentContextAsync(string userDataD RecordHarPath = options.RecordHarPath, RecordHarOmitContent = options.RecordHarOmitContent, }; - context.LocalUtils = Playwright.Utils; + ((Core.Tracing)context.Tracing).LocalUtils = Playwright.Utils; return context; } diff --git a/src/Playwright/Core/Locator.cs b/src/Playwright/Core/Locator.cs index 771895a93c..2698ed8138 100644 --- a/src/Playwright/Core/Locator.cs +++ b/src/Playwright/Core/Locator.cs @@ -61,6 +61,8 @@ public Locator(Frame parent, string selector, LocatorLocatorOptions options = nu public ILocator Last => new Locator(_frame, $"{_selector} >> nth=-1"); + IPage ILocator.Page => _frame.Page; + public async Task> AllInnerTextsAsync() => await EvaluateAllAsync("ee => ee.map(e => e.innerText)").ConfigureAwait(false); diff --git a/src/Playwright/Core/Tracing.cs b/src/Playwright/Core/Tracing.cs index c2c24592d7..dc359adef1 100644 --- a/src/Playwright/Core/Tracing.cs +++ b/src/Playwright/Core/Tracing.cs @@ -23,32 +23,41 @@ */ using System.Threading.Tasks; +using Microsoft.Playwright.Transport; +using Microsoft.Playwright.Transport.Channels; +using Microsoft.Playwright.Transport.Protocol; namespace Microsoft.Playwright.Core { - internal partial class Tracing : ITracing + internal class Tracing : ChannelOwnerBase, IChannelOwner, ITracing { - private readonly BrowserContext _context; + private readonly TracingChannel _channel; - public Tracing(BrowserContext context) + public Tracing(IChannelOwner parent, string guid) : base(parent, guid) { - _context = context; + _channel = new(guid, parent.Connection, this); } + internal LocalUtils LocalUtils { get; set; } + + ChannelBase IChannelOwner.Channel => _channel; + + IChannel IChannelOwner.Channel => _channel; + public async Task StartAsync(TracingStartOptions options = default) { - await _context.Channel.TracingStartAsync( + await _channel.TracingStartAsync( name: options?.Name, title: options?.Title, screenshots: options?.Screenshots, snapshots: options?.Snapshots, sources: options?.Sources).ConfigureAwait(false); - await _context.Channel.StartChunkAsync(options?.Title).ConfigureAwait(false); + await _channel.StartChunkAsync(options?.Title).ConfigureAwait(false); } public Task StartChunkAsync() => StartChunkAsync(); - public Task StartChunkAsync(TracingStartChunkOptions options) => _context.Channel.StartChunkAsync(title: options?.Title); + public Task StartChunkAsync(TracingStartChunkOptions options) => _channel.StartChunkAsync(title: options?.Title); public async Task StopChunkAsync(TracingStopChunkOptions options = null) { @@ -58,12 +67,12 @@ public async Task StopChunkAsync(TracingStopChunkOptions options = null) public async Task StopAsync(TracingStopOptions options = default) { await StopChunkAsync(new() { Path = options?.Path }).ConfigureAwait(false); - await _context.Channel.TracingStopAsync().ConfigureAwait(false); + await _channel.TracingStopAsync().ConfigureAwait(false); } private async Task DoStopChunkAsync(string filePath) { - bool isLocal = _context.Channel.Connection.IsRemote; + bool isLocal = !_channel.Connection.IsRemote; var mode = "doNotSave"; if (!string.IsNullOrEmpty(filePath)) @@ -74,7 +83,7 @@ private async Task DoStopChunkAsync(string filePath) mode = "compressTrace"; } - var (artifact, sourceEntries) = await _context.Channel.StopChunkAsync(mode).ConfigureAwait(false); + var (artifact, sourceEntries) = await _channel.StopChunkAsync(mode).ConfigureAwait(false); // Not interested in artifacts. if (string.IsNullOrEmpty(filePath)) @@ -90,7 +99,7 @@ private async Task DoStopChunkAsync(string filePath) // Add local sources to the remote trace if necessary. if (sourceEntries.Count > 0) - await _context.LocalUtils.ZipAsync(filePath, sourceEntries).ConfigureAwait(false); + await LocalUtils.ZipAsync(filePath, sourceEntries).ConfigureAwait(false); } } } diff --git a/src/Playwright/Helpers/Driver.cs b/src/Playwright/Helpers/Driver.cs index cd9c586e19..23c3e8d50a 100644 --- a/src/Playwright/Helpers/Driver.cs +++ b/src/Playwright/Helpers/Driver.cs @@ -87,8 +87,8 @@ private static string GetPath(string driversPath) internal static Dictionary GetEnvironmentVariables() { var environmentVariables = new Dictionary(); - environmentVariables.Add("PW_CLI_TARGET_LANG", "csharp"); - environmentVariables.Add("PW_CLI_TARGET_LANG_VERSION", $"{Environment.Version.Major}.{Environment.Version.Minor}"); + environmentVariables.Add("PW_LANG_NAME", "csharp"); + environmentVariables.Add("PW_LANG_NAME_VERSION", $"{Environment.Version.Major}.{Environment.Version.Minor}"); environmentVariables.Add("PW_CLI_DISPLAY_VERSION", GetSemVerPackageVersion()); return environmentVariables; } diff --git a/src/Playwright/Transport/Channels/BrowserContextChannel.cs b/src/Playwright/Transport/Channels/BrowserContextChannel.cs index 4a6be91ba4..b50d7d007c 100644 --- a/src/Playwright/Transport/Channels/BrowserContextChannel.cs +++ b/src/Playwright/Transport/Channels/BrowserContextChannel.cs @@ -234,54 +234,6 @@ internal Task SetExtraHTTPHeadersAsync(IEnumerable> internal Task GetStorageStateAsync() => Connection.SendMessageToServerAsync(Guid, "storageState", null); - internal Task TracingStartAsync(string name, string title, bool? screenshots, bool? snapshots, bool? sources) - => Connection.SendMessageToServerAsync( - Guid, - "tracingStart", - new Dictionary - { - ["name"] = name, - ["title"] = title, - ["screenshots"] = screenshots, - ["snapshots"] = snapshots, - ["sources"] = sources, - }); - - internal Task TracingStopAsync() - => Connection.SendMessageToServerAsync( - Guid, - "tracingStop"); - - internal Task StartChunkAsync(string title = null) - => Connection.SendMessageToServerAsync(Guid, "tracingStartChunk", new Dictionary - { - ["title"] = title, - }); - - internal async Task<(Artifact Artifact, List SourceEntries)> StopChunkAsync(string mode) - { - var result = await Connection.SendMessageToServerAsync(Guid, "tracingStopChunk", new Dictionary - { - ["mode"] = mode, - }).ConfigureAwait(false); - - var artifact = result.GetObject("artifact", Connection); - List sourceEntries = new() { }; - if (result.Value.TryGetProperty("sourceEntries", out var sourceEntriesElement)) - { - var sourceEntriesEnumerator = sourceEntriesElement.EnumerateArray(); - while (sourceEntriesEnumerator.MoveNext()) - { - JsonElement current = sourceEntriesEnumerator.Current; - sourceEntries.Add(current.Deserialize(new JsonSerializerOptions() - { - PropertyNameCaseInsensitive = true, - })); - } - } - return (artifact, sourceEntries); - } - internal async Task HarExportAsync() { var result = await Connection.SendMessageToServerAsync( diff --git a/src/Playwright/Transport/Channels/ChannelOwnerType.cs b/src/Playwright/Transport/Channels/ChannelOwnerType.cs index 94c0a08416..fec1d4d405 100644 --- a/src/Playwright/Transport/Channels/ChannelOwnerType.cs +++ b/src/Playwright/Transport/Channels/ChannelOwnerType.cs @@ -102,6 +102,9 @@ internal enum ChannelOwnerType [EnumMember(Value = "stream")] Stream, + [EnumMember(Value = "tracing")] + Tracing, + [EnumMember(Value = "fetchRequest")] FetchRequest, diff --git a/src/Playwright/Transport/Channels/TracingChannel.cs b/src/Playwright/Transport/Channels/TracingChannel.cs new file mode 100644 index 0000000000..a01c79f5ea --- /dev/null +++ b/src/Playwright/Transport/Channels/TracingChannel.cs @@ -0,0 +1,87 @@ +/* + * MIT License + * + * Copyright (c) Microsoft Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and / or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Playwright.Core; +using Microsoft.Playwright.Helpers; + +namespace Microsoft.Playwright.Transport.Channels +{ + internal class TracingChannel : Channel + { + public TracingChannel(string guid, Connection connection, Tracing owner) : base(guid, connection, owner) + { + } + + internal Task TracingStartAsync(string name, string title, bool? screenshots, bool? snapshots, bool? sources) + => Connection.SendMessageToServerAsync( + Guid, + "tracingStart", + new Dictionary + { + ["name"] = name, + ["title"] = title, + ["screenshots"] = screenshots, + ["snapshots"] = snapshots, + ["sources"] = sources, + }); + + internal Task TracingStopAsync() + => Connection.SendMessageToServerAsync( + Guid, + "tracingStop"); + + internal Task StartChunkAsync(string title = null) + => Connection.SendMessageToServerAsync(Guid, "tracingStartChunk", new Dictionary + { + ["title"] = title, + }); + + internal async Task<(Artifact Artifact, List SourceEntries)> StopChunkAsync(string mode) + { + var result = await Connection.SendMessageToServerAsync(Guid, "tracingStopChunk", new Dictionary + { + ["mode"] = mode, + }).ConfigureAwait(false); + + var artifact = result.GetObject("artifact", Connection); + List sourceEntries = new() { }; + if (result.Value.TryGetProperty("sourceEntries", out var sourceEntriesElement)) + { + var sourceEntriesEnumerator = sourceEntriesElement.EnumerateArray(); + while (sourceEntriesEnumerator.MoveNext()) + { + JsonElement current = sourceEntriesEnumerator.Current; + sourceEntries.Add(current.Deserialize(new JsonSerializerOptions() + { + PropertyNameCaseInsensitive = true, + })); + } + } + return (artifact, sourceEntries); + } + } +} diff --git a/src/Playwright/Transport/Connection.cs b/src/Playwright/Transport/Connection.cs index 98fc0e15f5..3f4b265ea6 100644 --- a/src/Playwright/Transport/Connection.cs +++ b/src/Playwright/Transport/Connection.cs @@ -331,6 +331,9 @@ private void CreateRemoteObject(string parentGuid, ChannelOwnerType type, string case ChannelOwnerType.Stream: result = new Stream(parent, guid); break; + case ChannelOwnerType.Tracing: + result = new Tracing(parent, guid); + break; default: TraceMessage("pw:dotnet", "Missing type " + type); break; diff --git a/src/Playwright/Transport/Protocol/Generated/APIRequestContextInitializer.cs b/src/Playwright/Transport/Protocol/Generated/APIRequestContextInitializer.cs index ee65c12fb9..e0214ec6f1 100644 --- a/src/Playwright/Transport/Protocol/Generated/APIRequestContextInitializer.cs +++ b/src/Playwright/Transport/Protocol/Generated/APIRequestContextInitializer.cs @@ -28,5 +28,6 @@ namespace Microsoft.Playwright.Transport.Protocol { internal class APIRequestContextInitializer { + public Core.Tracing Tracing { get; set; } } } diff --git a/src/Playwright/Transport/Protocol/Generated/BrowserContextInitializer.cs b/src/Playwright/Transport/Protocol/Generated/BrowserContextInitializer.cs index a7db0d438b..670926ad06 100644 --- a/src/Playwright/Transport/Protocol/Generated/BrowserContextInitializer.cs +++ b/src/Playwright/Transport/Protocol/Generated/BrowserContextInitializer.cs @@ -31,5 +31,7 @@ internal class BrowserContextInitializer : EventTargetInitializer public bool IsChromium { get; set; } public Core.APIRequestContext APIRequestContext { get; set; } + + public Core.Tracing Tracing { get; set; } } } diff --git a/src/Playwright/Transport/Protocol/Generated/TracingInitializer.cs b/src/Playwright/Transport/Protocol/Generated/TracingInitializer.cs new file mode 100644 index 0000000000..18f90d1f37 --- /dev/null +++ b/src/Playwright/Transport/Protocol/Generated/TracingInitializer.cs @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (c) Microsoft Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and / or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +using System.Collections.Generic; + +namespace Microsoft.Playwright.Transport.Protocol +{ + internal class TracingInitializer + { + } +}