Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-10396-tests-1713821841742.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tests
---

Fix hanging account switching test ([#10396](https://github.com/linode/manager/pull/10396))
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ describe('Parent/Child account switching', () => {
interceptGetInvoices().as('getInvoices');

cy.visitWithLogin('/account/billing');
cy.trackPageVisit().as('pageVisit');
cy.wait(['@getPayments', '@getInvoices', '@getPaymentMethods']);

// Confirm that "Switch Account" button is present, then click it.
Expand Down Expand Up @@ -220,6 +221,7 @@ describe('Parent/Child account switching', () => {
});

cy.wait('@switchAccount');
cy.expectNewPageVisit('@pageVisit');

// Confirm that Cloud Manager updates local storage authentication values.
// Satisfy TypeScript using non-null assertions since we know what the mock data contains.
Expand Down Expand Up @@ -253,6 +255,7 @@ describe('Parent/Child account switching', () => {
mockGetUser(mockParentUser);

cy.visitWithLogin('/');
cy.trackPageVisit().as('pageVisit');

// Confirm that Parent account username and company name are shown in user
// menu button, then click the button.
Expand Down Expand Up @@ -301,6 +304,7 @@ describe('Parent/Child account switching', () => {
});

cy.wait('@switchAccount');
cy.expectNewPageVisit('@pageVisit');

// Confirm that Cloud Manager updates local storage authentication values.
// Satisfy TypeScript using non-null assertions since we know what the mock data contains.
Expand Down Expand Up @@ -334,7 +338,7 @@ describe('Parent/Child account switching', () => {
* - Confirms that Parent account information is displayed in user menu button after switch.
* - Confirms that Cloud updates local storage auth values upon account switch.
*/
it.skip('can switch from Proxy user back to Parent account user from Billing page', () => {
it('can switch from Proxy user back to Parent account user from Billing page', () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Only this test has given us issues, but because I don't have a great grasp on the root cause of the hanging I decided to apply the fix to all of the tests in this file that involve an account switching-related page reload.

const mockParentToken = randomString(32);
const mockParentExpiration = DateTime.now().plus({ minutes: 15 }).toISO();

Expand All @@ -357,6 +361,10 @@ describe('Parent/Child account switching', () => {
},
});

// Track the initial page visit so that we can later assert that Cloud has
// reloaded upon switching accounts.
cy.trackPageVisit().as('pageVisit');

// Wait for page to finish loading before proceeding with account switch.
cy.wait(['@getPayments', '@getPaymentMethods', '@getInvoices']);

Expand Down Expand Up @@ -398,15 +406,15 @@ describe('Parent/Child account switching', () => {
.click();
});

// Allow page to load before asserting user menu, ensuring no app crash, etc.
cy.expectNewPageVisit('@pageVisit');
cy.wait(['@getInvoices', '@getPayments', '@getPaymentMethods']);

assertAuthLocalStorage(mockParentToken, mockParentExpiration, '*');

assertUserMenuButton(
mockParentProfile.username,
mockParentAccount.company
);

assertAuthLocalStorage(mockParentToken, mockParentExpiration, '*');
});
});

Expand Down Expand Up @@ -442,6 +450,8 @@ describe('Parent/Child account switching', () => {
},
});

cy.trackPageVisit().as('pageVisit');

// Wait for page to finish loading before proceeding with account switch.
cy.wait(['@getPayments', '@getPaymentMethods', '@getInvoices']);

Expand Down Expand Up @@ -489,6 +499,7 @@ describe('Parent/Child account switching', () => {

// Allow page to load before asserting user menu, ensuring no app crash, etc.
cy.wait('@switchAccount');
cy.expectNewPageVisit('@pageVisit');
cy.wait(['@getInvoices', '@getPayments', '@getPaymentMethods']);

assertUserMenuButton(
Expand Down
1 change: 1 addition & 0 deletions packages/manager/cypress/support/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'cypress-real-events/support';

import './setup/defer-command';
import './setup/login-command';
import './setup/page-visit-tracking-commands';
chai.use(chaiString);

chai.use(function (chai, utils) {
Expand Down
30 changes: 30 additions & 0 deletions packages/manager/cypress/support/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,36 @@ declare global {
cypressOptions?: Partial<Cypress.VisitOptions>
): Chainable<any>;

/**
* Assigns a random page visit ID to the current page.
*
* Used to determine whether navigation has occurred later.
*
* @example
* // After initial call to `cy.visit()` or `cy.visitWithLogin()`:
* cy.trackPageVisit().as('pageVisit');
* // Later in the tests, to assert that navigation has occurred:
* cy.expectNewPageVisit('@pageVisit');
*
* @returns Cypress chainable that yields the random page visit ID.
*/
trackPageVisit(): Chainable<number>;

/**
* Asserts that a browser page visit (e.g. navigation or reload) has occurred.
*
* @example
* // After initial call to `cy.visit()` or `cy.visitWithLogin()`:
* cy.trackPageVisit().as('pageVisit');
* // Later in the tests, to assert that navigation has occurred:
* cy.expectNewPageVisit('@pageVisit');
*
* @param alias - Alias to the current page load ID.
*
* @returns Cypress chainable.
*/
expectNewPageVisit(alias: string): Chainable<>;

/**
* Internal Cypress command to retrieve test state.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { randomNumber } from 'support/util/random';

/**
* Assigns a random page visit ID to the current page.
*
* Used to determine whether navigation has occurred later.
*
* @returns Cypress chainable that yields the random page visit ID.
*/
Cypress.Commands.add('trackPageVisit', { prevSubject: false }, () => {
const pageLoadId = randomNumber(100000, 999999);

cy.window({ log: false }).then((window) => {
window['cypress-visit-id'] = pageLoadId;
});

cy.log(`Tracking page visit with ID ${pageLoadId}`);

return cy.wrap(pageLoadId, { log: false });
});

/**
* Asserts that a browser page visit (e.g. via navigation or reload) has occurred.
*
* @param alias - Alias to the current page load ID.
*
* @returns Cypress chainable.
*/
Cypress.Commands.add(
'expectNewPageVisit',
{ prevSubject: false },
(alias: string) => {
return cy
.get<any>(alias, { log: false })
.then((pageLoadId) => {
const log = Cypress.log({
autoEnd: false,
end: false,
message: `Expecting window not to have page visit ID ${pageLoadId}`,
name: 'expectNewPageVisit',
});

cy.window({ log: false }).should(
'not.have.prop',
'cypress-visit-id',
pageLoadId
);
log.end();
});
}
);