Skip to content
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

Update to Recaptcha Enterprise #1128

Merged
merged 11 commits into from
Jan 14, 2025
7 changes: 6 additions & 1 deletion src/app/branded/branded-checkout.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import thankYouSummary from 'app/thankYou/summary/thankYouSummary.component'

import sessionService from 'common/services/session/session.service'
import orderService from 'common/services/api/order.service'
import checkoutService from 'common/services/checkoutHelpers/checkout.service'
import brandedAnalyticsFactory from './analytics/branded-analytics.factory'

import 'common/lib/fakeLocalStorage'
Expand All @@ -23,7 +24,7 @@ const componentName = 'brandedCheckout'

class BrandedCheckoutController {
/* @ngInject */
constructor ($element, $window, analyticsFactory, brandedAnalyticsFactory, tsysService, sessionService, envService, orderService, $translate) {
constructor ($element, $window, analyticsFactory, brandedAnalyticsFactory, tsysService, sessionService, envService, orderService, checkoutService, $translate) {
this.$element = $element[0] // extract the DOM element from the jqLite wrapper
this.$window = $window
this.analyticsFactory = analyticsFactory
Expand All @@ -33,6 +34,7 @@ class BrandedCheckoutController {
this.envService = envService
this.orderService = orderService
this.$translate = $translate
this.checkoutService = checkoutService

this.orderService.clearCoverFees()
}
Expand All @@ -57,6 +59,8 @@ class BrandedCheckoutController {
console.error(err)
})
this.$translate.use(this.language || 'en')

this.checkoutService.initializeRecaptcha()
}

formatDonorDetails () {
Expand Down Expand Up @@ -152,6 +156,7 @@ export default angular
thankYouSummary.name,
sessionService.name,
orderService.name,
checkoutService.name,
brandedAnalyticsFactory.name,
uibModal,
'environment',
Expand Down
11 changes: 10 additions & 1 deletion src/app/branded/branded-checkout.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@ describe('branded checkout', () => {
onOrderCompleted: jest.fn(),
onOrderFailed: jest.fn(),
},
);
)
}))

describe('$onInit', () => {
beforeEach(() => {
jest.spyOn($ctrl.checkoutService, 'initializeRecaptcha').mockImplementation(() => {})
})

it('should set API Url if custom one is set', () => {
$ctrl.apiUrl = 'https://custom-api.cru.org'
$ctrl.$onInit()
Expand All @@ -74,6 +78,11 @@ describe('branded checkout', () => {
expect($ctrl.formatDonorDetails).toHaveBeenCalled()
expect($ctrl.$window.sessionStorage.removeItem).toHaveBeenCalledWith('initialLoadComplete')
})

it('should initialize recaptcha', () => {
$ctrl.$onInit()
expect($ctrl.checkoutService.initializeRecaptcha).toHaveBeenCalled()
})
})

describe('formatDonorDetails', () => {
Expand Down
5 changes: 0 additions & 5 deletions src/app/checkout/cart-summary/cart-summary.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import template from './cart-summary.tpl.html'

const componentName = 'checkoutCartSummary'

export const recaptchaFailedEvent = 'recaptchaFailedEvent'
export const submitOrderEvent = 'submitOrderEvent'

class CartSummaryController {
Expand All @@ -22,10 +21,6 @@ class CartSummaryController {
return this.cartService.buildCartUrl()
}

handleRecaptchaFailure (componentInstance) {
componentInstance.$rootScope.$emit(recaptchaFailedEvent)
}

onSubmit (componentInstance) {
componentInstance.$rootScope.$emit(submitOrderEvent)
}
Expand Down
8 changes: 0 additions & 8 deletions src/app/checkout/cart-summary/cart-summary.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,5 @@ describe('checkout', function () {
expect(componentInstance.$rootScope.$emit).toHaveBeenCalledWith(submitOrderEvent)
})
})

describe('handleRecaptchaFailure', () => {
it('should emit an event', () => {
jest.spyOn(componentInstance.$rootScope, '$emit').mockImplementation(() => {})
self.controller.handleRecaptchaFailure(componentInstance)
expect(componentInstance.$rootScope.$emit).toHaveBeenCalledWith(recaptchaFailedEvent)
})
})
})
})
3 changes: 1 addition & 2 deletions src/app/checkout/cart-summary/cart-summary.tpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ <h3 id="cart-summary-header" class="panel-name" translate>Cart Summary</h3>
<a id="editCartButton" ng-href="{{$ctrl.buildCartUrl()}}" class="btn btn-subtle mt" translate>Edit Cart</a>
<recaptcha-wrapper
ng-if="$ctrl.showSubmitBtn"
action="'submit_gift'"
action="'checkout'"
on-success="$ctrl.onSubmit"
on-failure="$ctrl.handleRecaptchaFailure"
component-instance="$ctrl.componentReference"
button-id="'submitGiftButton'"
button-type="'submit'"
Expand Down
7 changes: 6 additions & 1 deletion src/app/checkout/checkout.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import showErrors from 'common/filters/showErrors.filter'
import cartService from 'common/services/api/cart.service'
import orderService from 'common/services/api/order.service'
import designationsService from 'common/services/api/designations.service'
import checkoutService from 'common/services/checkoutHelpers/checkout.service'

import sessionEnforcerService, { EnforcerCallbacks } from 'common/services/session/sessionEnforcer.service'
import { Roles, SignOutEvent } from 'common/services/session/session.service'
Expand All @@ -27,7 +28,7 @@ const componentName = 'checkout'

class CheckoutController {
/* @ngInject */
constructor ($window, $location, $rootScope, $log, cartService, envService, orderService, designationsService, sessionEnforcerService, analyticsFactory) {
constructor ($window, $location, $rootScope, $log, cartService, envService, orderService, designationsService, sessionEnforcerService, checkoutService, analyticsFactory) {
this.$log = $log
this.$window = $window
this.$location = $location
Expand All @@ -40,6 +41,7 @@ class CheckoutController {
this.loadingCartData = true
this.analyticsFactory = analyticsFactory
this.selfReference = this
this.checkoutService = checkoutService
}

$onInit () {
Expand All @@ -56,6 +58,8 @@ class CheckoutController {
this.initStepParam(true)
this.listenForLocationChange()
this.analyticsFactory.pageLoaded(true)

this.checkoutService.initializeRecaptcha()
}

$onDestroy () {
Expand Down Expand Up @@ -146,6 +150,7 @@ export default angular
orderService.name,
designationsService.name,
sessionEnforcerService.name,
checkoutService.name,
showErrors.name,
analyticsFactory.name
])
Expand Down
2 changes: 2 additions & 0 deletions src/app/checkout/checkout.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('checkout', function () {
jest.spyOn(self.controller, 'sessionEnforcerService').mockImplementation(() => {})
jest.spyOn(self.controller.$rootScope, '$on').mockImplementation(() => {})
jest.spyOn(self.controller, 'signedOut').mockImplementation(() => {})
jest.spyOn(self.controller.checkoutService, 'initializeRecaptcha').mockImplementation(() => {})
self.controller.$onInit()
})

Expand All @@ -53,6 +54,7 @@ describe('checkout', function () {
self.controller.$rootScope.$on.mock.calls[0][1]()

expect(self.controller.signedOut).toHaveBeenCalled()
expect(self.controller.checkoutService.initializeRecaptcha).toHaveBeenCalled()
})

describe('sessionEnforcerService success', () => {
Expand Down
17 changes: 1 addition & 16 deletions src/app/checkout/step-3/step-3.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { datadogRum } from '@datadog/browser-rum'
import template from './step-3.tpl.html'

import analyticsFactory from 'app/analytics/analytics.factory'
import { recaptchaFailedEvent, submitOrderEvent } from 'app/checkout/cart-summary/cart-summary.component'
import { submitOrderEvent } from 'app/checkout/cart-summary/cart-summary.component'

const componentName = 'checkoutStep3'

Expand All @@ -46,9 +46,6 @@ class Step3Controller {
this.$onInit()
})

this.$rootScope.$on(recaptchaFailedEvent, () => {
this.handleRecaptchaFailure(this)
})
this.$rootScope.$on(submitOrderEvent, () => {
this.submitOrder()
})
Expand Down Expand Up @@ -183,18 +180,6 @@ class Step3Controller {
componentInstance.$window.scrollTo(0, 0)
})
}

handleRecaptchaFailure (componentInstance) {
componentInstance.analyticsFactory.checkoutFieldError('submitOrder', 'failed')
componentInstance.submittingOrder = false
componentInstance.onSubmittingOrder({ value: false })

componentInstance.loadCart()

componentInstance.onSubmitted()
componentInstance.submissionError = 'generic error'
componentInstance.$window.scrollTo(0, 0)
}
}

export default angular
Expand Down
22 changes: 0 additions & 22 deletions src/app/checkout/step-3/step-3.component.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,34 +448,12 @@ describe('checkout', () => {
})
})

describe('handleRecaptchaFailure', () => {
it('should show an error if recaptcha fails', () => {
const componentInstance = self.controller
jest.spyOn(componentInstance.analyticsFactory, 'checkoutFieldError').mockImplementation(() => {})
self.controller.handleRecaptchaFailure(componentInstance)

expect(componentInstance.analyticsFactory.checkoutFieldError).toHaveBeenCalledWith('submitOrder', 'failed')
expect(componentInstance.submittingOrder).toEqual(false)
expect(componentInstance.onSubmittingOrder).toHaveBeenCalledWith({ value: false })
expect(componentInstance.loadCart).toHaveBeenCalled()
expect(componentInstance.onSubmitted).toHaveBeenCalled()
expect(componentInstance.submissionError).toEqual('generic error')
expect(componentInstance.$window.scrollTo).toHaveBeenCalledWith(0, 0)
})
})

describe('event handling', () => {
it('should call submit order if the submitOrderEvent is received', () => {
jest.spyOn(self.controller, 'submitOrder').mockImplementation(() => {})
self.controller.$rootScope.$emit(submitOrderEvent)
expect(self.controller.submitOrder).toHaveBeenCalled()
})

it('should call handleRecaptchaFailure if the recaptchaFailedEvent is received', () => {
jest.spyOn(self.controller, 'handleRecaptchaFailure').mockImplementation(() => {})
self.controller.$rootScope.$emit(recaptchaFailedEvent)
expect(self.controller.handleRecaptchaFailure).toHaveBeenCalledWith(self.controller)
})
})
})
})
3 changes: 1 addition & 2 deletions src/app/checkout/step-3/step-3.tpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,8 @@
</div>
<div class="checkout-cta pull-right">
<recaptcha-wrapper
action="$ctrl.isBranded ? 'branded_submit' : 'submit_gift'"
action="$ctrl.isBranded ? 'branded_checkout' : 'checkout'"
on-success="$ctrl.submitOrderInternal"
on-failure="$ctrl.handleRecaptchaFailure"
component-instance="$ctrl.selfReference"
button-id="'submitOrderButton'"
button-type="'submit'"
Expand Down
12 changes: 6 additions & 6 deletions src/common/app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const appConfig = /* @ngInject */ function (envServiceProvider, $compileP
publicCru: 'https://stage.cru.org',
publicGive: 'https://give-stage2.cru.org',
acsUrl: 'https://cru-mkt-stage1.adobe-campaign.com/lp/LP63?_uuid=f1938f90-38ea-41a6-baad-9ac133f6d2ec&service=%404k83N_C5RZnLNvwz7waA2SwyzIuP6ATcN8vJjmT5km0iZPYKUUYk54sthkZjj-hltAuOKDYocuEi5Pxv8BSICoA4uppcvU_STKCzjv9RzLpE4hqj&pkey=',
recaptchaKey: '6LdNz5UlAAAAAPSrzydROuY76yGVIquVQAup69PO'
recaptchaKey: '6LcCMoYqAAAAABMoyLs5CyKWwE8qn_YslEaiRPRD'
},
devcloud: {
apiUrl: 'https://give-stage2.cru.org',
Expand All @@ -63,7 +63,7 @@ export const appConfig = /* @ngInject */ function (envServiceProvider, $compileP
publicCru: 'https://stage-cloud.cru.org',
publicGive: 'https://give-dev-cloud.cru.org',
acsUrl: 'https://cru-mkt-stage1.adobe-campaign.com/lp/LP63?_uuid=f1938f90-38ea-41a6-baad-9ac133f6d2ec&service=%404k83N_C5RZnLNvwz7waA2SwyzIuP6ATcN8vJjmT5km0iZPYKUUYk54sthkZjj-hltAuOKDYocuEi5Pxv8BSICoA4uppcvU_STKCzjv9RzLpE4hqj&pkey=',
recaptchaKey: '6LdNz5UlAAAAAPSrzydROuY76yGVIquVQAup69PO'
recaptchaKey: '6LcCMoYqAAAAABMoyLs5CyKWwE8qn_YslEaiRPRD'
},
stagecloud: {
apiUrl: 'https://give-stage-cloud.cru.org',
Expand All @@ -72,7 +72,7 @@ export const appConfig = /* @ngInject */ function (envServiceProvider, $compileP
publicCru: 'https://stage-cloud.cru.org',
publicGive: 'https://give-stage-cloud.cru.org',
acsUrl: 'https://cru-mkt-stage1.adobe-campaign.com/lp/LP63?_uuid=f1938f90-38ea-41a6-baad-9ac133f6d2ec&service=%404k83N_C5RZnLNvwz7waA2SwyzIuP6ATcN8vJjmT5km0iZPYKUUYk54sthkZjj-hltAuOKDYocuEi5Pxv8BSICoA4uppcvU_STKCzjv9RzLpE4hqj&pkey=',
recaptchaKey: '6LdNz5UlAAAAAPSrzydROuY76yGVIquVQAup69PO'
recaptchaKey: '6LcCMoYqAAAAABMoyLs5CyKWwE8qn_YslEaiRPRD'
},
prodcloud: {
apiUrl: 'https://give-prod-cloud.cru.org',
Expand All @@ -81,7 +81,7 @@ export const appConfig = /* @ngInject */ function (envServiceProvider, $compileP
publicCru: 'https://www.cru.org',
publicGive: 'https://give-prod-cloud.cru.org',
acsUrl: 'https://cru-mkt-prod1-m.adobe-campaign.com/lp/LPEmailPrefCenter?_uuid=8831d67a-0d46-406b-8987-fd07c97c4ca7&service=%400fAlW4GPmxXExp8qlx7HDlAM6FSZUd0yYRlQg6HRsO_kglfi0gs650oHPZX6LrOvg7OHoIWWpobOeGZduxdNU_m5alc&pkey=',
recaptchaKey: '6LdNz5UlAAAAAPSrzydROuY76yGVIquVQAup69PO'
recaptchaKey: '6LduSiQqAAAAAOLA7NEU8-3-mdCmBKEUCwaFQuJF'
},
staging: {
apiUrl: 'https://give-stage2.cru.org',
Expand All @@ -90,7 +90,7 @@ export const appConfig = /* @ngInject */ function (envServiceProvider, $compileP
publicCru: 'https://stage.cru.org',
publicGive: 'https://give-stage2.cru.org',
acsUrl: 'https://cru-mkt-stage1.adobe-campaign.com/lp/LP63?_uuid=f1938f90-38ea-41a6-baad-9ac133f6d2ec&service=%404k83N_C5RZnLNvwz7waA2SwyzIuP6ATcN8vJjmT5km0iZPYKUUYk54sthkZjj-hltAuOKDYocuEi5Pxv8BSICoA4uppcvU_STKCzjv9RzLpE4hqj&pkey=',
recaptchaKey: '6LdNz5UlAAAAAPSrzydROuY76yGVIquVQAup69PO'
recaptchaKey: '6LcCMoYqAAAAABMoyLs5CyKWwE8qn_YslEaiRPRD'
},
nonprod: {
apiUrl: 'https://give-stage2-next.cru.org',
Expand All @@ -116,7 +116,7 @@ export const appConfig = /* @ngInject */ function (envServiceProvider, $compileP
publicCru: 'https://www.cru.org',
publicGive: 'https://give.cru.org',
acsUrl: 'https://cru-mkt-prod1-m.adobe-campaign.com/lp/LPEmailPrefCenter?_uuid=8831d67a-0d46-406b-8987-fd07c97c4ca7&service=%400fAlW4GPmxXExp8qlx7HDlAM6FSZUd0yYRlQg6HRsO_kglfi0gs650oHPZX6LrOvg7OHoIWWpobOeGZduxdNU_m5alc&pkey=',
recaptchaKey: '6LdNz5UlAAAAAPSrzydROuY76yGVIquVQAup69PO'
recaptchaKey: '6LduSiQqAAAAAOLA7NEU8-3-mdCmBKEUCwaFQuJF'
},
defaults: {
isCheckout: false,
Expand Down
Loading
Loading