-
Notifications
You must be signed in to change notification settings - Fork 357
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
test: [M3-7508] - Add tests to check Parent and Child Close Account flows #10296
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -18,6 +18,11 @@ import { | |||||
} from 'support/util/random'; | ||||||
import type { CancelAccount } from '@linode/api-v4'; | ||||||
import { mockWebpageUrl } from 'support/intercepts/general'; | ||||||
import { | ||||||
mockAppendFeatureFlags, | ||||||
mockGetFeatureFlagClientstream, | ||||||
} from 'support/intercepts/feature-flags'; | ||||||
import { makeFeatureFlagData } from 'support/util/feature-flags'; | ||||||
|
||||||
// Data loss warning which is displayed in the account cancellation dialog. | ||||||
const cancellationDataLossWarning = | ||||||
|
@@ -30,6 +35,18 @@ const cancellationPaymentErrorMessage = | |||||
'We were unable to charge your credit card for services rendered. \ | ||||||
We cannot cancel this account until the balance has been paid.'; | ||||||
|
||||||
// Tooltip message that appears when a child account tries to close the account. | ||||||
const contactParentUserTooltipsMessage = | ||||||
'Contact your parent user to close your account.'; | ||||||
|
||||||
// Tooltip message that appears when a child account tries to close the account. | ||||||
const contactCustomerSupportTooltipsMessage = | ||||||
'Contact customer support to close this account.'; | ||||||
|
||||||
// Tooltip message that appears when a parent account with one and more child accounts tries to close the account. | ||||||
const removeChildAccountTooltipsMessage = | ||||||
'Remove child accounts before closing the account.'; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: We started created constants for things like this which would be nice to use especially when verbiage changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for the other two if @jdamore-linode approves, but I understand if in a testing scenario we want to keep things silo'd There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree @jaalah-akamai, I think using the constants from (The only situations where I might insist that the strings be defined in the tests rather than imported from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup I agree with that |
||||||
|
||||||
describe('Account cancellation', () => { | ||||||
/* | ||||||
* - Confirms that a user can cancel their account from the Account Settings page. | ||||||
|
@@ -198,3 +215,223 @@ describe('Account cancellation', () => { | |||||
}); | ||||||
}); | ||||||
}); | ||||||
|
||||||
describe('Parent/Child account cancellation', () => { | ||||||
/* | ||||||
* - Confirms that a child user cannot close the account. | ||||||
*/ | ||||||
it('disables the "Close Account" button for a child user', () => { | ||||||
const mockAccount = accountFactory.build({}); | ||||||
const mockProfile = profileFactory.build({ | ||||||
username: 'mock-child-user', | ||||||
restricted: false, | ||||||
user_type: 'child', | ||||||
}); | ||||||
|
||||||
mockGetAccount(mockAccount).as('getAccount'); | ||||||
mockGetProfile(mockProfile).as('getProfile'); | ||||||
|
||||||
// Navigate to Account Settings page, click "Close Account" button. | ||||||
cy.visitWithLogin('/account/settings'); | ||||||
cy.wait(['@getAccount', '@getProfile']); | ||||||
|
||||||
ui.accordion | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.within(() => { | ||||||
ui.button | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.should('be.disabled') | ||||||
.trigger('mouseover'); | ||||||
// Click the button first, then confirm the tooltip is shown. | ||||||
ui.tooltip | ||||||
.findByText(contactParentUserTooltipsMessage) | ||||||
.should('be.visible'); | ||||||
}); | ||||||
}); | ||||||
|
||||||
/** | ||||||
* Confirms that a proxy account cannot close the account | ||||||
*/ | ||||||
it('disables a proxy account to close the account', () => { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
const mockAccount = accountFactory.build(); | ||||||
const mockProfile = profileFactory.build({ | ||||||
username: 'proxy-user', | ||||||
restricted: false, | ||||||
user_type: 'proxy', | ||||||
}); | ||||||
|
||||||
mockGetAccount(mockAccount).as('getAccount'); | ||||||
mockGetProfile(mockProfile).as('getProfile'); | ||||||
|
||||||
// Navigate to Account Settings page, click "Close Account" button. | ||||||
cy.visitWithLogin('/account/settings'); | ||||||
cy.wait(['@getAccount', '@getProfile']); | ||||||
|
||||||
ui.accordion | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.within(() => { | ||||||
ui.button | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.should('be.disabled') | ||||||
.trigger('mouseover'); | ||||||
// Click the button first, then confirm the tooltip is shown. | ||||||
ui.tooltip | ||||||
.findByText(contactCustomerSupportTooltipsMessage) | ||||||
.should('be.visible'); | ||||||
}); | ||||||
}); | ||||||
|
||||||
/** | ||||||
* Confirms that a parent account with one or more active child accounts cannot close the account | ||||||
*/ | ||||||
it('disables a parent account with one or more active child accounts to close the account', () => { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
const mockAccount = accountFactory.build(); | ||||||
const mockProfile = profileFactory.build({ | ||||||
username: 'parent-user', | ||||||
restricted: false, | ||||||
user_type: 'parent', | ||||||
}); | ||||||
|
||||||
mockGetAccount(mockAccount).as('getAccount'); | ||||||
mockGetProfile(mockProfile).as('getProfile'); | ||||||
|
||||||
// Navigate to Account Settings page, click "Close Account" button. | ||||||
cy.visitWithLogin('/account/settings'); | ||||||
cy.wait(['@getAccount', '@getProfile']); | ||||||
|
||||||
ui.accordion | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.within(() => { | ||||||
ui.button | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.should('be.disabled') | ||||||
.trigger('mouseover'); | ||||||
// Click the button first, then confirm the tooltip is shown. | ||||||
ui.tooltip | ||||||
.findByText(removeChildAccountTooltipsMessage) | ||||||
.should('be.visible'); | ||||||
}); | ||||||
}); | ||||||
|
||||||
/** | ||||||
* Confirms that a parent account with no active child accounts can close the account | ||||||
*/ | ||||||
it('allows a default account with no active child accounts to close the account', () => { | ||||||
const mockAccount = accountFactory.build(); | ||||||
const mockProfile = profileFactory.build({ | ||||||
username: 'default-user', | ||||||
restricted: true, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test shouldn't pass in real life because a restricted user should not be able to close an account, as we test in an earlier test case. Depending on what access they have for the So, we should mock an unrestricted default account here:
Suggested change
If a restricted default user with read_only/read_write |
||||||
user_type: 'default', | ||||||
}); | ||||||
const mockCancellationResponse: CancelAccount = { | ||||||
survey_link: `https://${randomDomainName()}/${randomString(5)}`, | ||||||
}; | ||||||
|
||||||
const cancellationComments = randomPhrase(); | ||||||
|
||||||
// TODO: Parent/Child - M3-7559 clean up when feature is live in prod and feature flag is removed. | ||||||
mockAppendFeatureFlags({ | ||||||
parentChildAccountAccess: makeFeatureFlagData(true), | ||||||
}).as('getFeatureFlags'); | ||||||
mockGetFeatureFlagClientstream().as('getClientStream'); | ||||||
|
||||||
mockGetAccount(mockAccount).as('getAccount'); | ||||||
mockGetProfile(mockProfile).as('getProfile'); | ||||||
mockCancelAccountError(cancellationPaymentErrorMessage, 409).as( | ||||||
'cancelAccount' | ||||||
); | ||||||
mockWebpageUrl( | ||||||
mockCancellationResponse.survey_link, | ||||||
'This is a mock webpage to confirm Cloud Manager survey link behavior' | ||||||
).as('getSurveyPage'); | ||||||
|
||||||
// Navigate to Account Settings page, click "Close Account" button. | ||||||
cy.visitWithLogin('/account/settings'); | ||||||
cy.wait(['@getAccount', '@getProfile']); | ||||||
|
||||||
ui.accordion | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.within(() => { | ||||||
ui.button | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.should('be.enabled') | ||||||
.click(); | ||||||
}); | ||||||
|
||||||
ui.dialog | ||||||
.findByTitle('Are you sure you want to close your Linode account?') | ||||||
.should('be.visible') | ||||||
.within(() => { | ||||||
cy.findByText(cancellationDataLossWarning, { exact: false }).should( | ||||||
'be.visible' | ||||||
); | ||||||
|
||||||
// Confirm that submit button is disabled before entering required info. | ||||||
ui.button | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.should('be.disabled'); | ||||||
|
||||||
// Enter username, confirm that submit button becomes enabled, and click | ||||||
// the submit button. | ||||||
cy.findByLabelText( | ||||||
`Please enter your Username (${mockProfile.username}) to confirm.` | ||||||
) | ||||||
.should('be.visible') | ||||||
.should('be.enabled') | ||||||
.type(mockProfile.username); | ||||||
|
||||||
ui.button | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.should('be.enabled') | ||||||
.click(); | ||||||
|
||||||
// Confirm that request payload contains expected data and API error | ||||||
// message is displayed in the dialog. | ||||||
cy.wait('@cancelAccount').then((intercept) => { | ||||||
expect(intercept.request.body['comments']).to.equal(''); | ||||||
}); | ||||||
|
||||||
cy.findByText(cancellationPaymentErrorMessage).should('be.visible'); | ||||||
|
||||||
// Enter account cancellation comments, click "Close Account" again, | ||||||
// and this time mock a successful account cancellation response. | ||||||
mockCancelAccount(mockCancellationResponse).as('cancelAccount'); | ||||||
cy.contains('Comments (optional)').click().type(cancellationComments); | ||||||
|
||||||
ui.button | ||||||
.findByTitle('Close Account') | ||||||
.should('be.visible') | ||||||
.should('be.enabled') | ||||||
.click(); | ||||||
|
||||||
cy.wait('@cancelAccount').then((intercept) => { | ||||||
expect(intercept.request.body['comments']).to.equal( | ||||||
cancellationComments | ||||||
); | ||||||
}); | ||||||
}); | ||||||
|
||||||
// Confirm that Cloud presents account cancellation screen and prompts the | ||||||
// user to complete the exit survey. Confirm that clicking survey button | ||||||
// directs the user to the expected URL. | ||||||
cy.findByText('It’s been our pleasure to serve you.').should('be.visible'); | ||||||
ui.button | ||||||
.findByTitle('Take our exit survey') | ||||||
.should('be.visible') | ||||||
.should('be.enabled') | ||||||
.click(); | ||||||
|
||||||
cy.wait('@getSurveyPage'); | ||||||
cy.url().should('equal', mockCancellationResponse.survey_link); | ||||||
}); | ||||||
}); |
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.
Let's clarify this by saying proxy.