Skip to content

Commit 4fe6ee4

Browse files
authored
[dotnet] [bidi] Possibility to reset viewport (#16601)
1 parent ae2b6de commit 4fe6ee4

File tree

4 files changed

+133
-5
lines changed

4 files changed

+133
-5
lines changed

dotnet/src/webdriver/BiDi/BrowsingContext/SetViewportCommand.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,21 @@
1717
// under the License.
1818
// </copyright>
1919

20+
using OpenQA.Selenium.BiDi.Json.Converters;
21+
using System.Text.Json.Serialization;
22+
2023
namespace OpenQA.Selenium.BiDi.BrowsingContext;
2124

2225
internal sealed class SetViewportCommand(SetViewportParameters @params)
2326
: Command<SetViewportParameters, SetViewportResult>(@params, "browsingContext.setViewport");
2427

25-
internal sealed record SetViewportParameters(BrowsingContext Context, Viewport? Viewport, double? DevicePixelRatio) : Parameters;
28+
internal sealed record SetViewportParameters(BrowsingContext Context, [property: JsonConverter(typeof(OptionalConverter<Viewport?>))] Optional<Viewport?>? Viewport, [property: JsonConverter(typeof(OptionalConverter<double?>))] Optional<double?>? DevicePixelRatio) : Parameters;
2629

2730
public sealed class SetViewportOptions : CommandOptions
2831
{
29-
public Viewport? Viewport { get; set; }
32+
public Optional<Viewport?>? Viewport { get; set; }
3033

31-
public double? DevicePixelRatio { get; set; }
34+
public Optional<double?>? DevicePixelRatio { get; set; }
3235
}
3336

3437
public readonly record struct Viewport(long Width, long Height);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// <copyright file="OptionalConverter.cs" company="Selenium Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
// </copyright>
19+
20+
using System;
21+
using System.Text.Json;
22+
using System.Text.Json.Serialization;
23+
24+
namespace OpenQA.Selenium.BiDi.Json.Converters;
25+
26+
public sealed class OptionalConverter<T> : JsonConverter<Optional<T>>
27+
{
28+
public override Optional<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
29+
{
30+
if (reader.TokenType == JsonTokenType.Null)
31+
{
32+
reader.Read(); // consume null
33+
return new Optional<T>(default!);
34+
}
35+
36+
T value = JsonSerializer.Deserialize<T>(ref reader, options)!;
37+
return new Optional<T>(value);
38+
}
39+
40+
public override void Write(Utf8JsonWriter writer, Optional<T> value, JsonSerializerOptions options)
41+
{
42+
if (value.TryGetValue(out var optionalValue))
43+
{
44+
JsonSerializer.Serialize(writer, optionalValue, options);
45+
}
46+
else
47+
{
48+
writer.WriteNullValue();
49+
}
50+
}
51+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// <copyright file="Optional.cs" company="Selenium Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
// </copyright>
19+
20+
using System;
21+
22+
namespace OpenQA.Selenium.BiDi;
23+
24+
public readonly record struct Optional<T>
25+
{
26+
private readonly T _value;
27+
public bool HasValue { get; }
28+
29+
public T Value => HasValue
30+
? _value
31+
: throw new InvalidOperationException("Optional has no value. Check IsSet first.");
32+
33+
public Optional(T value)
34+
{
35+
_value = value;
36+
HasValue = true;
37+
}
38+
39+
public bool TryGetValue(out T value)
40+
{
41+
value = _value;
42+
return HasValue;
43+
}
44+
45+
// implicit conversion from T -> Optional<T>
46+
public static implicit operator Optional<T>(T value) => new(value);
47+
}

dotnet/test/common/BiDi/BrowsingContext/BrowsingContextTest.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,13 +298,40 @@ public async Task CanCaptureScreenshotOfElement()
298298
[Test]
299299
public async Task CanSetViewport()
300300
{
301-
await context.SetViewportAsync(new() { Viewport = new(250, 300) });
301+
Task<int> GetWidthAsync() => context.Script.EvaluateAsync<int>("window.innerWidth", false);
302+
Task<int> GetHeightAsync() => context.Script.EvaluateAsync<int>("window.innerHeight", false);
303+
304+
var defaultWidth = await GetWidthAsync();
305+
var defaultHeight = await GetHeightAsync();
306+
307+
await context.SetViewportAsync(new() { Viewport = new Viewport(250, 300) });
308+
309+
Assert.That(await GetWidthAsync(), Is.EqualTo(250));
310+
Assert.That(await GetHeightAsync(), Is.EqualTo(300));
311+
312+
await context.SetViewportAsync(new() { Viewport = new Viewport(250, 300) });
313+
await context.SetViewportAsync(); // Sends nothing
314+
315+
Assert.That(await GetWidthAsync(), Is.EqualTo(250));
316+
Assert.That(await GetHeightAsync(), Is.EqualTo(300));
317+
318+
await context.SetViewportAsync(new() { Viewport = new Viewport(250, 300) });
319+
await context.SetViewportAsync(new() { Viewport = default }); // Sends nothing
320+
321+
Assert.That(await GetWidthAsync(), Is.EqualTo(250));
322+
Assert.That(await GetHeightAsync(), Is.EqualTo(300));
323+
324+
await context.SetViewportAsync(new() { Viewport = new Viewport(250, 300) });
325+
await context.SetViewportAsync(new() { Viewport = default(Viewport?) }); // Explicitly sends "null", resetting to default
326+
327+
Assert.That(await GetWidthAsync(), Is.EqualTo(defaultWidth));
328+
Assert.That(await GetHeightAsync(), Is.EqualTo(defaultHeight));
302329
}
303330

304331
[Test]
305332
public async Task CanSetViewportWithDevicePixelRatio()
306333
{
307-
await context.SetViewportAsync(new() { Viewport = new(250, 300), DevicePixelRatio = 5 });
334+
await context.SetViewportAsync(new() { Viewport = new Viewport(250, 300), DevicePixelRatio = 5 });
308335
}
309336

310337
[Test]

0 commit comments

Comments
 (0)