Skip to content

Commit

Permalink
test: Improve asm flaky e2es (#15929)
Browse files Browse the repository at this point in the history
Notes:

- removed redundant registration that happens twice at the beginning and other duplicate tasks
- make sure to wait for asm input box to no longer be disabled before typing
- removed unused functions
- removed duplicates and reuse the intended function for customer emulation tests
- instead of visiting a page by using cy.visit, we use the my-account dropdown instead. Visiting pages is not a user journey on how a user would navigate the page. Also, visiting a page is like a refresh as it's changing the url and going to that route through the browser instead of making it a user journey (an end to end test).
- in addition, the visit caused most of the customer agent session timeout because of some existing bug in the feature

---

important:

- reproducible asm agent session timeout as shown in videos by just waiting ~6 mins in a page. Needs fix in feature for token expiration instead, however, the videos in the issue shows that flakiness as well (not related to session timeout), which should be fixed by this PR

closes https://jira.tools.sap/browse/CXSPA-661
  • Loading branch information
bgambocjaviniar authored Jul 1, 2022
1 parent 14ab49c commit d6e3078
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 254 deletions.
156 changes: 118 additions & 38 deletions projects/storefrontapp-e2e-cypress/cypress/helpers/asm.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { login } from './auth-forms';
import * as addressBook from '../helpers/address-book';
import * as asm from '../helpers/asm';
import * as checkout from '../helpers/checkout-flow';
import { fillShippingAddress } from '../helpers/checkout-forms';
import * as consent from '../helpers/consent-management';
import * as profile from '../helpers/update-profile';
import { getSampleUser } from '../sample-data/checkout-flow';
import { SampleUser } from '../sample-data/checkout-flow';
import { interceptGet, interceptPost } from '../support/utils/intercept';
import { login } from './auth-forms';
import * as loginHelper from './login';
import {
interceptDelete,
interceptGet,
interceptPost,
} from '../support/utils/intercept';
import { navigateToCategory, navigateToHomepage } from './navigation';
navigateToAMyAccountPage,
navigateToCategory,
navigateToHomepage,
waitForPage,
} from './navigation';

export function listenForAuthenticationRequest(): string {
return interceptPost(
Expand All @@ -34,19 +35,27 @@ export function listenForUserDetailsRequest(): string {
return interceptGet('userDetails', '/users/*');
}

export function listenForListOfAddressesRequest(): string {
return interceptGet('addresses', '/users/**/addresses?*');
}

export function agentLogin(): void {
const authRequest = listenForAuthenticationRequest();
cy.get('cx-storefront').within(() => {
cy.get('cx-csagent-login-form').should('exist');
cy.get('cx-customer-selection').should('not.exist');
cy.get('cx-csagent-login-form form').within(() => {
cy.get('[formcontrolname="userId"]').type('asagent');
cy.get('[formcontrolname="password"]').type('pw4all');
cy.get('[formcontrolname="userId"]')
.should('not.be.disabled')
.type('asagent');
cy.get('[formcontrolname="password"]')
.should('not.be.disabled')
.type('pw4all');
cy.get('button[type="submit"]').click();
});
});

cy.wait(authRequest);
cy.wait(authRequest).its('response.statusCode').should('eq', 200);
cy.get('cx-csagent-login-form').should('not.exist');
cy.get('cx-customer-selection').should('exist');
}
Expand All @@ -58,33 +67,41 @@ export function startCustomerEmulation(customer): void {
cy.get('cx-csagent-login-form').should('not.exist');
cy.get('cx-customer-selection').should('exist');
cy.get('cx-customer-selection form').within(() => {
cy.get('[formcontrolname="searchTerm"]').type(customer.email);
cy.get('[formcontrolname="searchTerm"]')
.should('not.be.disabled')
.type(customer.email);
cy.get('[formcontrolname="searchTerm"]').should(
'have.value',
`${customer.email}`
);
});
cy.wait(customerSearchRequestAlias);
cy.wait(customerSearchRequestAlias)
.its('response.statusCode')
.should('eq', 200);

cy.get('cx-customer-selection div.asm-results button').click();
cy.get('button[type="submit"]').click();

cy.wait(userDetailsRequestAlias);
cy.wait(userDetailsRequestAlias).its('response.statusCode').should('eq', 200);
cy.get('cx-customer-emulation input')
.invoke('attr', 'placeholder')
.should('contain', customer.fullName);
cy.get('cx-csagent-login-form').should('not.exist');
cy.get('cx-customer-selection').should('not.exist');
cy.get('cx-customer-emulation').should('exist');
cy.get('cx-customer-emulation').should('be.visible');
}

export function loginCustomerInStorefront(customer) {
const authRequest = listenForAuthenticationRequest();

login(customer.email, customer.password);
cy.wait(authRequest);
cy.wait(authRequest).its('response.statusCode').should('eq', 200);
}

export function agentSignOut() {
const tokenRevocationAlias = loginHelper.listenForTokenRevocationRequest();
cy.get('button[title="Sign Out"]').click();
cy.wait(tokenRevocationAlias);
cy.wait(tokenRevocationAlias).its('response.statusCode').should('eq', 200);
cy.get('cx-csagent-login-form').should('exist');
cy.get('cx-customer-selection').should('not.exist');
}
Expand All @@ -93,24 +110,15 @@ export function assertCustomerIsSignedIn() {
cy.get('cx-login div.cx-login-greet').should('exist');
}

export function deleteFirstAddress() {
interceptDelete('deleteAddresses', '/users/*/addresses/*?lang=en&curr=USD');
interceptGet('fetchAddresses', '/users/*/addresses/*?lang=en&curr=USD');

const firstCard = cy.get('cx-card').first();
firstCard.contains('Delete').click();
cy.get('.cx-card-delete button.btn-primary').click();
cy.wait('@deleteAddress');
cy.wait('@fetchAddresses');
}

export function testCustomerEmulation() {
let customer: SampleUser;

it('should test customer emulation', () => {
let customer = getSampleUser();
checkout.registerUser(false, customer);
checkout.visitHomePage();

customer = checkout.registerUser(false);

// storefront should have ASM UI disabled by default
checkout.visitHomePage();
cy.get('cx-asm-main-ui').should('not.exist');

cy.log('--> Agent logging in');
Expand All @@ -124,29 +132,59 @@ export function testCustomerEmulation() {
asm.startCustomerEmulation(customer);

cy.log('--> Update personal details');
cy.visit('/my-account/update-profile');
profile.updateProfile();
navigateToAMyAccountPage(
'Personal Details',
'/my-account/update-profile',
'updateProfilePage'
);

profile.updateProfile(customer);
customer.firstName = profile.newFirstName;
customer.lastName = profile.newLastName;
customer.fullName = `${profile.newFirstName} ${profile.newLastName}`;
customer.titleCode = profile.newTitle;

cy.log('--> Create new address');
cy.visit('/my-account/address-book');
cy.get('cx-card').should('have.length', 0);

navigateToAMyAccountPage(
'Address Book',
'/my-account/address-book',
'addressBookPage'
);

cy.get('cx-address-book').should('be.visible');
cy.get('cx-card').should('not.exist');

const getListOfAddressesRequestAlias = listenForListOfAddressesRequest();
fillShippingAddress(addressBook.newAddress);
cy.get('cx-card').should('have.length', 1);
cy.wait(getListOfAddressesRequestAlias)
.its('response.statusCode')
.should('eq', 200);

addressBook.verifyNewAddress();

cy.log('--> Add a consent');

cy.visit('/my-account/consents');
navigateToAMyAccountPage(
'Consent Management',
'/my-account/consents',
'consentManagementPage'
);

consent.giveConsent();

cy.log('--> Stop customer emulation');
cy.get('cx-customer-emulation button').click();
cy.get('cx-csagent-login-form').should('not.exist');
cy.get('cx-customer-selection').should('exist');
cy.get('cx-customer-selection').should('be.visible');

// Make sure homepage is visible
cy.wait(`@getHomePage`).its('response.statusCode').should('eq', 200);
cy.get('cx-global-message div').should(
'contain',
'You have successfully signed out.'
);
cy.get('cx-page-slot.Section1 cx-banner').first().should('be.visible');

// Without this wait, the test fails b/c the customer search box is disabled
cy.wait(1000);
Expand All @@ -159,7 +197,7 @@ export function testCustomerEmulation() {
);
cy.get('cx-customer-emulation button').click();
cy.get('cx-customer-emulation').should('not.exist');
cy.get('cx-customer-selection').should('exist');
cy.get('cx-customer-selection').should('be.visible');

cy.log('--> sign out and close ASM UI');
asm.agentSignOut();
Expand All @@ -175,4 +213,46 @@ export function testCustomerEmulation() {
navigateToCategory('Brands', 'brands', false);
cy.get('cx-product-list-item').should('exist');
});

it('should verify data changed by the agent as a customer', () => {
cy.log('--> customer sign in');

const loginPage = waitForPage('/login', 'getLoginPage');
cy.visit('/login');
cy.wait(`@${loginPage}`).its('response.statusCode').should('eq', 200);

asm.loginCustomerInStorefront(customer);
asm.assertCustomerIsSignedIn();

cy.log('Check personal details updated by the agent');

navigateToAMyAccountPage(
'Personal Details',
'/my-account/update-profile',
'updateProfilePage'
);
profile.verifyUpdatedProfile();

cy.log('--> check address created by the agent');

navigateToAMyAccountPage(
'Address Book',
'/my-account/address-book',
'addressBookPage'
);

cy.get('cx-card').should('be.visible');
addressBook.verifyNewAddress();

cy.log('--> Check consent given by agent');

navigateToAMyAccountPage(
'Consent Management',
'/my-account/consents',
'consentManagementPage'
);
cy.get('input[type="checkbox"]').first().should('be.checked');

checkout.signOutUser();
});
}
13 changes: 13 additions & 0 deletions projects/storefrontapp-e2e-cypress/cypress/helpers/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,16 @@ export function navigateToCategory(
.click({ force });
cy.wait(`@${categoryPage}`).its('response.statusCode').should('eq', 200);
}

export function navigateToAMyAccountPage(
myAccountOptionText: string,
page: string,
alias: string
) {
const pageAlias = waitForPage(page, alias);

cy.selectUserMenuOption({
option: myAccountOptionText,
});
cy.wait(`@${pageAlias}`).its('response.statusCode').should('eq', 200);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import * as login from '../helpers/login';
import { SampleUser } from '../sample-data/checkout-flow';
import * as alerts from './global-message';
import { checkBanner } from './homepage';
import * as login from '../helpers/login';

export const newTitle = 'Dr.';
export const newFirstName = 'N';
export const newLastName = 'Z';
export const UPDATE_PROFILE_URL = '/my-account/update-profile';

export function updateProfile() {
export function updateProfile(user?: SampleUser) {
if (user) {
cy.get('[formcontrolname="firstName"]').should(
'have.value',
user.firstName
);
cy.get('[formcontrolname="lastName"]').should('have.value', user.lastName);
}

cy.get('cx-update-profile').within(() => {
cy.get('[formcontrolname="titleCode"]').ngSelect(newTitle);
cy.get('[formcontrolname="firstName"]').clear().type(newFirstName);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import * as asm from '../../../helpers/asm';
import { clearAllStorage } from '../../../support/utils/clear-all-storage';
import * as checkout from '../../../helpers/checkout-flow';
import { getSampleUser } from '../../../sample-data/checkout-flow';

let customer: any;
context('Assisted Service Module', () => {
before(() => {
clearAllStorage();
cy.visit('/');
customer = getSampleUser();
checkout.registerUser(false, customer);
});

describe('Customer Support Agent - Emulation', () => {
Expand Down
Loading

0 comments on commit d6e3078

Please sign in to comment.