Skip to content

Commit 9bebc1f

Browse files
Meir017kblok
authored andcommitted
Implement Target tests (#164)
1 parent 1f17485 commit 9bebc1f

File tree

7 files changed

+256
-52
lines changed

7 files changed

+256
-52
lines changed

lib/PuppeteerSharp.Tests/Puppeteer/PuppeteerConnectTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public async Task ShouldBeAbleToReconnectToADisconnectedBrowser()
4444

4545
using (var browser = await PuppeteerSharp.Puppeteer.ConnectAsync(options))
4646
{
47-
var pages = (await browser.Pages()).ToList();
47+
var pages = (await browser.PagesAsync()).ToList();
4848
var restoredPage = pages.FirstOrDefault(x => x.Url == url);
4949
Assert.NotNull(restoredPage);
5050
var frameDump = FrameUtils.DumpFrames(restoredPage.MainFrame);

lib/PuppeteerSharp.Tests/Puppeteer/PuppeteerLaunchTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public async Task ShouldRejectAllPromisesWhenBrowserIsClosed()
8484
TestConstants.ChromiumRevision))
8585
using (var page = await browser.NewPageAsync())
8686
{
87-
var neverResolves = page.EvaluateFunctionHandle("() => new Promise(r => {})");
87+
var neverResolves = page.EvaluateFunctionHandleAsync("() => new Promise(r => {})");
8888
await browser.CloseAsync();
8989

9090
await neverResolves;
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
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+
}

lib/PuppeteerSharp/Browser.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,27 @@ public async Task<Page> NewPageAsync()
6767

6868
var target = _targets[targetId];
6969
await target.InitializedTask;
70-
return await target.Page();
70+
return await target.PageAsync();
7171
}
7272

73-
public async Task<IEnumerable<Page>> Pages()
74-
=> (await Task.WhenAll(this._targets.Select(x => x.Value.Page()))).Where(x => x != null);
73+
/// <summary>
74+
/// Returns An Array of all active targets
75+
/// </summary>
76+
/// <returns>An Array of all active targets</returns>
77+
public Target[] Targets() => _targets.Values.Where(target => target.IsInitialized).ToArray();
7578

76-
internal void ChangeTarget(TargetInfo targetInfo)
79+
/// <summary>
80+
/// Returns a Task which resolves to an array of all open pages.
81+
/// </summary>
82+
/// <returns>Task which resolves to an array of all open pages.</returns>
83+
public async Task<Page[]> PagesAsync()
84+
=> (await Task.WhenAll(Targets().Select(target => target.PageAsync()))).Where(x => x != null).ToArray();
85+
86+
internal void ChangeTarget(Target target)
7787
{
78-
TargetChanged?.Invoke(this, new TargetChangedArgs()
88+
TargetChanged?.Invoke(this, new TargetChangedArgs
7989
{
80-
TargetInfo = targetInfo
90+
Target = target
8191
});
8292
}
8393

@@ -132,7 +142,8 @@ private void ChangeTargetInfo(MessageEventArgs args)
132142
throw new InvalidTargetException("Target should exists before ChangeTargetInfo");
133143
}
134144

135-
var target = _targets[args.MessageData.targetInfo.targetId.Value];
145+
string targetId = args.MessageData.targetInfo.targetId.Value;
146+
var target = _targets[targetId];
136147
target.TargetInfoChanged(new TargetInfo(args.MessageData.targetInfo));
137148
}
138149

0 commit comments

Comments
 (0)