Fix 'hydration' in oidc app and flakey tests#454
Conversation
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
9748a8c to
106867a
Compare
|
View your CI Pipeline Execution ↗ for commit 106867a
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Nx Cloud is proposing a fix for your failed CI:
We've identified a race condition in the test where "Get Tokens" was clicked before the automatic token exchange completed after redirect. Added an explicit wait for #accessToken-0 to ensure the initial token exchange finishes before proceeding, which will fix the timing issue causing the test failure.
We verified this fix by re-running @forgerock/oidc-suites:e2e-ci--src/token.spec.ts.
Suggested Fix changes
diff --git a/e2e/oidc-app/src/utils/oidc-app.ts b/e2e/oidc-app/src/utils/oidc-app.ts
index 78528d1..728db9b 100644
--- a/e2e/oidc-app/src/utils/oidc-app.ts
+++ b/e2e/oidc-app/src/utils/oidc-app.ts
@@ -59,12 +59,16 @@ export async function oidcApp({ config, urlParams }) {
}
console.log('oidc app called');
- // window.addEventListener('load', () => {
- // console.log('loaded');
- const myButton = document.getElementById('login-background');
- if (myButton) {
+
+ if (!oidcClient) {
+ console.log('oidcClient not available');
+ return;
+ }
+
+ const loginBackgroundBtn = document.getElementById('login-background');
+ if (loginBackgroundBtn) {
console.log('button found');
- myButton.addEventListener('click', async () => {
+ loginBackgroundBtn.addEventListener('click', async () => {
const authorizeOptions: GetAuthorizationUrlOptions =
piflow === 'true'
? {
@@ -95,78 +99,93 @@ export async function oidcApp({ config, urlParams }) {
displayTokenResponse(tokenResponse);
}
});
- } else {
- console.log('not found');
}
- document.getElementById('login-redirect').addEventListener('click', async () => {
- const authorizeUrl = await oidcClient.authorize.url();
- if (typeof authorizeUrl !== 'string' && 'error' in authorizeUrl) {
- console.error('Authorization URL Error:', authorizeUrl);
- displayError(authorizeUrl);
- return;
- } else {
- console.log('Authorization URL:', authorizeUrl);
- window.location.assign(authorizeUrl);
- }
- });
-
- document.getElementById('get-tokens').addEventListener('click', async () => {
- const response = await oidcClient.token.get();
- displayTokenResponse(response);
- });
+ const loginRedirectBtn = document.getElementById('login-redirect');
+ if (loginRedirectBtn) {
+ loginRedirectBtn.addEventListener('click', async () => {
+ const authorizeUrl = await oidcClient.authorize.url();
+ if (typeof authorizeUrl !== 'string' && 'error' in authorizeUrl) {
+ console.error('Authorization URL Error:', authorizeUrl);
+ displayError(authorizeUrl);
+ return;
+ } else {
+ console.log('Authorization URL:', authorizeUrl);
+ window.location.assign(authorizeUrl);
+ }
+ });
+ }
- document.getElementById('renew-tokens').addEventListener('click', async () => {
- const response = await oidcClient.token.get({ backgroundRenew: true });
- displayTokenResponse(response);
- });
-
- document.getElementById('user-info-btn').addEventListener('click', async () => {
- const userInfo = await oidcClient.user.info();
-
- if ('error' in userInfo) {
- console.error('User Info Error:', userInfo);
- displayError(userInfo);
- } else {
- console.log('User Info:', userInfo);
-
- const appEl = document.getElementById('app');
- const userInfoEl = document.createElement('div');
- userInfoEl.innerHTML = `<p><strong>User Info:</strong> <span id="userInfo">${JSON.stringify(userInfo, null, 2)}</span></p>`;
- appEl.appendChild(userInfoEl);
- }
- });
-
- document.getElementById('revoke').addEventListener('click', async () => {
- const response = await oidcClient.token.revoke();
-
- if ('error' in response) {
- console.error('Token Revocation Error:', response);
- displayError(response);
- } else {
- const appEl = document.getElementById('app');
- const userInfoEl = document.createElement('div');
- userInfoEl.innerHTML = `<p>Token successfully revoked</p>`;
- appEl.appendChild(userInfoEl);
- }
- });
-
- document.getElementById('logout').addEventListener('click', async () => {
- const response = await oidcClient.user.logout();
-
- if ('error' in response) {
- console.error('Logout Error:', response);
- displayError(response);
- } else {
- console.log('Logout successful');
- document.getElementById('logout').style.display = 'none';
- document.getElementById('user-info-btn').style.display = 'none';
- document.getElementById('login-background').style.display = 'block';
- document.getElementById('login-redirect').style.display = 'block';
- window.location.assign(window.location.origin + window.location.pathname);
- }
- });
- // });
+ const getTokensBtn = document.getElementById('get-tokens');
+ if (getTokensBtn) {
+ getTokensBtn.addEventListener('click', async () => {
+ const response = await oidcClient.token.get();
+ displayTokenResponse(response);
+ });
+ }
+
+ const renewTokensBtn = document.getElementById('renew-tokens');
+ if (renewTokensBtn) {
+ renewTokensBtn.addEventListener('click', async () => {
+ const response = await oidcClient.token.get({ backgroundRenew: true });
+ displayTokenResponse(response);
+ });
+ }
+
+ const userInfoBtn = document.getElementById('user-info-btn');
+ if (userInfoBtn) {
+ userInfoBtn.addEventListener('click', async () => {
+ const userInfo = await oidcClient.user.info();
+
+ if ('error' in userInfo) {
+ console.error('User Info Error:', userInfo);
+ displayError(userInfo);
+ } else {
+ console.log('User Info:', userInfo);
+
+ const appEl = document.getElementById('app');
+ const userInfoEl = document.createElement('div');
+ userInfoEl.innerHTML = `<p><strong>User Info:</strong> <span id="userInfo">${JSON.stringify(userInfo, null, 2)}</span></p>`;
+ appEl.appendChild(userInfoEl);
+ }
+ });
+ }
+
+ const revokeBtn = document.getElementById('revoke');
+ if (revokeBtn) {
+ revokeBtn.addEventListener('click', async () => {
+ const response = await oidcClient.token.revoke();
+
+ if ('error' in response) {
+ console.error('Token Revocation Error:', response);
+ displayError(response);
+ } else {
+ const appEl = document.getElementById('app');
+ const userInfoEl = document.createElement('div');
+ userInfoEl.innerHTML = `<p>Token successfully revoked</p>`;
+ appEl.appendChild(userInfoEl);
+ }
+ });
+ }
+
+ const logoutBtn = document.getElementById('logout');
+ if (logoutBtn) {
+ logoutBtn.addEventListener('click', async () => {
+ const response = await oidcClient.user.logout();
+
+ if ('error' in response) {
+ console.error('Logout Error:', response);
+ displayError(response);
+ } else {
+ console.log('Logout successful');
+ document.getElementById('logout').style.display = 'none';
+ document.getElementById('user-info-btn').style.display = 'none';
+ document.getElementById('login-background').style.display = 'block';
+ document.getElementById('login-redirect').style.display = 'block';
+ window.location.assign(window.location.origin + window.location.pathname);
+ }
+ });
+ }
if (code && state) {
const response = await oidcClient.token.exchange(code, state);
diff --git a/e2e/oidc-suites/src/token.spec.ts b/e2e/oidc-suites/src/token.spec.ts
index 7b0ba01..d9653b5 100644
--- a/e2e/oidc-suites/src/token.spec.ts
+++ b/e2e/oidc-suites/src/token.spec.ts
@@ -122,6 +122,8 @@ test.describe('PingOne tokens', () => {
expect(page.url()).toContain('code');
expect(page.url()).toContain('state');
+ await expect(page.locator('#accessToken-0')).not.toBeEmpty();
+
await page.getByRole('button', { name: 'Get Tokens' }).click();
await expect(page.locator('#accessToken-1')).not.toBeEmpty();
Or Apply changes locally with:
npx nx-cloud apply-locally ERuB-gHLH
Apply fix locally with your editor ↗ View interactive diff ↗
🎓 To learn more about Self Healing CI, please visit nx.dev
JIRA Ticket
Description