UNPKG

qe-fe-automation

Version:
646 lines (603 loc) 21 kB
import { AUTH_TOKEN, loginRequest } from '../commands'; import { stagingUsers } from '@fixtures/staging-users'; import { AccountRegistrationClient, SuperAdminClient } from './lib'; import { Accept, HttpRequest, HttpStatusCodes } from '../base'; import { CompanyLoginOptions, CustomField, CustomFieldsUtility, CustomFiledOption, Logs, Random, Timeouts } from '@utility-lib/index'; import { LoyaltyInfo, CreditCard } from '@flight-modal/index'; import { faker } from '@faker-js/faker'; import { SplitUtility } from '@split-lib/index'; import { Provider_Type, User_Type } from '@support-onboard/index'; import { postChargeableEntity } from './../commerce/commerceCommands'; import { AgencyCurrency, AgencyData, CompanyParams, DEFAULT_LOCALE_EN_US } from '@fixtures/onboard'; const { superAdmin } = stagingUsers; const superAdminCredentials = Cypress.env('superAdmin').SUPER_ADMIN_PASSWORD; const onBoardUserCredentials = Cypress.env('newUser').NEW_USER_PASSWORD; Cypress.Commands.add('initiateCompanyCreationFlow', (companyLoginOptions: CompanyLoginOptions) => { const { providers, users, locale, creditCardInfo, loyaltyInfo, feeModelInfo, companyCustomFields, vip, companySuffix, phoneNumber } = companyLoginOptions; cy.allure().logStep('Initiate company creation flow'); const email = superAdmin.email; cy.loginWithAuthToken({ email, password: superAdminCredentials, isSA: true }) .then(() => createCompany(loyaltyInfo, companySuffix)) .then((companyResponse) => checkAndCreateFeeModelForCompany(companyResponse, feeModelInfo)) .then((companyResponse) => updateCompanyParams(companyResponse, companyLoginOptions)) .then((companyResponse) => addUserAgency(companyResponse, feeModelInfo, vip)) .then((agencyResponse) => isUserRegistered(agencyResponse, users, providers)) .then((email) => sendPreSignupEmail(email)) .then((email) => getSignUpToken(email)) .then(({ email, body }) => createAccount(email, body, onBoardUserCredentials)) .then((email) => retrieveUserByEmail(email)) .then(({ userResponse }) => setUserAsVIP(userResponse, vip)) .then(({ userResponse }) => setUserByType(userResponse, users)) .then((email) => loginRequest({ email, password: onBoardUserCredentials })) .then(() => setTravelFrequency()) .then(() => updateUserInfo()) .then(() => updatePassengerInfoDefault(phoneNumber)) .then((companyResponse) => addPersonalPaymentMethod(companyResponse, creditCardInfo)) .then(() => getAndCheckSplitsForProviders(providers)) .then(() => (locale !== DEFAULT_LOCALE_EN_US ? setLocale(locale) : 'Locale is already set to english')) .then(() => { companyCustomFields.forEach((values, companyCustomField) => setCompanyCustomField(companyCustomField, values)); }); }); Cypress.Commands.add('addNewTraveler', (companyDomain: string) => { const email = Random.randomString(5) + '@' + `${companyDomain}`; cy.loginWithAuthToken({ email: superAdmin.email, password: superAdminCredentials, isSA: true }) .then(() => sendPreSignupEmail(email)) .then((email) => getSignUpToken(email)) .then(({ email, body }) => createAccount(email, body, onBoardUserCredentials)) .then((email) => loginRequest({ email, password: onBoardUserCredentials })) .then(() => setTravelFrequency()) .then(() => updateUserInfo()) .then(() => updatePassengerInfoDefault()) .then(() => addPersonalPaymentMethod()) .then(() => cy.task('putDataInCache', { key: 'travelerEmail', data: email })); }); Cypress.Commands.add('retrieveSignUpToken', (email: string) => { cy.loginWithAuthToken({ email: superAdmin.email, password: superAdminCredentials, isSA: true, localStorage: false }).then(() => getSignUpToken(email)); }); Cypress.Commands.add('retrieveUserByEmail', (email: string) => { cy.loginWithAuthToken({ email: superAdmin.email, password: superAdminCredentials, isSA: true, localStorage: false }).then(() => retrieveUserByEmail(email)); }); function createCompany(loyaltyInfo?: LoyaltyInfo, companySuffix?: string): Cypress.Chainable<any> { cy.allure().logStep('Start creating brand new company'); const randomId = Random.randomString(12); const companyDomain = randomId + '-navan' + companySuffix + '.staging.tripactions.xyz'; const companyName = 'TA_CYPRESS_' + randomId; const options = { method: HttpRequest.Post, url: SuperAdminClient.companiesUrl, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: { name: companyName, domain: companyDomain, loyaltyInfo, status: 'ACTIVE' }, retryOnStatusCodeFailure: true }; return cy .request(options) .then((xhr) => Logs.logResponseStatusAndBody(xhr)) .then(({ body, status }) => { expect(status, 'Successfully created company').to.equal(HttpStatusCodes.Created); return body; }); } function updateCompanyParams(companyResponse: any, companyLoginOptions: CompanyLoginOptions) { const newCompanyParams: CompanyParams = { tripProposalEnabled: companyLoginOptions.tripProposal, chargeBookingFee: true, chargeTripFee: true }; const requestBody = { ...companyResponse, ...newCompanyParams }; cy.log('Update the company with the following parameters: ' + JSON.stringify(newCompanyParams)); return cy .request({ method: 'PUT', url: SuperAdminClient.companiesUrl + `/${companyResponse.uuid}`, headers: { Authorization: AUTH_TOKEN }, body: requestBody, retryOnStatusCodeFailure: true }) .then(({ body, status }) => { expect(status, 'Company params updated').to.equal(HttpStatusCodes.Ok); return body; }); } function updateUserInfo() { const userInfo = { phone_number: '+14157483333', onboardingCompleted: true }; cy.log('Update user info with the following parameters: ' + JSON.stringify(userInfo)); return cy .request({ method: HttpRequest.Patch, url: AccountRegistrationClient.userInfo, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: userInfo, retryOnStatusCodeFailure: true }) .then(({ status }) => { expect(status, 'Updated user info').to.equal(HttpStatusCodes.Ok); }); } function checkAndCreateFeeModelForCompany(companyResponse: any, feeModelName: string): Cypress.Chainable<any> { if (feeModelName?.includes('Fee')) { cy.log(companyResponse.uuid); cy.log(feeModelName); postChargeableEntity(companyResponse.uuid, feeModelName); } return cy.wrap(companyResponse); } function addUserAgency(companyResponse: any, feeModelInfo: string, vip: boolean): Cypress.Chainable<any> { const companyUuid = companyResponse.uuid; const agencyData = getAgencyData(companyResponse, feeModelInfo, vip); cy.log(feeModelInfo); cy.task('putDataInCache', { key: 'agencyUuid', data: agencyData.agency.uuid }); if (!feeModelInfo.includes('Fee')) { cy.log('feeModelInfo does not include FEE'); cy.task('putDataInCache', { key: 'tripFee', data: '5.00' }); } cy.allure().logStep(`Add user agency for ${companyUuid} company`); return cy .request({ method: HttpRequest.Put, url: SuperAdminClient.travelOpsCompaniesAgencyUrl .replace('{companyUuid}', companyUuid) .replace('{agencyUuid}', agencyData.agency.uuid), headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: agencyData, retryOnStatusCodeFailure: true }) .then(({ body, status }) => { expect(status, 'Successfully updated company with agency ').to.equal(HttpStatusCodes.Ok); return body; }); } function getAgencyData(companyResponse: any, feeModelInfo: string, vip: boolean) { const companyUuid = companyResponse?.uuid; const companyId = companyResponse?.domain?.split('.')[0]; if (vip) { return AgencyData.generateUSDAgencyVIPData(companyUuid, companyId); } if (feeModelInfo.includes(AgencyCurrency.Euro)) { return AgencyData.generateEURAgencyData(companyUuid, companyId); } return AgencyData.generateUSDAgencyData(companyUuid, companyId); } function isUserRegistered( userAgencyResponse: any, users: User_Type[], providers: Provider_Type[] ): Cypress.Chainable<any> { const domain = userAgencyResponse.companyId; const usersString = getEnumsAsString(users); const providersString = getEnumsAsString(providers); const email = providersString + '_' + usersString + '_' + Random.randomString(3) + '@' + `${domain}` + `.staging.tripactions.xyz`; cy.task('putDataInCache', { key: 'companyCreationEmail', data: email }); cy.allure().logStep(`Is user is already registered : ${email}`); return cy .request({ method: HttpRequest.Get, url: AccountRegistrationClient.emailInfo, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, qs: { email }, retryOnStatusCodeFailure: true }) .then(({ status }) => { expect(status, 'User is not registered').to.equal(HttpStatusCodes.Ok); return email; }); } function getEnumsAsString<T extends string | number>(enumArray: T[]) { let enumsString = ''; enumArray.forEach((enumItem: T) => { if (enumsString) { enumsString += '_'; } enumsString += enumItem.toString(); }); return enumsString; } function sendPreSignupEmail(email: string): Cypress.Chainable<any> { cy.allure().logStep(`Send pre sign up email for ${email}`); return cy .request({ method: HttpRequest.Post, url: AccountRegistrationClient.preSignUpEmail, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, qs: { email }, retryOnStatusCodeFailure: true }) .then(({ status }) => { expect(status, 'Sign up email triggered').to.equal(HttpStatusCodes.Accepted); return email; }); } function getSignUpToken(email: string): Cypress.Chainable<any> { cy.allure().logStep(`Retrieve sign up token for ${email}`); return cy .request({ method: HttpRequest.Get, url: SuperAdminClient.retrieveSignupToken, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, qs: { email }, retryOnStatusCodeFailure: true }) .then(({ body, status }) => { expect(status, 'Signup token retrieved').to.equal(HttpStatusCodes.Ok); return { email, body }; }); } function createAccount(email: string, token: string, password: string): Cypress.Chainable<any> { cy.allure().logStep(`Creating account for ${email}`); cy.task('putDataInCache', { key: 'userEmail', data: email }); return cy.task('getDataFromCache', 'agencyUuid').then((agencyData) => { return cy .request({ method: HttpRequest.Post, url: AccountRegistrationClient.signUp, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: { emailVerificationToken: token, email: email, familyName: faker.name.lastName().replace(/'/g, ''), givenName: faker.name.firstName(), password: password, agencyCompanyAssociationUuid: agencyData }, retryOnStatusCodeFailure: true }) .then(({ status }) => { expect(status, 'Account created').to.equal(HttpStatusCodes.Created); return email; }); }); } function setTravelFrequency(travelFrequency = '1-2 times a month'): Cypress.Chainable<any> { cy.allure().logStep('Setting travel frequency'); return cy .request({ method: HttpRequest.Patch, url: AccountRegistrationClient.userProfile, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: { travelFrequency: travelFrequency }, retryOnStatusCodeFailure: true }) .then(({ status }) => { expect(status, 'Updated travel frequency').to.equal(HttpStatusCodes.Ok); }); } function getAndCheckSplitsForProviders(providers: Provider_Type[]): Cypress.Chainable<any> { cy.allure().logStep('Update splits'); if (AUTH_TOKEN) { return cy .request({ method: HttpRequest.Get, url: AccountRegistrationClient.getSplits, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, retryOnStatusCodeFailure: true }) .then(({ body, status }) => { expect(status, 'Updated splits').to.equal(HttpStatusCodes.Ok); cy.task('putDataInCache', { key: 'splitList', data: body }); SplitUtility.checkOnlyRelevantSplitIsOn(providers); }); } else { throw new Error('Please login before calling api endpoints'); } } function updatePassengerInfoDefault(phoneNumber = '+12029064406'): Cypress.Chainable<any> { cy.allure().logStep('Update passenger information'); const firstName = faker.name.firstName(); const lastName = faker.name.lastName().replace(/'/g, ''); const travelerName = firstName + ' ' + lastName; cy.task('putDataInCache', { key: 'travelerName', data: travelerName }); return cy .request({ method: HttpRequest.Put, url: AccountRegistrationClient.passengerInfo, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: { givenName: firstName, familyName: lastName, passport: { countryOfCitizenship: 'US', number: '31195855', countryOfIssue: 'US', issuedOn: '2020-12-12', expiresOn: '2030-12-12' }, birthdate: '1990-07-17', gender: 'X', secondaryGender: 'MALE', contact: { phone: { number: phoneNumber } } }, retryOnStatusCodeFailure: true }) .then(({ status }) => { expect(status, 'Update passenger default information').to.equal(HttpStatusCodes.Ok); }); } function addPersonalPaymentMethod( companyResponse?: any, creditCardInfo?: CreditCard, current_attempt = 1 ): Cypress.Chainable<any> { cy.allure().logStep('Add personal payment method'); const creditCard = creditCardInfo ? creditCardInfo : { fullName: 'JMeter', givenName: faker.name.firstName(), familyName: faker.name.lastName().replace(/'/g, ''), number: '4242424242424242', expirationMonth: '1', expirationYear: '2026', cvc: '123' }; return cy .request({ method: HttpRequest.Post, url: AccountRegistrationClient.paymentMethod, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: { billingAddress: { addressLine1: 'Strawinskylaan', addressLine2: '1337', state: 'AL', city: 'Amsterdam', country: 'NL', postalCode: '1337AM' }, creditCard, nickname: 'Corporate Visa Card' }, failOnStatusCode: false }) .then(({ status, body }) => { if ((status === 500 || status === 504) && current_attempt < 5) { cy.allure().logStep('Retrying adding personal payment method, attempt: ' + current_attempt); cy.wait(Timeouts.MEDIUM_TIMEOUT_20_SEC.timeout); cy.allure().logStep('Applied wait time: ' + Timeouts.MEDIUM_TIMEOUT_20_SEC.timeout); addPersonalPaymentMethod(companyResponse, creditCardInfo, ++current_attempt); } expect(status, 'Payment method updated').to.equal(HttpStatusCodes.Created); cy.task('putDataInCache', { key: 'paymentMethod', data: body }); const paymentMethodUuId = body.uuid; cy.task('putDataInCache', { key: 'paymentMethodUuId', data: paymentMethodUuId }); }); } function setUserByType(userResponse: any, users: User_Type[]): Cypress.Chainable<any> | PromiseLike<string> { users.forEach((user) => { if (user === 'admin' || user === 'programManager') { cy.allure().logStep('Set user as ' + users.toString()); return cy .request({ method: HttpRequest.Patch, url: SuperAdminClient.adminUsers + `/${userResponse.uuid}`, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: getUserAvailableObject(users), retryOnStatusCodeFailure: true }) .then(({ body, status }) => { expect(status, 'Set user as ' + users.toString()).to.equal(HttpStatusCodes.Ok); return body.email; }); } }); return new Cypress.Promise((resolve) => { resolve(userResponse.email); }); } function setUserAsVIP(userResponse: any, vip: boolean): Cypress.Chainable<any> | PromiseLike<any> { if (vip) { cy.allure().logStep(`Set user as VIP = ${vip}`); return cy .request({ method: HttpRequest.Patch, url: SuperAdminClient.adminUsers + `/${userResponse.uuid}`, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: { vip: true }, retryOnStatusCodeFailure: true }) .then(({ body, status }) => { expect(status, 'Set user as VIP').to.equal(HttpStatusCodes.Ok); cy.log('Returned response email : ' + body.email); cy.task('putDataInCache', { key: 'userResponse', data: userResponse }).then(() => { return { userResponse }; }); }); } return new Cypress.Promise((resolve) => { resolve({ userResponse }); }); } function getUserAvailableObject(users: User_Type[]): any { const userParameters: { [key in User_Type]?: boolean } = {}; users.forEach((user) => { userParameters[user] = true; }); return userParameters; } function retrieveUserByEmail(email: string, current_attempt = 1): Cypress.Chainable<any> { cy.allure().logStep('Retrieve user by email'); cy.wait(Timeouts.SHORT_TIMEOUT_3_SEC.timeout); // Wait newly created user to sync return cy .request({ method: HttpRequest.Get, url: SuperAdminClient.adminUsers, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, qs: { q: email, size: 12 }, retryOnStatusCodeFailure: true }) .then(({ body, status }) => { expect(status, 'Retrieve user by email').to.equal(HttpStatusCodes.Ok); const response = body?._embedded?.users; if (!response) { // Temporary logging to track the response body without an array of users. To be deleted later Logs.logToCypressAndAllure( `Request: ${HttpRequest.Get} ${SuperAdminClient.adminUsers}\n Response body: ${JSON.stringify(body)}` ); } const userResponse = response?.find(function (user: any) { cy.log('Returned response email : ' + user.email); return user.email === email.toLowerCase(); }); if (!userResponse) { if (current_attempt > 3) { cy.log(`User response return empty after ${current_attempt} attempts`); throw new Error(`User response return empty after ${current_attempt} attempts`); } else { ++current_attempt; cy.wait(Timeouts.MEDIUM_TIMEOUT_10_SEC.timeout); cy.log('Retrying since user response return empty. Attempt: ' + current_attempt); return retrieveUserByEmail(email, current_attempt); } } cy.task('putDataInCache', { key: 'userResponse', data: userResponse }).then(() => { return { userResponse }; }); }); } function setLocale(locale: string): Cypress.Chainable<any> { cy.allure().logStep('Setting locale for user'); return cy .request({ method: HttpRequest.Patch, url: AccountRegistrationClient.userInfo, headers: { Authorization: AUTH_TOKEN, contentType: Accept.ApplicationJson }, body: { locale: locale }, retryOnStatusCodeFailure: true }) .then(({ status }) => { expect(status, 'Updated locale').to.equal(HttpStatusCodes.Ok); }); } function setCompanyCustomField(companyCustomField: CustomField, options: CustomFiledOption[]) { return cy .request({ method: HttpRequest.Post, url: AccountRegistrationClient.customFields, headers: { Authorization: AUTH_TOKEN, Accept: Accept.ApplicationJson }, body: CustomFieldsUtility.generateCompanyTripPurposeData(companyCustomField, options), retryOnStatusCodeFailure: true }) .then(({ status }) => { expect( status, `Custom field ${companyCustomField} updated with values: ${options.map((option) => option.value)}` ).to.equal(HttpStatusCodes.Ok); }); }