-
Notifications
You must be signed in to change notification settings - Fork 3
Fix 'hydration' in oidc app and flakey tests #454
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
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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