1+ using Microsoft . AspNetCore . Http ;
2+ using System ;
3+ using System . Linq ;
4+ using System . Threading . Tasks ;
5+ using Xunit ;
6+
7+ namespace PuppeteerSharp . Tests . Target
8+ {
9+ [ Collection ( "PuppeteerLoaderFixture collection" ) ]
10+ public class TargetTests : PuppeteerPageBaseTest
11+ {
12+ [ Fact ]
13+ public void BrowserTargetsShouldReturnAllOfTheTargets ( )
14+ {
15+ // The pages will be the testing page and the original newtab page
16+ var targets = Browser . Targets ( ) ;
17+ Assert . Contains ( targets , target => target . Type == "page"
18+ && target . Url == TestConstants . AboutBlank ) ;
19+ Assert . Contains ( targets , target => target . Type == "other"
20+ && target . Url == string . Empty ) ;
21+ }
22+
23+ [ Fact ]
24+ public async Task BrowserPagesShouldReturnAllOfThePages ( )
25+ {
26+ // The pages will be the testing page and the original newtab page
27+ var allPages = ( await Browser . PagesAsync ( ) ) . ToArray ( ) ;
28+ Assert . Equal ( 2 , allPages . Length ) ;
29+ Assert . Contains ( Page , allPages ) ;
30+ Assert . NotSame ( allPages [ 0 ] , allPages [ 1 ] ) ;
31+ }
32+
33+ [ Fact ]
34+ public async Task ShouldBeAbleToUseTheDefaultPageInTheBrowser ( )
35+ {
36+ // The pages will be the testing page and the original newtab page
37+ var allPages = await Browser . PagesAsync ( ) ;
38+ var originalPage = allPages . First ( p => p != Page ) ;
39+ Assert . Equal ( "Hello world" , await originalPage . EvaluateExpressionAsync < string > ( "['Hello', 'world'].join(' ')" ) ) ;
40+ Assert . NotNull ( await originalPage . GetElementAsync ( "body" ) ) ;
41+ }
42+
43+ [ Fact ]
44+ public async Task ShouldReportWhenANewPageIsCreatedAndClosed ( )
45+ {
46+ var otherPageTaskCompletion = new TaskCompletionSource < PuppeteerSharp . Page > ( ) ;
47+ async void TargetCreatedEventHandler ( object sender , TargetChangedArgs e )
48+ {
49+ otherPageTaskCompletion . SetResult ( await e . Target . PageAsync ( ) ) ;
50+ Browser . TargetCreated -= TargetCreatedEventHandler ;
51+ }
52+ Browser . TargetCreated += TargetCreatedEventHandler ;
53+ await Page . EvaluateFunctionHandleAsync ( "url => window.open(url)" , TestConstants . CrossProcessUrl ) ;
54+ var otherPage = await otherPageTaskCompletion . Task ;
55+ Assert . Contains ( TestConstants . CrossProcessUrl , otherPage . Url ) ;
56+
57+ Assert . Equal ( "Hello world" , await otherPage . EvaluateExpressionAsync < string > ( "['Hello', 'world'].join(' ')" ) ) ;
58+ Assert . NotNull ( await otherPage . GetElementAsync ( "body" ) ) ;
59+
60+ var allPages = await Browser . PagesAsync ( ) ;
61+ Assert . Contains ( Page , allPages ) ;
62+ Assert . Contains ( otherPage , allPages ) ;
63+
64+ var closePageTaskCompletion = new TaskCompletionSource < PuppeteerSharp . Page > ( ) ;
65+ async void TargetDestroyedEventHandler ( object sender , TargetChangedArgs e )
66+ {
67+ closePageTaskCompletion . SetResult ( await e . Target . PageAsync ( ) ) ;
68+ Browser . TargetDestroyed -= TargetDestroyedEventHandler ;
69+ }
70+ Browser . TargetDestroyed += TargetDestroyedEventHandler ;
71+ await otherPage . CloseAsync ( ) ;
72+ Assert . Equal ( otherPage , await closePageTaskCompletion . Task ) ;
73+
74+ allPages = await Task . WhenAll ( Browser . Targets ( ) . Select ( target => target . PageAsync ( ) ) ) ;
75+ Assert . Contains ( Page , allPages ) ;
76+ Assert . DoesNotContain ( otherPage , allPages ) ;
77+ }
78+
79+ [ Fact ]
80+ public async Task ShouldReportWhenAServiceWorkerIsCreatedAndDestroyed ( )
81+ {
82+ await Page . GoToAsync ( TestConstants . EmptyPage ) ;
83+ var createdTargetTaskCompletion = new TaskCompletionSource < PuppeteerSharp . Target > ( ) ;
84+ void TargetCreatedEventHandler ( object sender , TargetChangedArgs e )
85+ {
86+ createdTargetTaskCompletion . SetResult ( e . Target ) ;
87+ Browser . TargetCreated -= TargetCreatedEventHandler ;
88+ }
89+ Browser . TargetCreated += TargetCreatedEventHandler ;
90+ var registration = await Page . EvaluateExpressionHandleAsync ( "navigator.serviceWorker.register('sw.js')" ) ;
91+
92+ var createdTarget = await createdTargetTaskCompletion . Task ;
93+ Assert . Equal ( "service_worker" , createdTarget . Type ) ;
94+ Assert . Equal ( TestConstants . ServerUrl + "/sw.js" , createdTarget . Url ) ;
95+
96+ var targetDestroyedTaskCompletion = new TaskCompletionSource < PuppeteerSharp . Target > ( ) ;
97+ void TargetDestroyedEventHandler ( object sender , TargetChangedArgs e )
98+ {
99+ targetDestroyedTaskCompletion . SetResult ( e . Target ) ;
100+ Browser . TargetDestroyed -= TargetDestroyedEventHandler ;
101+ }
102+ Browser . TargetDestroyed += TargetDestroyedEventHandler ;
103+ await Page . EvaluateFunctionAsync ( "registration => registration.unregister()" , registration ) ;
104+ Assert . Equal ( createdTarget , await targetDestroyedTaskCompletion . Task ) ;
105+ }
106+
107+ [ Fact ]
108+ public async Task ShouldReportWhenATargetUrlChanges ( )
109+ {
110+ await Page . GoToAsync ( TestConstants . EmptyPage ) ;
111+
112+ var changedTargetTaskCompletion = new TaskCompletionSource < PuppeteerSharp . Target > ( ) ;
113+ void ChangedTargetEventHandler ( object sender , TargetChangedArgs e )
114+ {
115+ changedTargetTaskCompletion . SetResult ( e . Target ) ;
116+ Browser . TargetChanged -= ChangedTargetEventHandler ;
117+ }
118+ Browser . TargetChanged += ChangedTargetEventHandler ;
119+
120+ await Page . GoToAsync ( TestConstants . CrossProcessUrl + "/" ) ;
121+ var changedTarget = await changedTargetTaskCompletion . Task ;
122+ Assert . Equal ( TestConstants . CrossProcessUrl + "/" , changedTarget . Url ) ;
123+
124+ changedTargetTaskCompletion = new TaskCompletionSource < PuppeteerSharp . Target > ( ) ;
125+ Browser . TargetChanged += ChangedTargetEventHandler ;
126+ await Page . GoToAsync ( TestConstants . EmptyPage ) ;
127+ changedTarget = await changedTargetTaskCompletion . Task ;
128+ Assert . Equal ( TestConstants . EmptyPage , changedTarget . Url ) ;
129+ }
130+
131+ [ Fact ]
132+ public async Task ShouldNotReportUninitializedPages ( )
133+ {
134+ var targetChanged = false ;
135+ EventHandler < TargetChangedArgs > listener = ( sender , e ) => targetChanged = true ;
136+ Browser . TargetChanged += listener ;
137+ var targetCompletionTask = new TaskCompletionSource < PuppeteerSharp . Target > ( ) ;
138+ void TargetCreatedEventHandler ( object sender , TargetChangedArgs e )
139+ {
140+ targetCompletionTask . SetResult ( e . Target ) ;
141+ Browser . TargetCreated -= TargetCreatedEventHandler ;
142+ }
143+ Browser . TargetCreated += TargetCreatedEventHandler ;
144+ var newPageTask = Browser . NewPageAsync ( ) ;
145+ var target = await targetCompletionTask . Task ;
146+ Assert . Equal ( TestConstants . AboutBlank , target . Url ) ;
147+
148+ var newPage = await newPageTask ;
149+ targetCompletionTask = new TaskCompletionSource < PuppeteerSharp . Target > ( ) ;
150+ Browser . TargetCreated += TargetCreatedEventHandler ;
151+ var evaluateTask = newPage . EvaluateExpressionHandleAsync ( "window.open('about:blank')" ) ;
152+ var target2 = await targetCompletionTask . Task ;
153+ Assert . Equal ( TestConstants . AboutBlank , target2 . Url ) ;
154+ await evaluateTask ;
155+ await newPage . CloseAsync ( ) ;
156+ Assert . False ( targetChanged , "target should not be reported as changed" ) ;
157+ Browser . TargetChanged -= listener ;
158+ }
159+
160+ [ Fact ]
161+ public async Task ShouldNotCrashWhileRedirectingIfOriginalRequestWasMissed ( )
162+ {
163+ var serverResponseEnd = new TaskCompletionSource < bool > ( ) ;
164+ var serverResponse = ( HttpResponse ) null ;
165+ Server . SetRoute ( "/one-style.css" , context => { serverResponse = context . Response ; return serverResponseEnd . Task ; } ) ;
166+ // Open a new page. Use window.open to connect to the page later.
167+ await Task . WhenAll (
168+ Page . EvaluateFunctionHandleAsync ( "url => window.open(url)" , TestConstants . ServerUrl + "/one-style.html" ) ,
169+ Server . WaitForRequest ( "/one-style.css" )
170+ ) ;
171+ // Connect to the opened page.
172+ var target = Browser . Targets ( ) . First ( t => t . Url . Contains ( "one-style.html" ) ) ;
173+ var newPage = await target . PageAsync ( ) ;
174+ // Issue a redirect.
175+ serverResponse . Redirect ( "/injectedstyle.css" ) ;
176+ serverResponseEnd . SetResult ( true ) ;
177+ // Wait for the new page to load.
178+ await WaitForEvents ( newPage . Client , "Page.loadEventFired" ) ;
179+ // Cleanup.
180+ await newPage . CloseAsync ( ) ;
181+ }
182+ }
183+ }
0 commit comments