diff --git a/dotnet/src/webdriver/BiDi/Communication/Broker.cs b/dotnet/src/webdriver/BiDi/Communication/Broker.cs index ec7cf5b5bd775..eee788d27e85c 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Broker.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Broker.cs @@ -72,8 +72,8 @@ internal Broker(BiDi bidi, Uri url) Converters = { new BrowsingContextConverter(_bidi), - new BrowserUserContextConverter(bidi), - new BrowserClientWindowConverter(), + new BrowserUserContextConverter(_bidi), + new BrowserClientWindowConverter(_bidi), new NavigationConverter(), new InterceptConverter(_bidi), new RequestConverter(), diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs b/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs index dfee51b37a522..7b003be19ee09 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs @@ -87,6 +87,7 @@ namespace OpenQA.Selenium.BiDi.Communication.Json; [JsonSerializable(typeof(Modules.Browser.RemoveUserContextCommand))] [JsonSerializable(typeof(Modules.Browser.GetClientWindowsCommand))] [JsonSerializable(typeof(Modules.Browser.GetClientWindowsResult))] +[JsonSerializable(typeof(Modules.Browser.SetClientWindowStateCommand))] [JsonSerializable(typeof(Modules.Browser.UserContextInfo))] [JsonSerializable(typeof(IReadOnlyList))] [JsonSerializable(typeof(IReadOnlyList))] diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserClientWindowConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserClientWindowConverter.cs index d04eca3b6b328..c173709f98fe1 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserClientWindowConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BrowserClientWindowConverter.cs @@ -26,11 +26,18 @@ namespace OpenQA.Selenium.BiDi.Communication.Json.Converters; internal class BrowserClientWindowConverter : JsonConverter { + private readonly BiDi _bidi; + + public BrowserClientWindowConverter(BiDi bidi) + { + _bidi = bidi; + } + public override ClientWindow? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var id = reader.GetString(); - return new ClientWindow(id!); + return new ClientWindow(_bidi, id!); } public override void Write(Utf8JsonWriter writer, ClientWindow value, JsonSerializerOptions options) diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs index 822fbe26ae33d..87fdb3d0eb3d1 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/BrowserModule.cs @@ -17,7 +17,6 @@ // under the License. // -using System.Collections.Generic; using System.Threading.Tasks; using OpenQA.Selenium.BiDi.Communication; @@ -51,4 +50,18 @@ public async Task GetClientWindowsAsync(GetClientWindows { return await Broker.ExecuteCommandAsync(new(), options).ConfigureAwait(false); } + + internal async Task SetClientWindowStateAsync(ClientWindow clientWindow, ClientWindowNamedState state, SetClientWindowNamedStateOptions? options = null) + { + var @params = new SetClientWindowNamedStateCommandParameters(clientWindow, state); + + return await Broker.ExecuteCommandAsync(new SetClientWindowStateCommand(@params), options).ConfigureAwait(false); + } + + internal async Task SetClientWindowStateAsync(ClientWindow clientWindow, SetClientWindowRectStateOptions? options = null) + { + var @params = new SetClientWindowRectStateCommandParameters(clientWindow, options); + + return await Broker.ExecuteCommandAsync(new SetClientWindowStateCommand(@params), options).ConfigureAwait(false); + } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindow.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindow.cs index fe80e23374bd3..e066841c7a362 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindow.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindow.cs @@ -17,14 +17,29 @@ // under the License. // +using System.Threading.Tasks; + namespace OpenQA.Selenium.BiDi.Modules.Browser; public record ClientWindow { - internal ClientWindow(string id) + internal ClientWindow(BiDi bidi, string id) { + BiDi = bidi; Id = id; } + internal BiDi BiDi { get; } + internal string Id { get; } + + public Task SetStateAsync(ClientWindowNamedState state, SetClientWindowNamedStateOptions? options = null) + { + return BiDi.Browser.SetClientWindowStateAsync(this, state, options); + } + + public Task SetStateAsync(SetClientWindowRectStateOptions? options = null) + { + return BiDi.Browser.SetClientWindowStateAsync(this, options); + } } diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindowInfo.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindowInfo.cs index c5f123048e983..995b43b7dd347 100644 --- a/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindowInfo.cs +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/ClientWindowInfo.cs @@ -17,11 +17,12 @@ // under the License. // +using OpenQA.Selenium.BiDi.Communication; using System.Text.Json.Serialization; namespace OpenQA.Selenium.BiDi.Modules.Browser; -public record ClientWindowInfo([property: JsonPropertyName("active")] bool IsActive, ClientWindow ClientWindow, ClientWindowState State, int Height, int Width, int X, int Y); +public record ClientWindowInfo([property: JsonPropertyName("active")] bool IsActive, ClientWindow ClientWindow, ClientWindowState State, int Height, int Width, int X, int Y) : EmptyResult; public enum ClientWindowState { diff --git a/dotnet/src/webdriver/BiDi/Modules/Browser/SetClientWindowStateCommand.cs b/dotnet/src/webdriver/BiDi/Modules/Browser/SetClientWindowStateCommand.cs new file mode 100644 index 0000000000000..b3d9ed3e4a8cf --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Modules/Browser/SetClientWindowStateCommand.cs @@ -0,0 +1,66 @@ +// +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +using OpenQA.Selenium.BiDi.Communication; +using System.Text.Json.Serialization; + +namespace OpenQA.Selenium.BiDi.Modules.Browser; + +internal class SetClientWindowStateCommand(SetClientWindowStateCommandParameters @params) + : Command(@params, "browser.setClientWindowState"); + +[JsonDerivedType(typeof(SetClientWindowNamedStateCommandParameters))] +[JsonDerivedType(typeof(SetClientWindowRectStateCommandParameters))] +internal abstract record SetClientWindowStateCommandParameters(ClientWindow ClientWindow) : CommandParameters; + +internal record SetClientWindowNamedStateCommandParameters(ClientWindow ClientWindow, ClientWindowNamedState State) : SetClientWindowStateCommandParameters(ClientWindow); + +internal record SetClientWindowRectStateCommandParameters(ClientWindow ClientWindow, [property: JsonIgnore] SetClientWindowRectStateOptions? Options) : SetClientWindowStateCommandParameters(ClientWindow) +{ + [JsonInclude] + internal string State { get; } = "normal"; + + public int? Width { get; set; } = Options?.Width; + + public int? Height { get; set; } = Options?.Height; + + public int? X { get; set; } = Options?.X; + + public int? Y { get; set; } = Options?.Y; +} + +public record SetClientWindowNamedStateOptions : CommandOptions; + +public record SetClientWindowRectStateOptions : CommandOptions +{ + public int? Width { get; set; } + + public int? Height { get; set; } + + public int? X { get; set; } + + public int? Y { get; set; } +} + +public enum ClientWindowNamedState +{ + Fullscreen, + Maximized, + Minimized +} diff --git a/dotnet/test/common/BiDi/Browser/BrowserTest.cs b/dotnet/test/common/BiDi/Browser/BrowserTest.cs index c00792c310268..9b4a284f4e078 100644 --- a/dotnet/test/common/BiDi/Browser/BrowserTest.cs +++ b/dotnet/test/common/BiDi/Browser/BrowserTest.cs @@ -69,4 +69,28 @@ public async Task CanGetClientWindows() Assert.That(clientWindows, Has.Count.GreaterThanOrEqualTo(1)); Assert.That(clientWindows[0].ClientWindow, Is.Not.Null); } + + [Test] + [Ignore("Not yet implemented by all vendors")] + public async Task CanSetClientWindowNamedState() + { + var clientWindows = await bidi.Browser.GetClientWindowsAsync(); + + var clientWindowInfo = await clientWindows[0].ClientWindow.SetStateAsync(Modules.Browser.ClientWindowNamedState.Fullscreen); + + // TODO: Make assertion meaningfull + Assert.That(clientWindowInfo, Is.Not.Null); + } + + [Test] + [Ignore("Not yet implemented by all vendors")] + public async Task CanSetClientWindowRectState() + { + var clientWindows = await bidi.Browser.GetClientWindowsAsync(); + + var clientWindowInfo = await clientWindows[0].ClientWindow.SetStateAsync(new() { Width = 500, Height = 300, X = 10, Y = 10 }); + + // TODO: Make assertion meaningfull + Assert.That(clientWindowInfo, Is.Not.Null); + } }