mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #12031 from overleaf/ii-payment-page-migration-three-d-secure-currency-change
[web] 3DS currency change fix GitOrigin-RevId: e88c773c6576e55803df3b2ec6a6acb1df80e8f2
This commit is contained in:
parent
48587a7a62
commit
8616c53839
6 changed files with 57 additions and 21 deletions
|
@ -15,7 +15,7 @@ function CardElement({ className, elements, onChange }: CardElementProps) {
|
|||
const { t } = useTranslation()
|
||||
const [showCardElementInvalid, setShowCardElementInvalid] =
|
||||
useState<boolean>()
|
||||
const cardRef = useRef<HTMLDivElement>(null)
|
||||
const cardRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
// Card initialization
|
||||
useEffect(() => {
|
||||
|
@ -38,6 +38,10 @@ function CardElement({ className, elements, onChange }: CardElementProps) {
|
|||
setShowCardElementInvalid(!state.focus && !state.empty && !state.valid)
|
||||
onChange(state)
|
||||
})
|
||||
|
||||
return () => {
|
||||
cardRef.current = null
|
||||
}
|
||||
}, [elements, onChange])
|
||||
|
||||
return (
|
||||
|
|
|
@ -12,7 +12,7 @@ type ThreeDSecureProps = {
|
|||
function ThreeDSecure({ actionTokenId, onToken, onError }: ThreeDSecureProps) {
|
||||
const { t } = useTranslation()
|
||||
const container = useRef<HTMLDivElement>(null)
|
||||
const recurlyContainer = useRef<HTMLDivElement>(null)
|
||||
const recurlyContainer = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// scroll the UI into view (timeout needed to make sure the element is
|
||||
|
@ -36,6 +36,10 @@ function ThreeDSecure({ actionTokenId, onToken, onError }: ThreeDSecureProps) {
|
|||
threeDSecure.on('token', onToken)
|
||||
threeDSecure.on('error', onError)
|
||||
threeDSecure.attach(recurlyContainer.current)
|
||||
|
||||
return () => {
|
||||
recurlyContainer.current = null
|
||||
}
|
||||
}, [actionTokenId, onToken, onError])
|
||||
|
||||
return (
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
defaultSubscription,
|
||||
ElementsBase,
|
||||
} from '../../fixtures/recurly-mock'
|
||||
import { fillForm } from '../../helpers/payment'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { TokenHandler, RecurlyError } from 'recurly__recurly-js'
|
||||
|
||||
|
@ -17,19 +18,6 @@ function CheckoutPanelWithPaymentProvider() {
|
|||
)
|
||||
}
|
||||
|
||||
function fillForm() {
|
||||
cy.findByTestId('test-card-element').within(() => {
|
||||
cy.get('input').each(el => {
|
||||
cy.wrap(el).type('123', { delay: 0 })
|
||||
})
|
||||
})
|
||||
cy.findByLabelText(/first name/i).type('123', { delay: 0 })
|
||||
cy.findByLabelText(/last name/i).type('123', { delay: 0 })
|
||||
cy.findByLabelText('Address').type('123', { delay: 0 })
|
||||
cy.findByLabelText(/postal code/i).type('123', { delay: 0 })
|
||||
cy.findByLabelText(/country/i).select('Bulgaria')
|
||||
}
|
||||
|
||||
describe('checkout panel', function () {
|
||||
const itmCampaign = 'fake_itm_campaign'
|
||||
const itmContent = 'fake_itm_content'
|
||||
|
@ -158,10 +146,10 @@ describe('checkout panel', function () {
|
|||
expect(win.recurly.token).to.be.calledOnceWith(
|
||||
Cypress.sinon.match.instanceOf(ElementsBase),
|
||||
{
|
||||
first_name: '123',
|
||||
last_name: '123',
|
||||
postal_code: '123',
|
||||
address1: '123',
|
||||
first_name: '1',
|
||||
last_name: '1',
|
||||
postal_code: '1',
|
||||
address1: '1',
|
||||
address2: '',
|
||||
state: '',
|
||||
city: '',
|
||||
|
@ -330,7 +318,7 @@ describe('checkout panel', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe('3D challenge', function () {
|
||||
describe('3DS challenge', function () {
|
||||
it('shows three d secure challenge', function () {
|
||||
cy.intercept('POST', 'user/subscription/create', {
|
||||
statusCode: 404,
|
||||
|
|
|
@ -4,6 +4,9 @@ import {
|
|||
} from '../../fixtures/recurly-mock'
|
||||
import { PaymentProvider } from '../../../../../../frontend/js/features/subscription/context/payment-context'
|
||||
import { plans } from '../../fixtures/plans'
|
||||
import PaymentPreviewPanel from '../../../../../../frontend/js/features/subscription/components/new/payment-preview/payment-preview-panel'
|
||||
import CheckoutPanel from '../../../../../../frontend/js/features/subscription/components/new/checkout/checkout-panel'
|
||||
import { fillForm } from '../../helpers/payment'
|
||||
|
||||
describe('common recurly validations', function () {
|
||||
beforeEach(function () {
|
||||
|
@ -39,4 +42,27 @@ describe('common recurly validations', function () {
|
|||
expect(win.recurly.Pricing.Subscription).to.be.calledOnce
|
||||
})
|
||||
})
|
||||
|
||||
it('shows three d secure challenge content only once when changing currency', function () {
|
||||
cy.intercept('POST', 'user/subscription/create', {
|
||||
statusCode: 404,
|
||||
body: {
|
||||
threeDSecureActionTokenId: '123',
|
||||
},
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<PaymentProvider publicKey="0000">
|
||||
<PaymentPreviewPanel />
|
||||
<CheckoutPanel />
|
||||
</PaymentProvider>
|
||||
)
|
||||
cy.findByTestId('checkout-form').within(() => fillForm())
|
||||
cy.findByRole('button', { name: /upgrade now/i }).click()
|
||||
cy.findByRole('button', { name: /change currency/i }).click()
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByRole('menuitem', { name: /gbp/i }).click()
|
||||
})
|
||||
cy.findAllByText('3D challenge content').should('have.length', 1)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -154,7 +154,9 @@ export class ThreeDSecureBase {
|
|||
on(_eventName = 'change', _callback: () => void) {}
|
||||
|
||||
attach(el: HTMLElement) {
|
||||
el.textContent = '3D challenge content'
|
||||
const div = document.createElement('div')
|
||||
div.appendChild(document.createTextNode('3D challenge content'))
|
||||
el.appendChild(div)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
export function fillForm() {
|
||||
cy.findByTestId('test-card-element').within(() => {
|
||||
cy.get('input').each(el => {
|
||||
cy.wrap(el).type('1', { delay: 0 })
|
||||
})
|
||||
})
|
||||
cy.findByLabelText(/first name/i).type('1', { delay: 0 })
|
||||
cy.findByLabelText(/last name/i).type('1', { delay: 0 })
|
||||
cy.findByLabelText('Address').type('1', { delay: 0 })
|
||||
cy.findByLabelText(/postal code/i).type('1', { delay: 0 })
|
||||
cy.findByLabelText(/country/i).select('Bulgaria')
|
||||
}
|
Loading…
Reference in a new issue