Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev tools Network and Performance #7212

Merged
merged 28 commits into from
May 20, 2019
Merged

Conversation

adiohana
Copy link
Contributor

@adiohana adiohana commented May 16, 2019

Authors:
Adi Ohana
Shay Dratler
Behalf of Intuit

Summary:
Added Chrome DevTools Network and Performance API's
Added test scenarios that will run when running test_chrome command

Notes And Gaps:

Copy link
Member

@shs96c shs96c left a comment

Choose a reason for hiding this comment

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

Wow. There's a lot here! Thank you! It's mostly great, too. Some general comments:

  • For enums, pick either SHOUTY or NonShouty. General Java style suggests the former, good taste and readability the latter.
  • The project code style is moving towards "one param per line once we need to line break"
  • Avoid using wrapper classes of primitive types where possible. People unbox with glee, and mayhem ensues.
  • Just because the CDP is daft, we don't need to be. If there are matching types in Selenium already, feel free to use them. java.time is a lovely package.

There's a few places where I've expanded on the reasoning behind the comments. I hope it proves helpful.

* Returns all browser cookies. Depending on the backend support, will return detailed cookie information in the cookies field
* @return Array of cookies
*/
public static Command<Set<Cookie>> getAllCookies() {
Copy link
Member

Choose a reason for hiding this comment

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

Selenium already has a org.openqa.selenium.Cookie. There will be lower friction with other parts of the Selenium APIs if we return extant Selenium types. I think it's fine to extend those types to be more meaningful if necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@shs96c
In DevTools cookie the name of the fields are different (e.g expires VS expiry), this will cause the JSON deserializer to break. In addition, there are extra fields in DevTools Cookie.
What to do say about adding "asSeleniumCookie" to DevTools Cookie object. Then, the user can decide which Cookie he wants to use. Another option will be to always return the Selenium Cookie from DevTools command (and loose extra devtools cookie fields)

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 perfectly fine to have internal classes that never leak out of the package to make serialising/deserialising easy, but public APIs should be expressed in Selenium's own classes. Put another, having the "to/fromSeleniumCookie" method on CDP's Cookie class makes sense, but it should be package-level visible, rather than public.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added Cookies operations with Selenium Cookie.

the getCookies will be like:
devTools.send(getAllCookies()).asSeleniumCookies()
which will return List<org.openqa.selenium.Cookie>

the setCookie will just take Selenium Cookie.

third_party/java/testng/BUCK Outdated Show resolved Hide resolved
@p0deje p0deje added the C-java label May 17, 2019
@adiohana
Copy link
Contributor Author

adiohana commented May 18, 2019

@shs96c

all review notes are handled.
1 open issue that we have is calling devtools operations inside a Consumer handler always timing out. This affecting all "Interception" operations where you must continue/block request in order to continue. I think we can handle it in the next phase.

let me know if we can merge this PR and let's discuss about more implementations.

Copy link
Member

@shs96c shs96c left a comment

Choose a reason for hiding this comment

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

There's work to be done before we should ship to users --- lots of the data classes are mutable, there are a large number of primitive wrappers used in fields, and not all data classes have equals and hashCode implemented --- but this is a massive step forward.

<html>
<body>

<form method="post" action="resultPage.html">
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 probably fine now, but prefer creating new pages for tests: there are places where we count elements in tests because we didn't know better when we started writing these things.

* If a network fetch occurs as a result which encounters a redirect an additional Network.requestIntercepted event will be sent with the same InterceptionId.
* (EXPERIMENTAL)
*
* @param interceptionId - Identifier for the intercepted request
Copy link
Member

Choose a reason for hiding this comment

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

Nit: this will end up with really weird looking javadocs -- the body of the description will begin - Identifier. There's also no need to worry about aligning the start of the descriptions.

We can leave as is and edit after merging unless you're feeling particularly energetic :)

* (EXPERIMENTAL)
*
* @param interceptionId - Identifier for the intercepted request
* @param errorReason (Optional) - If set this causes the request to fail with the given reason.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: The type tells me that this parameter is Optional. There's no need to repeat that here. Same comment as above: we can fix after landing if necessary.

*
* @return Array of Cookies with a "asSeleniumCookies" method
*/
public static Command<Cookies> getAllCookies() {
Copy link
Member

Choose a reason for hiding this comment

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

Set<Cookie> would map more nicely to java.

* @param urls (Optional) - The list of URLs for which applicable cookies will be fetched
* @return Array of cookies
*/
public static Command<Cookies> getCookies(Optional<List<String>> urls) {
Copy link
Member

Choose a reason for hiding this comment

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

And this should also be Set<Cookie>

while (input.hasNext()) {
switch (input.nextName()) {
case "outerResponse":
outerResponse = Response.parseResponse(input);
Copy link
Member

Choose a reason for hiding this comment

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

If Response has a private Response fromJson(JsonInput) method json.read(Response.class) will work.

securityDetails = SecurityDetails.parseSecurityDetails(input);
break;
case "errors":
input.beginArray();
Copy link
Member

Choose a reason for hiding this comment

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

Similarly: json.read(new TypeToken<List<SignedExchangeError>>(){}.getType())

return (null != number) ? number.intValue() : null;
}

public static Map<String,Object> extractMap(JsonInput input){
Copy link
Member

Choose a reason for hiding this comment

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

This can be replaced with input.read(Json.MAP_TYPE)


public class JsonInputConverter {
public static Double extractDouble(JsonInput input){
Number number = input.nextNumber();
Copy link
Member

Choose a reason for hiding this comment

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

This is equivalent to input.read(Double.class)

return (null != number) ? number.doubleValue() : null;
}

public static Integer extractInt(JsonInput input){
Copy link
Member

Choose a reason for hiding this comment

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

This is equivalent to input.read(Integer.class)

@danhumphrey
Copy link

danhumphrey commented Dec 13, 2019

@adiohana I know this is merged, but you mention the ability to manipulate responses, however, I can't see how.

In puppeteer this would be done with page.setRequestInterception(true), then using something like:

page.on("request", request => {
  ...
  request.respond({
    status: 400
    ...
  })
}

I've looked at Network.requestIntercepted() , Network.responseReceived() etc. I've also looked at Fetch.requestPaused, but can't see how to mock the actual response status and/or body.

Could you please point me in the right direction?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants