55using Xunit ;
66using Xunit . Abstractions ;
77using PuppeteerSharp . Helpers . Json ;
8+ using System . Numerics ;
89
910namespace 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+ }
0 commit comments