diff --git a/lib/PuppeteerSharp.Nunit/TestExpectations/TestExpectations.local.json b/lib/PuppeteerSharp.Nunit/TestExpectations/TestExpectations.local.json index 77217ce8f..8afcc4124 100644 --- a/lib/PuppeteerSharp.Nunit/TestExpectations/TestExpectations.local.json +++ b/lib/PuppeteerSharp.Nunit/TestExpectations/TestExpectations.local.json @@ -525,6 +525,171 @@ "FAIL" ] }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *should accept element handle as an argument*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *tricky*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *circular*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *should throw*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *objects*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *exposed*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *should properly serialize null fields*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *promise*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *error messages*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *should work right after framenavigated*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, + { + "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", + "testIdPattern": "[evaluation.spec] *should work with unicode chars*", + "platforms": [ + "darwin", + "linux", + "win32" + ], + "parameters": [ + "webDriverBiDi" + ], + "expectations": [ + "FAIL" + ] + }, { "comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one", "testIdPattern": "[fixtures.spec] *", diff --git a/lib/PuppeteerSharp.Tests/EvaluationTests/PageEvaluateTests.cs b/lib/PuppeteerSharp.Tests/EvaluationTests/PageEvaluateTests.cs index 2271cb36e..c6af34371 100644 --- a/lib/PuppeteerSharp.Tests/EvaluationTests/PageEvaluateTests.cs +++ b/lib/PuppeteerSharp.Tests/EvaluationTests/PageEvaluateTests.cs @@ -187,6 +187,7 @@ public async Task BasicEvaluationTest(string script, object expected) public async Task ShouldAcceptNullAsOneOfMultipleParameters() { var result = await Page.EvaluateFunctionAsync( + "(a, b) => Object.is(a, null) && Object.is(b, 'foo')", null, "foo"); diff --git a/lib/PuppeteerSharp/Bidi/BidiRealm.cs b/lib/PuppeteerSharp/Bidi/BidiRealm.cs index 4ad170051..814586e24 100644 --- a/lib/PuppeteerSharp/Bidi/BidiRealm.cs +++ b/lib/PuppeteerSharp/Bidi/BidiRealm.cs @@ -27,6 +27,7 @@ using System.Globalization; using System.Linq; using System.Numerics; +using System.Reflection; using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -71,12 +72,12 @@ public void Dispose() internal override Task EvaluateFunctionHandleAsync(string script, params object[] args) => throw new System.NotImplementedException(); internal override async Task EvaluateExpressionAsync(string script) - => DeserializeEvaluationResult(await EvaluateAsync(false, true, script).ConfigureAwait(false)); + => DeserializeResult((await EvaluateAsync(true, true, script).ConfigureAwait(false)).Result.Value); internal override Task EvaluateExpressionAsync(string script) => throw new System.NotImplementedException(); internal override async Task EvaluateFunctionAsync(string script, params object[] args) - => DeserializeEvaluationResult(await EvaluateAsync(false, false, script, args).ConfigureAwait(false)); + => DeserializeResult((await EvaluateAsync(true, false, script, args).ConfigureAwait(false)).Result.Value); internal override Task EvaluateFunctionAsync(string script, params object[] args) => throw new System.NotImplementedException(); @@ -148,22 +149,74 @@ private async Task EvaluateAsync(bool returnByValue, bool return result as EvaluateResultSuccess; } - private T DeserializeEvaluationResult(EvaluateResultSuccess result) + private T DeserializeResult(object result) { + if (result is null) + { + return default; + } + + if (typeof(T) == typeof(JsonElement?)) + { + return (T)(object)JsonSerializer.SerializeToElement(result); + } + // Convert known types first if (typeof(T) == typeof(int)) { - return (T)(object)Convert.ToInt32(result.Result.Value, CultureInfo.InvariantCulture); + return (T)(object)Convert.ToInt32(result, CultureInfo.InvariantCulture); + } + + if (typeof(T) == typeof(double)) + { + return (T)(object)Convert.ToDouble(result, CultureInfo.InvariantCulture); } - switch (result.Result.Type) + if (typeof(T) == typeof(string)) { - case "number": - // TODO: Way too many todos here. - return (T)result.Result.Value; + return (T)result; } - return default; + if (typeof(T) == typeof(bool)) + { + return (T)(object)Convert.ToBoolean(result, CultureInfo.InvariantCulture); + } + + if (typeof(T).IsArray) + { + // Get the element type of the array + var elementType = typeof(T).GetElementType(); + + if (elementType != null && result is IEnumerable enumerable) + { + // Create a list of the element type + var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + + // Iterate over the input and add converted items to the list + foreach (var item in enumerable) + { + var itemToSerialize = item; + + if (item is RemoteValue remoteValue) + { + itemToSerialize = remoteValue.Value; + } + + // Maybe there is a better way to do this. + var deserializedItem = typeof(BidiRealm) + .GetMethod(nameof(DeserializeResult), BindingFlags.Instance | BindingFlags.NonPublic) + ?.MakeGenericMethod(elementType) + .Invoke(this, [itemToSerialize]); + + list.Add(deserializedItem); + } + + // Convert the list to an array + return (T)list.GetType().GetMethod("ToArray")!.Invoke(list, null)!; + } + } + + return (T)result; } private async Task FormatArgumentAsync(object arg) @@ -178,6 +231,11 @@ private async Task FormatArgumentAsync(object arg) arg = await lazyArg(this).ConfigureAwait(false); } + if (arg is null) + { + return LocalValue.Null; + } + switch (arg) { case BigInteger big: