-
Notifications
You must be signed in to change notification settings - Fork 367
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-7498] - Add Cypress tests for Parent/Child billing page UX enhancements #10070
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
49988b9
Upgrade Vitest from 1.0.x to 1.2.x
92041c2
Enable contact info unit test that was impacted by circular dependencβ¦
478b9b1
Add QA data attribute to Tooltip component
36917e7
Add intercept util for profile grants request
79c6472
Add tooltip UI helper
8809592
Add Cypress tests for Parent/Child restricted and child user billing UX
4ca0481
Rename test file to be more identifiable
7eff61c
Add changesets
a0bb078
Disable action menu items, update aria label
jaalah d965264
Confirm that payment method action menu items are enabled and disableβ¦
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@linode/manager": Tests | ||
--- | ||
|
||
Add Cypress tests for restricted user billing flows ([#10070](https://github.com/linode/manager/pull/10070)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@linode/manager": Tests | ||
--- | ||
|
||
Upgrade to Vitest 1.2.0 ([#10070](https://github.com/linode/manager/pull/10070)) |
339 changes: 339 additions & 0 deletions
339
packages/manager/cypress/e2e/core/billing/restricted-user-billing.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,339 @@ | ||
/** | ||
* @file Integration tests for restricted user billing flows. | ||
*/ | ||
|
||
import { paymentMethodFactory, profileFactory } from '@src/factories'; | ||
import { accountUserFactory } from '@src/factories/accountUsers'; | ||
import { grantsFactory } from '@src/factories/grants'; | ||
import { mockGetPaymentMethods, mockGetUser } from 'support/intercepts/account'; | ||
import { | ||
mockAppendFeatureFlags, | ||
mockGetFeatureFlagClientstream, | ||
} from 'support/intercepts/feature-flags'; | ||
import { | ||
mockGetProfile, | ||
mockGetProfileGrants, | ||
} from 'support/intercepts/profile'; | ||
import { ui } from 'support/ui'; | ||
import { makeFeatureFlagData } from 'support/util/feature-flags'; | ||
import { randomLabel } from 'support/util/random'; | ||
|
||
// Tooltip message that appears on disabled billing action buttons for restricted users. | ||
const restrictedUserTooltip = | ||
'To modify this content, please contact your administrator.'; | ||
|
||
// Tooltip message that appears on disabled billing action buttons for child users. | ||
const childUserTooltip = | ||
'To modify this content, please contact your business partner.'; | ||
|
||
// Mock credit card payment method to use in tests. | ||
const mockPaymentMethods = [ | ||
paymentMethodFactory.build({ | ||
data: { | ||
card_type: 'Visa', | ||
expiry: '12/2026', | ||
last_four: '1234', | ||
}, | ||
is_default: false, | ||
}), | ||
paymentMethodFactory.build({ | ||
data: { | ||
card_type: 'Visa', | ||
expiry: '12/2026', | ||
last_four: '5678', | ||
}, | ||
is_default: true, | ||
}), | ||
]; | ||
|
||
/** | ||
* Asserts that the billing contact "Edit" button is disabled. | ||
* | ||
* Additionally confirms that clicking the "Edit" button reveals a tooltip and | ||
* does not open the "Edit Billing Contact Info" drawer. | ||
* | ||
* @param tooltipText - Expected tooltip message to be shown to the user. | ||
*/ | ||
const assertEditBillingInfoDisabled = (tooltipText: string) => { | ||
// Confirm Billing Contact section "Edit" button is disabled, then click it. | ||
cy.get('[data-qa-contact-summary]') | ||
.should('be.visible') | ||
.within(() => { | ||
ui.button | ||
.findByTitle('Edit') | ||
.should('be.visible') | ||
.should('be.disabled') | ||
.click(); | ||
}); | ||
|
||
// Assert that "Edit Contact Billing Info" drawer does not open and that tooltip is revealed. | ||
cy.get(`[data-qa-drawer-title="Edit Billing Contact Info"]`).should( | ||
'not.exist' | ||
); | ||
ui.tooltip.findByText(tooltipText).should('be.visible'); | ||
}; | ||
|
||
/** | ||
* Asserts that the billing contact "Edit" button is enabled. | ||
* | ||
* Additionally confirms that clicking the "Edit" button opens the "Edit Billing | ||
* Contact Info" drawer, then closes the drawer. | ||
*/ | ||
const assertEditBillingInfoEnabled = () => { | ||
cy.get('[data-qa-contact-summary]') | ||
.should('be.visible') | ||
.within(() => { | ||
ui.button | ||
.findByTitle('Edit') | ||
.should('be.visible') | ||
.should('be.enabled') | ||
.click(); | ||
}); | ||
|
||
ui.drawer | ||
.findByTitle('Edit Billing Contact Info') | ||
.should('be.visible') | ||
.within(() => { | ||
ui.drawerCloseButton.find().click(); | ||
}); | ||
}; | ||
|
||
/** | ||
* Asserts that the "Add Payment Method" button is disabled. | ||
* | ||
* Additionally confirms that clicking the "Add Payment Method" button reveals | ||
* a tooltip and does not open the "Add Payment Method" drawer. | ||
* | ||
* @param tooltipText - Expected tooltip message to be shown to the user. | ||
*/ | ||
const assertAddPaymentMethodDisabled = (tooltipText: string) => { | ||
// Confirm that payment method action menu items are disabled. | ||
ui.actionMenu | ||
.findByTitle('Action menu for card ending in 1234') | ||
.should('be.visible') | ||
.should('be.enabled') | ||
.click(); | ||
|
||
['Make a Payment', 'Make Default', 'Delete'].forEach((menuItem: string) => { | ||
ui.actionMenuItem.findByTitle(menuItem).should('be.disabled'); | ||
}); | ||
|
||
// Dismiss action menu. | ||
cy.get('[data-qa-action-menu="true"]').click(); | ||
|
||
// Confirm Billing Summary section "Add Payment Method" button is disabled, then click it. | ||
cy.get('[data-qa-billing-summary]') | ||
.should('be.visible') | ||
.within(() => { | ||
ui.button | ||
.findByTitle('Add Payment Method') | ||
.should('be.visible') | ||
.should('be.disabled') | ||
.click(); | ||
}); | ||
|
||
// Assert that "Add Payment Method" drawer does not open and that tooltip is revealed. | ||
cy.get(`[data-qa-drawer-title="Add Payment Method"]`).should('not.exist'); | ||
ui.tooltip.findByText(tooltipText).should('be.visible'); | ||
}; | ||
|
||
/** | ||
* Asserts that the "Add Payment Method" button is enabled. | ||
* | ||
* Additionally confirms that clicking the "Add Payment Method" button opens the | ||
* "Add Payment Method" drawer, then closes the drawer. | ||
*/ | ||
const assertAddPaymentMethodEnabled = () => { | ||
// Confirm that payment method action menu items are enabled. | ||
ui.actionMenu | ||
.findByTitle('Action menu for card ending in 1234') | ||
.should('be.visible') | ||
.should('be.enabled') | ||
.click(); | ||
|
||
['Make a Payment', 'Make Default', 'Delete'].forEach((menuItem: string) => { | ||
ui.actionMenuItem.findByTitle(menuItem).should('be.enabled'); | ||
}); | ||
|
||
// Dismiss action menu. | ||
cy.get('[data-qa-action-menu="true"]').click(); | ||
|
||
cy.get('[data-qa-billing-summary]') | ||
.should('be.visible') | ||
.within(() => { | ||
ui.button | ||
.findByTitle('Add Payment Method') | ||
.should('be.visible') | ||
.should('be.enabled') | ||
.click(); | ||
}); | ||
|
||
ui.drawer | ||
.findByTitle('Add Payment Method') | ||
.should('be.visible') | ||
.within(() => { | ||
ui.drawerCloseButton.find().click(); | ||
}); | ||
}; | ||
|
||
describe('restricted user billing flows', () => { | ||
beforeEach(() => { | ||
mockGetPaymentMethods(mockPaymentMethods); | ||
}); | ||
|
||
// TODO Delete all of these tests when Parent/Child launches and flag is removed. | ||
describe('Parent/Child feature disabled', () => { | ||
beforeEach(() => { | ||
// Mock the Parent/Child feature flag to be enabled. | ||
mockAppendFeatureFlags({ | ||
parentChildAccountAccess: makeFeatureFlagData(false), | ||
}); | ||
mockGetFeatureFlagClientstream(); | ||
}); | ||
|
||
/* | ||
* - Smoke test to confirm that regular users can edit billing information. | ||
* - Confirms that billing action buttons are enabled and open their respective drawers on click. | ||
* - Confirms that payment method action menu items are enabled. | ||
*/ | ||
it('can edit billing information', () => { | ||
// The flow prior to Parent/Child does not account for user privileges, instead relying | ||
// on the API to forbid actions when the user does not have the required privileges. | ||
// Because the API is doing the heavy lifting, we only need to ensure that the billing action | ||
// buttons behave as expected for this smoke test. | ||
const mockProfile = profileFactory.build({ | ||
username: randomLabel(), | ||
restricted: false, | ||
}); | ||
|
||
const mockUser = accountUserFactory.build({ | ||
username: mockProfile.username, | ||
user_type: null, | ||
restricted: false, | ||
}); | ||
|
||
// Confirm button behavior for regular users. | ||
mockGetProfile(mockProfile); | ||
mockGetUser(mockUser); | ||
cy.visitWithLogin('/account/billing'); | ||
assertEditBillingInfoEnabled(); | ||
assertAddPaymentMethodEnabled(); | ||
}); | ||
}); | ||
|
||
describe('Parent/Child feature enabled', () => { | ||
beforeEach(() => { | ||
// Mock the Parent/Child feature flag to be enabled. | ||
// TODO Delete this `beforeEach()` block when Parent/Child launches and flag is removed. | ||
mockAppendFeatureFlags({ | ||
parentChildAccountAccess: makeFeatureFlagData(true), | ||
}); | ||
mockGetFeatureFlagClientstream(); | ||
}); | ||
|
||
/* | ||
* - Confirms that users with read-only account access cannot edit billing information. | ||
* - Confirms UX enhancements are applied when parent/child feature flag is enabled. | ||
* - Confirms that "Edit" and "Add Payment Method" buttons are disabled and have informational tooltips. | ||
* - Confirms that clicking "Edit" and "Add Payment Method" does not open their respective drawers when disabled. | ||
* - Confirms that button tooltip text reflects read-only account access. | ||
* - Confirms that payment method action menu items are disabled. | ||
*/ | ||
it('cannot edit billing information with read-only account access', () => { | ||
const mockProfile = profileFactory.build({ | ||
username: randomLabel(), | ||
restricted: true, | ||
}); | ||
|
||
const mockUser = accountUserFactory.build({ | ||
username: mockProfile.username, | ||
restricted: true, | ||
user_type: null, | ||
}); | ||
|
||
const mockGrants = grantsFactory.build({ | ||
global: { | ||
account_access: 'read_only', | ||
}, | ||
}); | ||
|
||
mockGetProfile(mockProfile); | ||
mockGetProfileGrants(mockGrants); | ||
mockGetUser(mockUser); | ||
cy.visitWithLogin('/account/billing'); | ||
|
||
assertEditBillingInfoDisabled(restrictedUserTooltip); | ||
assertAddPaymentMethodDisabled(restrictedUserTooltip); | ||
}); | ||
|
||
/* | ||
* - Confirms that child users cannot edit billing information. | ||
* - Confirms that UX enhancements are applied when parent/child feature flag is enabled. | ||
* - Confirms that "Edit" and "Add Payment Method" buttons are disabled and have informational tooltips. | ||
* - Confirms that clicking "Edit" and "Add Payment Method" does not open their respective drawers when disabled. | ||
* - Confirms that button tooltip text reflects child user access. | ||
* - Confirms that payment method action menu items are disabled. | ||
*/ | ||
it('cannot edit billing information as child account', () => { | ||
const mockProfile = profileFactory.build({ | ||
username: randomLabel(), | ||
}); | ||
|
||
const mockUser = accountUserFactory.build({ | ||
username: mockProfile.username, | ||
user_type: 'child', | ||
}); | ||
|
||
mockGetProfile(mockProfile); | ||
mockGetUser(mockUser); | ||
cy.visitWithLogin('/account/billing'); | ||
|
||
assertEditBillingInfoDisabled(childUserTooltip); | ||
assertAddPaymentMethodDisabled(childUserTooltip); | ||
}); | ||
|
||
/* | ||
* - Smoke test to confirm that regular and parent users can edit billing information. | ||
* - Confirms that billing action buttons are enabled and open their respective drawers on click. | ||
*/ | ||
it('can edit billing information as a regular user and as a parent user', () => { | ||
const mockProfileRegular = profileFactory.build({ | ||
username: randomLabel(), | ||
restricted: false, | ||
}); | ||
|
||
const mockUserRegular = accountUserFactory.build({ | ||
username: mockProfileRegular.username, | ||
user_type: null, | ||
restricted: false, | ||
}); | ||
|
||
const mockProfileParent = profileFactory.build({ | ||
username: randomLabel(), | ||
restricted: false, | ||
}); | ||
|
||
const mockUserParent = accountUserFactory.build({ | ||
username: mockProfileParent.username, | ||
user_type: 'parent', | ||
restricted: false, | ||
}); | ||
|
||
// Confirm button behavior for regular users. | ||
mockGetProfile(mockProfileRegular); | ||
mockGetUser(mockUserRegular); | ||
cy.visitWithLogin('/account/billing'); | ||
cy.findByText(mockProfileRegular.username); | ||
assertEditBillingInfoEnabled(); | ||
assertAddPaymentMethodEnabled(); | ||
|
||
// Confirm button behavior for parent users. | ||
mockGetProfile(mockProfileParent); | ||
mockGetUser(mockUserParent); | ||
cy.visitWithLogin('/account/billing'); | ||
cy.findByText(mockProfileParent.username); | ||
assertEditBillingInfoEnabled(); | ||
assertAddPaymentMethodEnabled(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
@jaalah-akamai quick question occurred to me while writing these tests: should the payment method action menus (or their items) be disabled for restricted and child users?
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.
Yes! Edit: Well let me triple check this.
Edit edit: 100% yes!