Skip to content
This repository has been archived by the owner on Oct 25, 2023. It is now read-only.

Handle /timeouts W3C + MJSONWP proxying #231

Merged
merged 2 commits into from Jul 11, 2018
Merged

Conversation

dpgraham
Copy link
Contributor

@dpgraham dpgraham commented Jul 6, 2018

  • The /timeouts endpoint is a special case because the syntax differs between W3C and MJSONWP

  • W3C takes a body like this:

    {pageLoad: 1, script: 2, implicit: 3}
  • MJSONWP takes a body like this

    {type: 'script', ms: 2}
  • Since W3C can send > 1 timeout type, we need to have special logic so that if a W3C /timeouts request is being proxied to a MJSONWP /timeouts endpoint, we need to proxy 1 request for each timeout

  • The way this PR handles that is by creating an array of timeout request objects like this:

    If the incoming request is W3C, like this:

{pageLoad: 1, script: 2, implicit: 3}

It will generate an array that looks like this:

[
  {pageLoad: 1, script: 2, implicit: 3, type: 'pageLoad', ms: 1},
  {pageLoad: 1, script: 2, implicit: 3, type: 'script', ms: 2},
  {pageLoad: 1, script: 2, implicit: 3, type: 'implicit', ms: 3},
]

If the incoming request is MJSONWP, like this:

{type: 'pageLoad', ms: 100}

It will generate an array that looks like this:

[{pageLoad: 100, script: undefined, implicit: undefined, type: 'pageLoad', ms: 100}]
  • All of the items in the request objects array are compatible with W3C and MJSONWP
  • What base driver does is executes them one-by-one
    • If it encounters a W3C proxied response, it will return that response immediately
    • If it encounters an MJSONWP proxied response, and it's successful, it will continue to the next
      object and proxy that one too
    • If it encounters an MJSONWP proxied response, and it fails, it will respond with that failure and
      not continue to the next

(related to: appium/appium#11016)

* at a time. So if we're using W3C and proxying to MJSONWP and there's more than one timeout type
* provided in the request, we need to do 3 proxies and combine the result
*
* @param {Array} timeoutObjects List of MJSONWP + W3C compatible timeouts request objects
Copy link
Contributor

Choose a reason for hiding this comment

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

param is body

Copy link
Contributor

Choose a reason for hiding this comment

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

also no return description

};
if (protocol === W3C) {
for (let [type, ms] of _.toPairs(baseObj)) {
if (_.isNumber(ms)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we also check if type is defined?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

type will always be defined because it's the key of an object


/**
* Proxy an array of timeout objects and merge the result
* @param {Array} timeoutObjects List of W3C+MJSONWP compatible /timeouts requests
Copy link
Contributor

Choose a reason for hiding this comment

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

same documentation issue here

let protocol = this.getProtocolFromResBody(resBody);

// If we got a non-MJSONWP response, return the result, nothing left to do
if (protocol !== MJSONWP) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is redundant, since there will be anyway only one item in the array in case of w3c

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If there's an array of timeout objects like this:

[
  {pageLoad: 1, script: 2, implicit: 3, type: 'pageLoad', ms: 1},
  {pageLoad: 1, script: 2, implicit: 3, type: 'script', ms: 2},
  {pageLoad: 1, script: 2, implicit: 3, type: 'implicit', ms: 3},
]

...then we need to stop after the first call if it's W3C because it's done.

return MJSONWP;
} else if (util.hasValue(resBody.value)) {
return W3C;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

what if both conditions fail?

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'd like to return it as undefined so that it's just an unknown protocol.

async command (url, method, body = null) {
let response;
let resBody;
try {
[response, resBody] = await this.proxy(url, method, body);
if (url === '/timeouts' && method.toLowerCase() === 'post') {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't really like the fact that the url is hardcoded here. We might make it more flexible

});
}
}
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

return [{
             ...baseObj,
             type,
             ms,
           }];

Copy link
Contributor

Choose a reason for hiding this comment

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

else will be redundant in such case

@dpgraham
Copy link
Contributor Author

dpgraham commented Jul 9, 2018

Fixes pushed

@dpgraham dpgraham merged commit c6c5609 into master Jul 11, 2018
@dpgraham dpgraham deleted the dpgraham-w3c-proxy-timeouts branch July 11, 2018 16:05
Copy link
Member

@jlipps jlipps left a comment

Choose a reason for hiding this comment

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

👍 fascinating problem!

async command (url, method, body = null) {
let response;
let resBody;
try {
[response, resBody] = await this.proxy(url, method, body);
if (url.endsWith('timeouts') && method.toLowerCase() === 'post') {
Copy link
Member

Choose a reason for hiding this comment

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

maybe endsWith('/timeouts')? what if a user is trying to get the 'timeouts' attribute of an element? (i know that's a 'get', just saying...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jlipps Yeah I could change it to that.

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

Successfully merging this pull request may close these issues.

None yet

3 participants