Skip to content

Conversation

@PhenX
Copy link
Contributor

@PhenX PhenX commented Apr 12, 2018

closes #13
closes #5

@PhenX PhenX changed the title Implement Console Events, including unit tests Implement Console Events Apr 12, 2018

public string Text()
{
return string.Join(" ", Args);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use arrow function

public class PageConsoleResponse
{
[JsonProperty("type")]
public string Type { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newtonsoft.Json knows how to deserialize enums (StringEnumConverter) so we can use ConsoleType here and remove the conversion in the
ConsoleMessage class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Meir017 I got "inspiration" from Dialog.cs made by @kblok , which uses a mapping method but you are right. @kblok what do you think ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can also improve Dialog go for it :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't think of it back then...
I think I thought that it wouldn't work when there are multiple words (DialogType.BeforeUnload), I just tested it and it works.

[JsonConverter(typeof(StringEnumConverter), true)]
public enum DialogType
{
    Alert,
    Prompt,
    Confirm,
    BeforeUnload
};
JsonConvert.DeserializeObject<DialogType>("beforeunload");
// output: BeforeUnload

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It only works when deserializing since:

JsonConvert.SerializeObject(DialogType.BeforeUnload)
// output: "\"beforeUnload\"" 

and not beforeunload

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A possible solution is to use [EnumMember(Value = "beforeunload")] for enum values where the default cameCase doesn't work, does this make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the changes, but didn't include "[JsonConverter(typeof(StringEnumConverter), true)]", do you confirm it's necessary ? It works find without it to deserialize, do we need to serialize these values too ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't really need it, don't add it.

@PhenX
Copy link
Contributor Author

PhenX commented Apr 13, 2018

I think everything is OK now, do you confirm?

private void OnConsoleAPI(MessageEventArgs e)
private async Task OnConsoleAPI(PageConsoleResponse message)
{
// TODO Do we need to translate this part ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need these comments? ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I have my answer :)

}

var handles = message.Args
.Select(_ => (JSHandle)_frameManager.CreateJsHandle(message.ExecutionContextId, _))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to cast here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I don't really understand why, but it doesn't recognize the return type of CreateJsHandle :

Unable to cast object of type 'System.Collections.Generic.List<dynamic>' to type 'System.Collections.Generic.IList<PuppeteerSharp.JSHandle>'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's because message.Args is dynamic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's normal, it's the original data, not yet transformed into a JSHandle

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too bad.
ok

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First time I see _ in use, fancy!

What would be the benefit of using _ instead of defaulting that argument to null in the method?

@@ -0,0 +1,14 @@
namespace PuppeteerSharp
{
public enum ConsoleType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks

@PhenX
Copy link
Contributor Author

PhenX commented Apr 13, 2018

Argh, I think I did a mistake :/

@Meir017
Copy link
Member

Meir017 commented Apr 13, 2018

if it's too hard to revert you can edit the description of this pull-request and add another closes #xx line
@kblok would this be okey since this is the last task?

@kblok
Copy link
Member

kblok commented Apr 13, 2018

Yeah I'm ok with that @PhenX @Meir017, change the description so the project can track it

@PhenX PhenX changed the title Implement Console Events Implement Console Events and Page.close tests Apr 13, 2018
@PhenX
Copy link
Contributor Author

PhenX commented Apr 13, 2018

@Meir017 @kblok thanks I was starting to panic :)

Assert.Equal("5", (await message.Args[1].JsonValue()).ToString());

// TODO Json Serialization is not exactly the same as in Puppeteer
Assert.Equal("{\r\n \"foo\": \"bar\"\r\n}", (await message.Args[2].JsonValue()).ToString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we should get a json, object, and in line 30 we should get a 5 as an int.

I think that ValueFromRemoteObject should try to parse that as a JSON value. I should succeed parsing strings, numbers, and objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I'll change it to use remoteObject.type (https://chromedevtools.github.io/devtools-protocol/tot/Runtime#type-RemoteObject) with a switch to handle all the cases, what do you think ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, sounds good

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe make JsonValue return Task<T> instead of Task<object>?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this a little bit, the doc says:

Remote object value in case of primitive values or JSON values (if it was requested).

So if we fall there it's because it's serializable, you can just use JSON.Parse in one line

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can make it generic, but let's leave that conversion to JSON.NET.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find a way to make it work for the third assert (with {foo: "bar"}) without using generics, and for the second (with "5"), there are no integers in JS, only numbers, so I have to force it to float. You'll see all this in my next commit.

});
private void OnExecutionContextCreated(ContextPayload contextPayload)
{

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this empty line

}

var handles = message.Args
.Select(_ => (JSHandle)_frameManager.CreateJsHandle(message.ExecutionContextId, _))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First time I see _ in use, fancy!

What would be the benefit of using _ instead of defaulting that argument to null in the method?

@PhenX
Copy link
Contributor Author

PhenX commented Apr 13, 2018

The "_" is not null, it corresponds to the items from the Args array. I use underscore for Queryables and Enumerables by habit :)

@kblok
Copy link
Member

kblok commented Apr 13, 2018

How about the one on CreateJsHandle @PhenX? #LearningMode

@PhenX
Copy link
Contributor Author

PhenX commented Apr 13, 2018

Hum, I'm not sure to understand, do we agree that this :

    var handles = message.Args
        .Select(_ => (JSHandle)_frameManager.CreateJsHandle(message.ExecutionContextId, _))

is the same as this ?

    var handles = message.Args
        .Select(item => (JSHandle)_frameManager.CreateJsHandle(message.ExecutionContextId, item))

or even this ?

    var handles = new List<JSHandle>();
    foreach (var arg in message.Args)
    {
        handles.Add(_frameManager.CreateJsHandle(message.ExecutionContextId, arg));
    }

@Meir017
Copy link
Member

Meir017 commented Apr 13, 2018

I think that once one of the argument is of type dynamic then all of the expression is dynamic but I'm not sure.
The casting will be removed once everything is strongly typed

@PhenX
Copy link
Contributor Author

PhenX commented Apr 13, 2018

@Meir017 yes, I think that's exactly this, I see it with the remoteObject object, I need to convert it explicitly to string in a string variable to get something other than dynamic.

@kblok
Copy link
Member

kblok commented Apr 17, 2018

How are we going with this guy @PhenX ?

@PhenX
Copy link
Contributor Author

PhenX commented Apr 18, 2018

What do you think about my latest changes on jsonvalue?

Assert.Equal("{\r\n \"foo\": \"bar\"\r\n}", (await message.Args[2].JsonValue()).ToString());
Assert.Equal("hello", await message.Args[0].JsonValue());
Assert.Equal(5, await message.Args[1].JsonValue<float>());
Assert.Equal(obj,await message.Args[2].JsonValue<Dictionary<string, object>>());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about testing this?

Assert.Equal("bar", await message.Args[2].JsonValue<dynamic>().foo);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it could be in addition to the current test

switch (objectType)
{
case "object":
return JsonConvert.DeserializeObject<T>(objectValue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think JsonConvert will be able to serialize a "number" a "boolean" and a "bigint", what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it's pretty sure it can

@kblok
Copy link
Member

kblok commented Apr 18, 2018

Looking good!
Could you try pulling from master and see if it builds?

@PhenX
Copy link
Contributor Author

PhenX commented Apr 18, 2018

I'll try and do that tomorrow. When do you think you'll release 0.4?

@kblok
Copy link
Member

kblok commented Apr 18, 2018

I want to release it during the weekend, we are almost there

var newPage = await Browser.NewPageAsync();
var neverResolves = newPage.EvaluateFunctionAsync("() => new Promise(r => {})");

await newPage.CloseAsync();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I noticed on Puppeteer is that they are not awaiting the close
https://github.com/GoogleChrome/puppeteer/blob/v1.0.0/test/test.js#L325

public ConsoleType Type { get; }
public IList<JSHandle> Args { get; }

public ConsoleMessage(ConsoleType type, IList<JSHandle> args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConsoleMessage has a text property which is different from the args

https://github.com/GoogleChrome/puppeteer/blob/v1.0.0/lib/Page.js#L447

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, at the beginning it was present, I didn't see the purpose ... I replaced it by this in ConsoleMessage which does the same

    public string Text() => string.Join(" ", Args);

If really needed I'll change it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, we have to honor Puppeteer

@PhenX
Copy link
Contributor Author

PhenX commented Apr 19, 2018

(•_•)
( •_•)>⌐■-■
(⌐■_■)

@kblok
Copy link
Member

kblok commented Apr 19, 2018

Looks good to me, what do you think @Meir017 ?

@kblok kblok merged commit 5858143 into hardkoded:master Apr 19, 2018
@kblok
Copy link
Member

kblok commented Apr 19, 2018

@PhenX you have officially completed version 0.4 :)

@PhenX
Copy link
Contributor Author

PhenX commented Apr 19, 2018

:D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Page.Events.Console Implement Page.close tests

3 participants