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

Fix flaky TestCafe OV polling test in DeviceChallengePollView_spec #3654

Open
wants to merge 3 commits into
base: 7.21
Choose a base branch
from

Conversation

denysoblohin-okta
Copy link
Contributor

Description:

The fix consists of 2 parts:

  1. Need to comment skipped tests. For some reason (bug in TestCafe 1.x?) mocks used in test.skip.requestHooks(xxx) interferes with mocks in other tests - other tests in spec can use mocks from skipped test
  2. Promisified $.ajax in BaseOktaVerifyChallengeView - migrated from jQuery's Promise-like done/fail to native then/catch. With old approach, probe and challenge requests are not chained correctly (et. probing port 6512 can be started in parallel with challenging port 6511). With native Promise it's always a chain probe 1 -> challenge 1 -> probe 2 -> challenge 2 -> ...

Notes:

  • Tested the fix 10 times on Bacon and got constant green testcafe task
  • Tried to upgrade TestCafe to 3.x to eliminate need to comment skipped tests, but it requires upgrading Chrome version and causes other issues, so postponed..

PR Checklist

Issue:

Reviewers:

Screenshot/Video:

Downstream Monolith Build:

@@ -14,7 +14,13 @@ const request = (opts) => {
method: 'GET',
contentType: 'application/json',
}, opts);
return $.ajax(ajaxOptions);
return new Promise((resolve, reject) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Explain why/how this helps

Copy link
Contributor

Choose a reason for hiding this comment

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

@shuowu-okta did you have a specific behavior-change related concern w.r.t. Promisifying this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In current code Promises are mixed with jQuery's Deferred (line 159 let probeChain = Promise.resolve(); uses Promise, $.ajax returns Deferred and done/fail APIs are used)

Tests expect that requests are performed in chain: probe port 2000 -> challenge 2000 (if probe OK) -> probe 6511 -> challenge 6511 -> probe 6512 -> challenge 6512 -> probe 6513 -> challenge 6513
With current code it's not always true, eg. probe 6511 can run in parallel with challenge 2000
So eg. this check

await t.expect(loopbackChallengeErrorLogger.contains(record => record.request.url.match(/6512|6513/))).eql(false);

can fail

Copy link
Contributor

Choose a reason for hiding this comment

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

Changing the base xhr approach may cause unexpected issue for legacy browsers. As the goal is to fix flaky bacon test, I propose to find another way that fix against test directly, for example, migrate test from e2e to unit level (testcafe -> jest).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See latest commit that uses $.Deferred instead of Promise and then+catch API instead of done+fail for proper chaining.
The recommended API method to use chaining is then: https://api.jquery.com/deferred.then/

};

let probeChain = Promise.resolve();
let probeChain = $.Deferred().resolve();
Copy link
Contributor

Choose a reason for hiding this comment

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

will this deferred cause any degradation of UX like slower authentication speed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With this change the behaviour will be same as in Gen3 - probe/challenge calls will be running not in parallel, but in chain (probing/challenging for port 2 should wait for probing/challenging of port 1 to complete).
This can be slower.
But such behaviour in expected judging from code and tests.

If it's desired to have parallel requests, then tests should be rewritten to reflect this.
For example, this line should be removed:

await t.expect(loopbackChallengeErrorLogger.contains(record => record.request.url.match(/6512|6513/))).eql(false);

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

After talking with the team, we would like to fix it, to make V2 behave similar like V3, there shouldn't be a performance concern.
We can be more cautious by using a new flag from server, but this might be an overkill

Copy link
Contributor

Choose a reason for hiding this comment

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

We typically isolate higher-risk changes in a patch bump on the tip so it can be easily rolled back. I think this can target 7.22.1

Copy link
Contributor

Choose a reason for hiding this comment

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

the $.Deferred().resolve() is the jquery's promise, not sure about the very low level, but jquery promise has the .done method (similar as .then), while es6 promise doesn't.
since all the probing will use jquery $.ajax method, so I guess using $.Deferred().resolve() and return the rejected promise in onFailure will make it serial, but I will leave it to @denysoblohin-okta to confirm

Copy link
Contributor Author

@denysoblohin-okta denysoblohin-okta Aug 22, 2024

Choose a reason for hiding this comment

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

How does using $.Deferred().resolve() differ from Promise.resolve()

First one returns $.Deferred object instead of Promise. This will change probeChain from a chain of Promises to a chain of Deferred. Deferred is a "thenable" object, but not a real promise.

how does it cause the probe chain to become serial?

In current code native Promises are mixed with jQuery's Deferred:



($.ajax returns $.Deferred)

probeChain uses native Promises with then/catch API. But doProbing() returns $.Deferred and uses done/fail API.
This is a problem. To achieve proper chaining we need to change done/fail API to then/catch.

Actually we can leave Promise.resolve() instead of $.Deferred().resolve(), then we still have mixing of Promise and Deferred, but they can play well together with then/catch API.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rebased PR onto 7.21

Copy link
Contributor

Choose a reason for hiding this comment

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

just curious, this will target 7.21.2 in the 2024.09.0?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually we can leave Promise.resolve() instead of $.Deferred().resolve()

Yeah, I think now that the Promise API is standardized and canonically polyfilled we should try to use Promise when we can since it's better understood and well-documented (MDN).

Luxu2-Okta
Luxu2-Okta previously approved these changes Aug 9, 2024
Copy link
Contributor

@Luxu2-Okta Luxu2-Okta left a comment

Choose a reason for hiding this comment

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

LGTM, if we want to be very cautious, we can put this fix behind a FF or KS, but this maybe an overkill

@denysoblohin-okta denysoblohin-okta changed the base branch from master to 7.21 August 22, 2024 12:30
Copy link
Contributor

@Luxu2-Okta Luxu2-Okta left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Contributor

@lesterchoi-okta lesterchoi-okta left a comment

Choose a reason for hiding this comment

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

Hold for 7.22.1 release

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.

None yet

6 participants