Skip to content

Commit e9f1ecd

Browse files
authored
BigInteger support and EvaluateTests sync-up (#1059)
* BigInteger support and EvaluateTests sync-up * CodeFactor
1 parent 87fd1df commit e9f1ecd

File tree

4 files changed

+210
-129
lines changed

4 files changed

+210
-129
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
var globalVar = 123;
3+
</script>

lib/PuppeteerSharp.Tests/PageTests/EvaluateTests.cs

Lines changed: 172 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Xunit;
66
using Xunit.Abstractions;
77
using PuppeteerSharp.Helpers.Json;
8+
using System.Numerics;
89

910
namespace PuppeteerSharp.Tests.PageTests
1011
{
@@ -15,15 +16,6 @@ public EvaluateTests(ITestOutputHelper output) : base(output)
1516
{
1617
}
1718

18-
[Theory]
19-
[InlineData("1 + 5;", 6)] //ShouldAcceptSemiColons
20-
[InlineData("2 + 5\n// do some math!'", 7)] //ShouldAceptStringComments
21-
public async Task BasicIntExressionEvaluationTest(string script, object expected)
22-
{
23-
var result = await Page.EvaluateExpressionAsync<int>(script);
24-
Assert.Equal(expected, result);
25-
}
26-
2719
[Theory]
2820
[InlineData("() => 7 * 3", 21)] //ShouldWork
2921
[InlineData("() => Promise.resolve(8 * 7)", 56)] //ShouldAwaitPromise
@@ -33,6 +25,72 @@ public async Task BasicIntFunctionEvaluationTest(string script, object expected)
3325
Assert.Equal(expected, result);
3426
}
3527

28+
[Fact]
29+
public async Task ShouldTransferBigInt()
30+
{
31+
var result = await Page.EvaluateFunctionAsync<BigInteger>("a => a", new BigInteger(42));
32+
Assert.Equal(new BigInteger(42), result);
33+
}
34+
35+
[Theory]
36+
[InlineData(double.NaN)] //ShouldTransferNaN
37+
[InlineData(-0)] //ShouldTransferNegative0
38+
[InlineData(double.PositiveInfinity)] //ShouldTransferInfinity
39+
[InlineData(double.NegativeInfinity)] //ShouldTransferNegativeInfinty
40+
public async Task BasicTransferTest(object transferObject)
41+
{
42+
var result = await Page.EvaluateFunctionAsync<object>("a => a", transferObject);
43+
Assert.Equal(transferObject, result);
44+
}
45+
46+
[Fact]
47+
public async Task ShouldTransferArrays()
48+
{
49+
var result = await Page.EvaluateFunctionAsync<int[]>("a => a", new int[] { 1, 2, 3 });
50+
Assert.Equal(new int[] { 1, 2, 3 }, result);
51+
}
52+
53+
[Fact]
54+
public async Task ShouldTransferArraysAsArraysNotObjects()
55+
{
56+
var result = await Page.EvaluateFunctionAsync<bool>("a => Array.isArray(a)", new int[] { 1, 2, 3 });
57+
Assert.True(result);
58+
}
59+
60+
[Fact]
61+
public async Task ShouldModifyGlobalEnvironment()
62+
{
63+
await Page.EvaluateFunctionAsync("() => window.globalVar = 123");
64+
Assert.Equal(123, await Page.EvaluateFunctionAsync<int>("() => window.globalVar"));
65+
}
66+
67+
[Fact]
68+
public async Task ShouldEvaluateInThePageContext()
69+
{
70+
await Page.GoToAsync(TestConstants.ServerUrl + "/global-var.html");
71+
Assert.Equal(123, await Page.EvaluateFunctionAsync<int>("() => window.globalVar"));
72+
}
73+
74+
[Fact]
75+
public async Task ShouldReturnUndefinedForObjectsWithSymbols()
76+
=> Assert.Null(await Page.EvaluateFunctionAsync<object>("() => [Symbol('foo4')]"));
77+
78+
[Fact]
79+
public async Task ShouldThrowWhenEvaluationTriggersReload()
80+
{
81+
var exception = await Assert.ThrowsAsync<EvaluationFailedException>(() =>
82+
{
83+
return Page.EvaluateFunctionAsync(@"() => {
84+
location.reload();
85+
return new Promise(resolve => {
86+
setTimeout(() => resolve(1), 0);
87+
});
88+
}");
89+
});
90+
91+
Assert.Contains("Protocol error", exception.Message);
92+
}
93+
3694
[Fact]
3795
public async Task ShouldWorkRightAfterFrameNavigated()
3896
{
@@ -47,6 +105,19 @@ public async Task ShouldWorkRightAfterFrameNavigated()
47105
Assert.Equal(42, await frameEvaluation);
48106
}
49107

108+
[Fact]
109+
public async Task ShouldWorkFromInsideAnExposedFunction()
110+
{
111+
await Page.ExposeFunctionAsync("callController", async (int a, int b) =>
112+
{
113+
return await Page.EvaluateFunctionAsync<int>("(a, b) => a * b", a, b);
114+
});
115+
var result = await Page.EvaluateFunctionAsync<int>(@"async function() {
116+
return await callController(9, 3);
117+
}");
118+
Assert.Equal(27, result);
119+
}
120+
50121
[Fact]
51122
public async Task ShouldRejectPromiseWithExeption()
52123
{
@@ -58,6 +129,22 @@ public async Task ShouldRejectPromiseWithExeption()
58129
Assert.Contains("not is not defined", exception.Message);
59130
}
60131

132+
[Fact]
133+
public async Task ShouldSupportThrownStringsAsErrorMessages()
134+
{
135+
var exception = await Assert.ThrowsAsync<EvaluationFailedException>(
136+
() => Page.EvaluateExpressionAsync("throw 'qwerty'"));
137+
Assert.Contains("qwerty", exception.Message);
138+
}
139+
140+
[Fact]
141+
public async Task ShouldSupportThrownNumbersAsErrorMessages()
142+
{
143+
var exception = await Assert.ThrowsAsync<EvaluationFailedException>(
144+
() => Page.EvaluateExpressionAsync("throw 100500"));
145+
Assert.Contains("100500", exception.Message);
146+
}
147+
61148
[Fact]
62149
public async Task SouldReturnComplexObjects()
63150
{
@@ -70,21 +157,10 @@ public async Task SouldReturnComplexObjects()
70157
}
71158

72159
[Fact]
73-
public async Task ShouldWorkWithDifferentSerializerSettings()
160+
public async Task ShouldReturnBigInt()
74161
{
75-
var result = await Page.EvaluateFunctionAsync<ComplexObjectTestClass>("() => { return { foo: 'bar' }}");
76-
Assert.Equal("bar", result.Foo);
77-
78-
result = (await Page.EvaluateFunctionAsync<JToken>("() => { return { Foo: 'bar' }}"))
79-
.ToObject<ComplexObjectTestClass>(new JsonSerializerSettings());
80-
Assert.Equal("bar", result.Foo);
81-
82-
result = await Page.EvaluateExpressionAsync<ComplexObjectTestClass>("var obj = { foo: 'bar' }; obj;");
83-
Assert.Equal("bar", result.Foo);
84-
85-
result = (await Page.EvaluateExpressionAsync<JToken>("var obj = { Foo: 'bar' }; obj;"))
86-
.ToObject<ComplexObjectTestClass>(new JsonSerializerSettings());
87-
Assert.Equal("bar", result.Foo);
162+
var result = await Page.EvaluateFunctionAsync<object>("() => BigInt(42)");
163+
Assert.Equal(new BigInteger(42), result);
88164
}
89165

90166
[Theory]
@@ -109,23 +185,30 @@ public async Task ShouldAcceptNullAsOneOfMultipleParameters()
109185
}
110186

111187
[Fact]
112-
public async Task ShouldProperlyIgnoreUndefinedFields()
113-
{
114-
var result = await Page.EvaluateFunctionAsync<Dictionary<string, object>>("() => ({a: undefined})");
115-
Assert.Empty(result);
116-
}
188+
public async Task ShouldReturnNullForNonSerializableObjects()
189+
=> Assert.Null(await Page.EvaluateFunctionAsync("() => window"));
117190

118191
[Fact]
119-
public async Task ShouldProperlySerializeNullFields()
192+
public async Task ShouldFailForCircularObject()
120193
{
121-
var result = await Page.EvaluateFunctionAsync<Dictionary<string, object>>("() => ({a: null})");
122-
Assert.True(result.ContainsKey("a"));
123-
Assert.Null(result["a"]);
194+
var result = await Page.EvaluateFunctionAsync(@"() => {
195+
const a = {};
196+
const b = {a};
197+
a.b = b;
198+
return a;
199+
}");
200+
201+
Assert.Null(result);
124202
}
125203

126-
[Fact]
127-
public async Task ShouldReturnNullForNonSerializableObjects()
128-
=> Assert.Null(await Page.EvaluateFunctionAsync("() => window"));
204+
[Theory]
205+
[InlineData("1 + 5;", 6)] //ShouldAcceptSemiColons
206+
[InlineData("2 + 5\n// do some math!'", 7)] //ShouldAceptStringComments
207+
public async Task BasicIntExressionEvaluationTest(string script, object expected)
208+
{
209+
var result = await Page.EvaluateExpressionAsync<int>(script);
210+
Assert.Equal(expected, result);
211+
}
129212

130213
[Fact]
131214
public async Task ShouldAcceptElementHandleAsAnArgument()
@@ -158,6 +241,59 @@ public async Task ShouldThrowIfElementHandlesAreFromOtherFrames()
158241
Assert.Contains("JSHandles can be evaluated only in the context they were created", exception.Message);
159242
}
160243

244+
[Fact]
245+
public async Task ShouldSimulateAUserGesture()
246+
=> Assert.True(await Page.EvaluateFunctionAsync<bool>("() => document.execCommand('copy')"));
247+
248+
[Fact]
249+
public async Task ShouldThrowANiceErrorAfterANavigation()
250+
{
251+
var executionContext = await Page.MainFrame.GetExecutionContextAsync();
252+
253+
await Task.WhenAll(
254+
Page.WaitForNavigationAsync(),
255+
executionContext.EvaluateFunctionAsync("() => window.location.reload()")
256+
);
257+
var ex = await Assert.ThrowsAsync<EvaluationFailedException>(() =>
258+
{
259+
return executionContext.EvaluateFunctionAsync("() => null");
260+
});
261+
Assert.Contains("navigation", ex.Message);
262+
}
263+
264+
[Fact]
265+
public async Task ShouldWorkWithDifferentSerializerSettings()
266+
{
267+
var result = await Page.EvaluateFunctionAsync<ComplexObjectTestClass>("() => { return { foo: 'bar' }}");
268+
Assert.Equal("bar", result.Foo);
269+
270+
result = (await Page.EvaluateFunctionAsync<JToken>("() => { return { Foo: 'bar' }}"))
271+
.ToObject<ComplexObjectTestClass>(new JsonSerializerSettings());
272+
Assert.Equal("bar", result.Foo);
273+
274+
result = await Page.EvaluateExpressionAsync<ComplexObjectTestClass>("var obj = { foo: 'bar' }; obj;");
275+
Assert.Equal("bar", result.Foo);
276+
277+
result = (await Page.EvaluateExpressionAsync<JToken>("var obj = { Foo: 'bar' }; obj;"))
278+
.ToObject<ComplexObjectTestClass>(new JsonSerializerSettings());
279+
Assert.Equal("bar", result.Foo);
280+
}
281+
282+
[Fact]
283+
public async Task ShouldProperlyIgnoreUndefinedFields()
284+
{
285+
var result = await Page.EvaluateFunctionAsync<Dictionary<string, object>>("() => ({a: undefined})");
286+
Assert.Empty(result);
287+
}
288+
289+
[Fact]
290+
public async Task ShouldProperlySerializeNullFields()
291+
{
292+
var result = await Page.EvaluateFunctionAsync<Dictionary<string, object>>("() => ({a: null})");
293+
Assert.True(result.ContainsKey("a"));
294+
Assert.Null(result["a"]);
295+
}
296+
161297
[Fact]
162298
public async Task ShouldAcceptObjectHandleAsAnArgument()
163299
{
@@ -196,84 +332,6 @@ public async Task ShouldWarnOnNestedObjectHandles()
196332
Assert.Contains("Are you passing a nested JSHandle?", exception.Message);
197333
}
198334

199-
[Fact]
200-
public async Task ShouldWorkFromInsideAnExposedFunction()
201-
{
202-
await Page.ExposeFunctionAsync("callController", async (int a, int b) =>
203-
{
204-
return await Page.EvaluateFunctionAsync<int>("(a, b) => a * b", a, b);
205-
});
206-
var result = await Page.EvaluateFunctionAsync<int>(@"async function() {
207-
return await callController(9, 3);
208-
}");
209-
Assert.Equal(27, result);
210-
}
211-
212-
[Fact]
213-
public async Task ShouldSupportThrownStringsAsErrorMessages()
214-
{
215-
var exception = await Assert.ThrowsAsync<EvaluationFailedException>(
216-
() => Page.EvaluateExpressionAsync("throw 'qwerty'"));
217-
Assert.Contains("qwerty", exception.Message);
218-
}
219-
220-
[Fact]
221-
public async Task ShouldSupportThrownNumbersAsErrorMessages()
222-
{
223-
var exception = await Assert.ThrowsAsync<EvaluationFailedException>(
224-
() => Page.EvaluateExpressionAsync("throw 100500"));
225-
Assert.Contains("100500", exception.Message);
226-
}
227-
228-
[Fact]
229-
public async Task ShouldThrowWhenEvaluationTriggersReload()
230-
{
231-
var exception = await Assert.ThrowsAsync<EvaluationFailedException>(() =>
232-
{
233-
return Page.EvaluateFunctionAsync(@"() => {
234-
location.reload();
235-
return new Promise(resolve => {
236-
setTimeout(() => resolve(1), 0);
237-
});
238-
}");
239-
});
240-
241-
Assert.Contains("Protocol error", exception.Message);
242-
}
243-
244-
[Fact]
245-
public async Task ShouldFailForCircularObject()
246-
{
247-
var result = await Page.EvaluateFunctionAsync(@"() => {
248-
const a = {};
249-
const b = {a};
250-
a.b = b;
251-
return a;
252-
}");
253-
254-
Assert.Null(result);
255-
}
256-
257-
[Fact]
258-
public async Task ShouldSimulateAUserGesture()
259-
=> Assert.True(await Page.EvaluateFunctionAsync<bool>("() => document.execCommand('copy')"));
260-
261-
[Fact]
262-
public async Task ShouldThrowANiceErrorAfterANavigation()
263-
{
264-
var executionContext = await Page.MainFrame.GetExecutionContextAsync();
265-
266-
await Task.WhenAll(
267-
Page.WaitForNavigationAsync(),
268-
executionContext.EvaluateFunctionAsync("() => window.location.reload()")
269-
);
270-
var ex = await Assert.ThrowsAsync<EvaluationFailedException>(() =>
271-
{
272-
return executionContext.EvaluateFunctionAsync("() => null");
273-
});
274-
Assert.Contains("navigation", ex.Message);
275-
}
276-
277335
[Fact]
278336
public async Task ShouldWorkWithoutGenerics()
279337
{
@@ -301,4 +359,4 @@ public class ComplexObjectTestClass
301359
public string Foo { get; set; }
302360
}
303361
}
304-
}
362+
}

lib/PuppeteerSharp/ExecutionContext.cs

100755100644
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using PuppeteerSharp.Messaging;
88
using PuppeteerSharp.Helpers;
99
using static PuppeteerSharp.Messaging.RuntimeQueryObjectsResponse;
10+
using System.Numerics;
1011

1112
namespace PuppeteerSharp
1213
{
@@ -221,6 +222,12 @@ private object FormatArgument(object arg)
221222
{
222223
switch (arg)
223224
{
225+
case BigInteger big:
226+
return new { unserializableValue = $"{big}n" };
227+
228+
case int integer when integer == -0:
229+
return new { unserializableValue = "-0" };
230+
224231
case double d:
225232
if (double.IsPositiveInfinity(d))
226233
{

0 commit comments

Comments
 (0)