Skip to content

Commit 3683608

Browse files
authored
Introduce ConsoleMessage.Location (#919)
* Some progress * Introduce ConsoleMessage.Location * CodeFactor + Test
1 parent 9d24cdb commit 3683608

File tree

9 files changed

+142
-10
lines changed

9 files changed

+142
-10
lines changed

lib/PuppeteerSharp.Tests/PageTests/Events/ConsoleTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,48 @@ public async Task ShouldTriggerCorrectLog()
119119
Assert.Equal(ConsoleType.Error, message.Type);
120120
}
121121

122+
[Fact]
123+
public async Task ShouldHaveLocationWhenFetchFails()
124+
{
125+
await Page.GoToAsync(TestConstants.EmptyPage);
126+
var consoleTask = new TaskCompletionSource<ConsoleEventArgs>();
127+
Page.Console += (sender, e) => consoleTask.TrySetResult(e);
128+
129+
await Task.WhenAll(
130+
consoleTask.Task,
131+
Page.SetContentAsync("<script>fetch('http://wat');</script>"));
132+
133+
var args = await consoleTask.Task;
134+
Assert.Contains("ERR_NAME", args.Message.Text);
135+
Assert.Equal(ConsoleType.Error, args.Message.Type);
136+
Assert.Equal(new ConsoleMessageLocation
137+
{
138+
URL = "http://wat/",
139+
}, args.Message.Location);
140+
}
141+
142+
[Fact]
143+
public async Task ShouldHaveLocationForConsoleAPICalls()
144+
{
145+
await Page.GoToAsync(TestConstants.EmptyPage);
146+
var consoleTask = new TaskCompletionSource<ConsoleEventArgs>();
147+
Page.Console += (sender, e) => consoleTask.TrySetResult(e);
148+
149+
await Task.WhenAll(
150+
consoleTask.Task,
151+
Page.GoToAsync(TestConstants.ServerUrl + "/consolelog.html"));
152+
153+
var args = await consoleTask.Task;
154+
Assert.Equal("yellow", args.Message.Text);
155+
Assert.Equal(ConsoleType.Log, args.Message.Type);
156+
Assert.Equal(new ConsoleMessageLocation
157+
{
158+
URL = TestConstants.ServerUrl + "/consolelog.html",
159+
LineNumber = 7,
160+
ColumnNumber = 14
161+
}, args.Message.Location);
162+
}
163+
122164
[Fact]
123165
public async Task ShouldNotThrowWhenThereAreConsoleMessagesInDetachedIframes()
124166
{

lib/PuppeteerSharp.Tests/WorkerTests/WorkerTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ public async Task ShouldReportConsoleLogs()
5858

5959
var log = await consoleTcs.Task;
6060
Assert.Equal("1", log.Text);
61+
Assert.Equal(new ConsoleMessageLocation
62+
{
63+
URL = "data:text/javascript,console.log(1)",
64+
LineNumber = 0,
65+
ColumnNumber = 8
66+
}, log.Location);
6167
}
6268

6369
[Fact]

lib/PuppeteerSharp/ConsoleMessage.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,24 @@ public class ConsoleMessage
2323
/// <value>The arguments.</value>
2424
public IList<JSHandle> Args { get; }
2525

26+
/// <summary>
27+
/// Gets the location.
28+
/// </summary>
29+
public ConsoleMessageLocation Location { get; }
30+
2631
/// <summary>
2732
/// Initializes a new instance of the <see cref="ConsoleMessage"/> class.
2833
/// </summary>
2934
/// <param name="type">Type.</param>
3035
/// <param name="text">Text.</param>
3136
/// <param name="args">Arguments.</param>
32-
public ConsoleMessage(ConsoleType type, string text, IList<JSHandle> args = null)
37+
/// <param name="location">Message location</param>
38+
public ConsoleMessage(ConsoleType type, string text, IList<JSHandle> args, ConsoleMessageLocation location = null)
3339
{
3440
Type = type;
3541
Text = text;
3642
Args = args;
43+
Location = location;
3744
}
3845
}
3946
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace PuppeteerSharp
5+
{
6+
/// <summary>
7+
/// Console message location.
8+
/// </summary>
9+
public class ConsoleMessageLocation : IEquatable<ConsoleMessageLocation>
10+
{
11+
/// <summary>
12+
/// URL of the resource if known.
13+
/// </summary>
14+
public string URL { get; set; }
15+
16+
/// <summary>
17+
/// Line number in the resource if known.
18+
/// </summary>
19+
public int? LineNumber { get; set; }
20+
21+
/// <summary>
22+
/// Column number in the resource if known.
23+
/// </summary>
24+
public int? ColumnNumber { get; set; }
25+
26+
/// <inheritdoc/>
27+
public bool Equals(ConsoleMessageLocation other)
28+
=> (URL, LineNumber, ColumnNumber) == (other?.URL, other?.LineNumber, other?.ColumnNumber);
29+
30+
/// <inheritdoc/>
31+
public override bool Equals(object obj) => Equals(obj as ConsoleMessageLocation);
32+
33+
/// <inheritdoc/>
34+
public override int GetHashCode()
35+
=> 412870874 +
36+
EqualityComparer<string>.Default.GetHashCode(URL) +
37+
EqualityComparer<int?>.Default.GetHashCode(LineNumber) +
38+
EqualityComparer<int?>.Default.GetHashCode(ColumnNumber);
39+
40+
/// <inheritdoc/>
41+
public static bool operator ==(ConsoleMessageLocation location1, ConsoleMessageLocation location2)
42+
=> EqualityComparer<ConsoleMessageLocation>.Default.Equals(location1, location2);
43+
44+
/// <inheritdoc/>
45+
public static bool operator !=(ConsoleMessageLocation location1, ConsoleMessageLocation location2)
46+
=> !(location1 == location2);
47+
}
48+
}

lib/PuppeteerSharp/Messaging/LogEntryAddedResponse.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ internal class LogEntry
1212
public RemoteObject[] Args { get; set; }
1313
public ConsoleType Level { get; set; }
1414
public string Text { get; set; }
15+
public string URL { get; set; }
16+
public int? LineNumber { get; set; }
1517
}
1618
}
1719
}

lib/PuppeteerSharp/Messaging/PageConsoleResponse.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ internal class PageConsoleResponse
77
public ConsoleType Type { get; set; }
88
public RemoteObject[] Args { get; set; }
99
public int ExecutionContextId { get; set; }
10+
public StackTrace StackTrace { get; set; }
1011
}
1112
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace PuppeteerSharp.Messaging
2+
{
3+
internal class StackTrace
4+
{
5+
public ConsoleMessageLocation[] CallFrames { get; set; }
6+
}
7+
}

lib/PuppeteerSharp/Page.cs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,7 @@ private Clip ProcessClip(Clip clip)
17441744
{
17451745
var x = Math.Round(clip.X);
17461746
var y = Math.Round(clip.Y);
1747-
1747+
17481748
return new Clip
17491749
{
17501750
X = x,
@@ -1951,7 +1951,7 @@ private async Task OnAttachedToTarget(TargetAttachedToTargetResponse e)
19511951
return;
19521952
}
19531953
var session = Client.CreateSession(TargetType.Worker, sessionId);
1954-
var worker = new Worker(session, targetInfo.Url, AddConsoleMessage, HandleException);
1954+
var worker = new Worker(session, targetInfo.Url, AddConsoleMessageAsync, HandleException);
19551955
_workers[sessionId] = worker;
19561956
WorkerCreated?.Invoke(this, new WorkerEventArgs(worker));
19571957
}
@@ -1967,7 +1967,15 @@ private async Task OnLogEntryAddedAsync(LogEntryAddedResponse e)
19671967
}
19681968
if (e.Entry.Source != TargetType.Worker)
19691969
{
1970-
Console?.Invoke(this, new ConsoleEventArgs(new ConsoleMessage(e.Entry.Level, e.Entry.Text)));
1970+
Console?.Invoke(this, new ConsoleEventArgs(new ConsoleMessage(
1971+
e.Entry.Level,
1972+
e.Entry.Text,
1973+
null,
1974+
new ConsoleMessageLocation
1975+
{
1976+
URL = e.Entry.URL,
1977+
LineNumber = e.Entry.LineNumber
1978+
})));
19711979
}
19721980
}
19731981

@@ -2039,10 +2047,11 @@ private Task OnConsoleAPI(PageConsoleResponse message)
20392047
}
20402048
var ctx = _frameManager.ExecutionContextById(message.ExecutionContextId);
20412049
var values = message.Args.Select(ctx.CreateJSHandle).ToArray();
2042-
return AddConsoleMessage(message.Type, values);
2050+
2051+
return AddConsoleMessageAsync(message.Type, values, message.StackTrace);
20432052
}
20442053

2045-
private async Task AddConsoleMessage(ConsoleType type, JSHandle[] values)
2054+
private async Task AddConsoleMessageAsync(ConsoleType type, JSHandle[] values, Messaging.StackTrace stackTrace)
20462055
{
20472056
if (Console?.GetInvocationList().Length == 0)
20482057
{
@@ -2054,7 +2063,16 @@ private async Task AddConsoleMessage(ConsoleType type, JSHandle[] values)
20542063
? i.ToString()
20552064
: RemoteObjectHelper.ValueFromRemoteObject<string>(i.RemoteObject));
20562065

2057-
var consoleMessage = new ConsoleMessage(type, string.Join(" ", tokens), values);
2066+
var location = new ConsoleMessageLocation();
2067+
if (stackTrace?.CallFrames?.Length > 0)
2068+
{
2069+
var callFrame = stackTrace.CallFrames[0];
2070+
location.URL = callFrame.URL;
2071+
location.LineNumber = callFrame.LineNumber;
2072+
location.ColumnNumber = callFrame.ColumnNumber;
2073+
}
2074+
2075+
var consoleMessage = new ConsoleMessage(type, string.Join(" ", tokens), values, location);
20582076
Console?.Invoke(this, new ConsoleEventArgs(consoleMessage));
20592077
}
20602078

lib/PuppeteerSharp/Worker.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ public class Worker
2828
private readonly ILogger _logger;
2929
private readonly CDPSession _client;
3030
private ExecutionContext _executionContext;
31-
private readonly Func<ConsoleType, JSHandle[], Task> _consoleAPICalled;
31+
private readonly Func<ConsoleType, JSHandle[], StackTrace, Task> _consoleAPICalled;
3232
private readonly Action<EvaluateExceptionResponseDetails> _exceptionThrown;
3333
private readonly TaskCompletionSource<ExecutionContext> _executionContextCallback;
3434
private Func<ExecutionContext, RemoteObject, JSHandle> _jsHandleFactory;
3535

3636
internal Worker(
3737
CDPSession client,
3838
string url,
39-
Func<ConsoleType, JSHandle[], Task> consoleAPICalled,
39+
Func<ConsoleType, JSHandle[], StackTrace, Task> consoleAPICalled,
4040
Action<EvaluateExceptionResponseDetails> exceptionThrown)
4141
{
4242
_logger = client.Connection.LoggerFactory.CreateLogger<Worker>();
@@ -128,7 +128,8 @@ private async Task OnConsoleAPICalled(MessageEventArgs e)
128128
var consoleData = e.MessageData.ToObject<PageConsoleResponse>(true);
129129
await _consoleAPICalled(
130130
consoleData.Type,
131-
consoleData.Args.Select(i => _jsHandleFactory(_executionContext, i)).ToArray())
131+
consoleData.Args.Select(i => _jsHandleFactory(_executionContext, i)).ToArray(),
132+
consoleData.StackTrace)
132133
.ConfigureAwait(false);
133134
}
134135

0 commit comments

Comments
 (0)