Skip to content

Commit

Permalink
POC: Tree shaking with new operator (#2323)
Browse files Browse the repository at this point in the history
* feat: passing component as prop

* fix: fixed build

* feat: attempt with different rollup

* fix: reverting rollup

* feat: tree shaking kinda working with preserveModules

* fix: rendering proper components

* feat: using registry. auto option

* fix: mapping components

* feat: working with typescript

* feat: deleted unused files

* feat: clean up

* feat: more clean up

* fix: dev env. bcmc txVariants

* feat: adjusting Components

* fix: fixed createfromaction

* feat: fixed playground

* fix: circular dependency

* fix: improved registry. cleanup paypal

* feat: added browserlist

* feat: fixed type

* First PoC - Dropin & Card components are initialised directly with the new keyword. No checkout.create fn called

* Adding warnings if component initialised without ref to checkout

* Adding Redirect to Card.dependencies

* Bancontact card working

* StoredCards working in Dropin

* Bancontact card working in Dropin

* InstantPaymentMethods (googlePay) working in Dropin

* Starting to handle Redirect PMs

* UIElement retrieves calculatedProps

* Dropin renders fully for NL & BE

* Dropin sessions working

* All PMs now work (constructors altered to work against new UIElement)

* Adding missing types for props param

* props param not obligatory in Bancontact. Removed superfluous setting of type on props, in UIElement

* Removing unnecessary txVariants from static prop in Card

* All PMs now work (constructors altered to work against new UIElement)

* Testing whether all subclasses of UIElement need their own constructor

* Adding a warning for if props.type missing in UIElement

* Remove circular dependencies caused by using instanceof Core in UIElement

* Removing old constructors and other commented out code

* Clearing calls to checkout.create from playground files

* Testing Klarna

* Klarna works as redirect or widget

* Adding comment about everything that extends UIElement "needing" a constructor

* updated comment

* Used init function to solve problem of accessing this.constructor.type

* Not necessary to pass checkoutRef to init function

* Don't pass type in Bancontact constructor

* props conditional for IssuerListContainer

* Initialise all playground issuer list comps with the new opeerator

* No need to generate props._parentInstance in core.ts now that BaseElement does it

* Fixed typing for new component constructor

* Created NewableComponent type

* Removed the create & handleCreate functions from core.ts

* Reinstated a simplified create function (for use by UMD merchants). TBD, if we can remove this?

* Renaming generateUIElementProps & generateUIElementForDropin functions

* Distinguish UMD users and throw error if npm users use checkout.create

* Comment out logs

* feat: draft

* feat: draft pt2

* feat draft pt3

* feat: draft pt5

* feat: draft again

* feat: draft again

* feat: more changes

* feat: fixed storing component ref on core

* feat: added testing UMD page and fixes

* feat: minor changes

* fix: amount

* fix: umd name

* feat: attempt to improve drop-in rendering redirects

* feat: using txvariants from file

* feat: adjusted paymentmethodsconfiguration

* fix: issuerlist types

* fix: removed paymentmethodsconfiguration from core

* fix: redirect

* feat: minor changes

* tree shaking translations. fixed secured fields. commented out some tests

* fix: createFromAction. not fetching config from api for stored payments

* feat: autoregistering components. threeds added to registry by default. threeds playground page

* feat: locale as string, and added translationFile prop

* feat: moved icore to types file. cleaned up some code

* feat: typescript bump

* feat: default export added. fixed typescript on auto

* Fixing types

* Make sure this.props.Dropin is available

* Fixing type for SRPanel config

* SecuredFields component and related files renamed to CustomCard

* Fixing CustomCard types

* feat: removed babel, polyfils. adjusted rollup

* feat: populatting bundle type into core

* Make name optional in BrandsConfiguration type

* fixed package json exports

* Removing AdyenWeb imports

* Adding NODE_ENV back to package.json

* feat: removed default export from playground. fixed umd naming and package json

* Correctly declare props that can be set on the Card component

* Added data-uid attrs to the custom card fields (will allow prefilling to work in the future)

* Keep paymentsConfig v69+ compatible

* Allow maskSecurityCode config prop for CustomCard

* fix: direct imports. error when not registering class

* Create CustomCardProps type

* fix: changed uielement validation on registry

* Made some RiskModule config props optional

* Tidying up Card playground file

* Stopping names on window object from clashing

* feat: tests running

* feat: fixed tests of core folder

* test: uielement fix

* test: fix baseelement

* CustomCardProps don't inherit the 'configuration' prop

* remove brands array from card config in playground

* test: fixed click to pay tests

* test: fixed payment method list. afterpay

* moved comment

* Removing old (API v66) 3DS2 e2e tests

* tests: fixed many tests

* tests: more tests

* tests: more fixes

* tests: fixed all

* fix: interfaces of components

* Removing legacy action types relating to 3DS2. Preparing for MDFlow using createFromAction

* cleanup: tx variants boleto, onlinebanking, entercash, visa

* feat: umd source maps

* disableIOSArrowKeys config prop is false by default

* feat: sourcemaps for es modules too

* tests: partially fixed e2e playwright

* tests: checking report on ci with list reporter

* fix: storybook

* feat: type loosing for ctp

* fix: storybook phone input

* feat: disable lint when parsing js. testing typescript generation. aligned isAvailable

* fix: adding card missing types. type-checking before building

---------

Co-authored-by: nicholas <[email protected]>
  • Loading branch information
ribeiroguilherme and sponglord authored Oct 18, 2023
1 parent 1cb36f4 commit 2fb4dec
Show file tree
Hide file tree
Showing 373 changed files with 61,681 additions and 7,289 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ dist
coverage
storybook-static

# Playwright reports
packages/playground/playwright-report/


*.log*
.env
.env*
Expand Down Expand Up @@ -32,4 +36,4 @@ Vagrantfile

# Certifictes
cert
*.pem
*.pem
52,978 changes: 52,978 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions packages/e2e-playwright/app/src/pages/ANCV/ANCV.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import AdyenCheckout from '@adyen/adyen-web';
import '@adyen/adyen-web/dist/es/adyen.css';
import { AdyenCheckout, ANCV, Card } from '@adyen/adyen-web';
import '@adyen/adyen-web/styles/adyen.css';
import { handleSubmit, handleAdditionalDetails, handleError, handleOrderRequest, showAuthorised } from '../../handlers';
import { amount, shopperLocale, countryCode } from '../../services/commonConfig';
import '../../style.scss';
Expand Down Expand Up @@ -38,7 +38,7 @@ const initCheckout = async () => {
onOrderCreated: data => {
console.log('=== onOrderCreated ===', data);

window.paymentMethod = checkout.create('card').mount('.ancv-field');
window.paymentMethod = new Card({ core: checkout }).mount('.ancv-field');
},
onPaymentCompleted: () => {
showAuthorised();
Expand All @@ -52,7 +52,7 @@ const initCheckout = async () => {
// ...window.mainConfiguration
});

window.paymentMethod = checkout.create('ancv').mount('.ancv-field');
window.paymentMethod = new ANCV({ core: checkout }).mount('.ancv-field');

document.querySelector('#ancv-pay-button').addEventListener('click', () => {
window.paymentMethod.submit();
Expand Down
51 changes: 25 additions & 26 deletions packages/e2e-playwright/app/src/pages/Cards/Cards.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import AdyenCheckout from '@adyen/adyen-web';
import '@adyen/adyen-web/dist/es/adyen.css';
import { AdyenCheckout, Card } from '@adyen/adyen-web';
import '@adyen/adyen-web/styles/adyen.css';
import { handleSubmit, handleAdditionalDetails, handleError } from '../../handlers';
import { amount, shopperLocale, countryCode } from '../../services/commonConfig';
import '../../style.scss';
Expand All @@ -20,30 +20,29 @@ const initCheckout = async () => {
});

// Credit card with installments
window.card = checkout
.create('card', {
brands: ['mc', 'visa', 'amex', 'maestro', 'bcmc'],
onChange: state => {
/**
* Needed now that, for v5, we enhance the securedFields state.errors object with a rootNode prop
* - Testcafe doesn't like a ClientFunction retrieving an object with a DOM node in it!?
*
* AND, for some reason, if you place this onChange function in expiryDate.clientScripts.js it doesn't always get read.
* It'll work when it's part of a small batch but if part of the full test suite it gets ignored - so the tests that rely on
* window.mappedStateErrors fail
*/
if (!!Object.keys(state.errors).length) {
// Replace any rootNode values in the objects in state.errors with an empty string
const nuErrors = Object.entries(state.errors).reduce((acc, [fieldType, error]) => {
acc[fieldType] = error ? { ...error, rootNode: '' } : error;
return acc;
}, {});
window.mappedStateErrors = nuErrors;
}
},
...window.cardConfig
})
.mount('.card-field');
window.card = new Card({
core: checkout,
brands: ['mc', 'visa', 'amex', 'maestro', 'bcmc'],
onChange: state => {
/**
* Needed now that, for v5, we enhance the securedFields state.errors object with a rootNode prop
* - Testcafe doesn't like a ClientFunction retrieving an object with a DOM node in it!?
*
* AND, for some reason, if you place this onChange function in expiryDate.clientScripts.js it doesn't always get read.
* It'll work when it's part of a small batch but if part of the full test suite it gets ignored - so the tests that rely on
* window.mappedStateErrors fail
*/
if (!!Object.keys(state.errors).length) {
// Replace any rootNode values in the objects in state.errors with an empty string
const nuErrors = Object.entries(state.errors).reduce((acc, [fieldType, error]) => {
acc[fieldType] = error ? { ...error, rootNode: '' } : error;
return acc;
}, {});
window.mappedStateErrors = nuErrors;
}
},
...window.cardConfig
}).mount('.card-field');
};

initCheckout();
27 changes: 13 additions & 14 deletions packages/e2e-playwright/app/src/pages/CustomCards/CustomCards.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import AdyenCheckout from '@adyen/adyen-web';
import '@adyen/adyen-web/dist/es/adyen.css';
import { AdyenCheckout, CustomCard } from '@adyen/adyen-web';
import '@adyen/adyen-web/styles/adyen.css';
import { handleSubmit, handleAdditionalDetails } from '../../handlers';
import { amount, shopperLocale, countryCode } from '../../services/commonConfig';
import '../../style.scss';
Expand All @@ -20,18 +20,17 @@ const initCheckout = async () => {
...window.mainConfiguration
});

window.securedFields = checkout
.create('customcard', {
type: 'card',
brands: ['mc', 'visa', 'amex', 'bcmc', 'maestro', 'cartebancaire'],
onConfigSuccess,
onBrand,
onFocus: setFocus,
onBinLookup,
onChange,
...window.cardConfig
})
.mount('.secured-fields');
window.securedFields = new CustomCard({
core: checkout,
type: 'card',
brands: ['mc', 'visa', 'amex', 'bcmc', 'maestro', 'cartebancaire'],
onConfigSuccess,
onBrand,
onFocus: setFocus,
onBinLookup,
onChange,
...window.cardConfig
}).mount('.secured-fields');

createPayButton('.secured-fields', window.securedFields, 'securedfields');

Expand Down
13 changes: 4 additions & 9 deletions packages/e2e-playwright/app/src/pages/IssuerLists/IssuerLists.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import AdyenCheckout from '@adyen/adyen-web';
import '@adyen/adyen-web/dist/es/adyen.css';
import { AdyenCheckout, Ideal } from '@adyen/adyen-web';
import '@adyen/adyen-web/styles/adyen.css';
import { handleSubmit, handleAdditionalDetails, handleError } from '../../handlers';
import { amount, shopperLocale, countryCode } from '../../services/commonConfig';
import '../../style.scss';
Expand All @@ -24,16 +24,11 @@ const initCheckout = async () => {
showPayButton: true,
onSubmit: handleSubmit,
onAdditionalDetails: handleAdditionalDetails,
onError: handleError,
paymentMethodsConfiguration: {
ideal: {
highlightedIssuers: ['1121', '1154', '1153']
}
}
onError: handleError
// ...window.mainConfiguration
});

window.ideal = checkout.create('ideal').mount('.ideal-field');
window.ideal = new Ideal({ core: checkout, highlightedIssuers: ['1121', '1154', '1153'] }).mount('.ideal-field');
};

initCheckout();
4 changes: 2 additions & 2 deletions packages/e2e-playwright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"html-webpack-plugin": "5.5.1",
"sass-loader": "^10.2.0",
"style-loader": "^2.0.0",
"ts-loader": "^8.1.0",
"typescript": "^4.4.4",
"ts-loader": "9.4.4",
"typescript": "5.2.2",
"webpack": "5.81.0",
"webpack-cli": "5.0.2",
"webpack-dev-server": "4.13.3"
Expand Down
4 changes: 2 additions & 2 deletions packages/e2e-playwright/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ dotenv.config({ path: path.resolve('../../', '.env') });
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: './tests',
testDir: './tests/',
/* Maximum time one test can run for. */
timeout: 10 * 2000,
expect: {
Expand All @@ -29,7 +29,7 @@ const config: PlaywrightTestConfig = {
workers: process.env.CI ? 1 : 1,

/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [['html', { open: 'never' }]],
reporter: [['html', { open: 'never' }], ['list']],

/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
Expand Down
20 changes: 11 additions & 9 deletions packages/e2e-playwright/tests/card/card.avs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ import { REGULAR_TEST_CARD } from '../utils/constants';
import { binLookupMock } from '../../mocks/binLookup/binLookup.mock';
import { optionalDateAndCvcMock } from '../../mocks/binLookup/binLookup.data';

test('should move the focus to the address field since expiryDate & cvc are optional', async ({ cardAvsPage }) => {
const { cardWithAvs, page } = cardAvsPage;
test.describe('Card - AVS', () => {
test('should move the focus to the address field since expiryDate & cvc are optional', async ({ cardAvsPage }) => {
const { cardWithAvs, page } = cardAvsPage;

await binLookupMock(page, optionalDateAndCvcMock);
await binLookupMock(page, optionalDateAndCvcMock);

await cardWithAvs.isComponentVisible();
await cardWithAvs.isComponentVisible();

const firstDigits = REGULAR_TEST_CARD.substring(0, 15);
const lastDigits = REGULAR_TEST_CARD.substring(15, 16);
const firstDigits = REGULAR_TEST_CARD.substring(0, 15);
const lastDigits = REGULAR_TEST_CARD.substring(15, 16);

await cardWithAvs.typeCardNumber(firstDigits);
await cardWithAvs.typeCardNumber(lastDigits);
await cardWithAvs.typeCardNumber(firstDigits);
await cardWithAvs.typeCardNumber(lastDigits);

await expect(cardWithAvs.billingAddress.addressInput).toBeFocused();
await expect(cardWithAvs.billingAddress.addressInput).toBeFocused();
});
});
134 changes: 68 additions & 66 deletions packages/e2e-playwright/tests/card/card.contextualTexts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,96 +7,98 @@ const CVC_CONTEXTUAL_TEXT_3_DIGITS = LANG['creditCard.securityCode.contextualTex
const CVC_CONTEXTUAL_TEXT_4_DIGITS = LANG['creditCard.securityCode.contextualText.4digits'];
const CVC_ERROR = LANG['error.va.sf-cc-cvc.01'];

test('#1 Should inspect the card inputs and see they have contextual elements set', async ({ cardPage }) => {
const { card, page } = cardPage;
test.describe('Card - Contextual text', () => {
test('#1 Should inspect the card inputs and see they have contextual elements set', async ({ cardPage }) => {
const { card, page } = cardPage;

await card.isComponentVisible();
await card.isComponentVisible();

// checkout expiryDate element
await expect(card.expiryDateContextualElement).toHaveText(EXPIRY_DATE_CONTEXTUAL_TEXT);
const expiryDateAriaHidden = await card.expiryDateContextualElement.getAttribute('aria-hidden');
await expect(expiryDateAriaHidden).toEqual('true');
// checkout expiryDate element
await expect(card.expiryDateContextualElement).toHaveText(EXPIRY_DATE_CONTEXTUAL_TEXT);
const expiryDateAriaHidden = await card.expiryDateContextualElement.getAttribute('aria-hidden');
await expect(expiryDateAriaHidden).toEqual('true');

// iframe expiryDate element
await expect(card.expiryDateIframeContextualElement).toHaveText(EXPIRY_DATE_CONTEXTUAL_TEXT);
// iframe expiryDate element
await expect(card.expiryDateIframeContextualElement).toHaveText(EXPIRY_DATE_CONTEXTUAL_TEXT);

// checkout security code contextual element
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
const cvcAriaHidden = await card.cvcContextualElement.getAttribute('aria-hidden');
await expect(cvcAriaHidden).toEqual('true');
// checkout security code contextual element
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
const cvcAriaHidden = await card.cvcContextualElement.getAttribute('aria-hidden');
await expect(cvcAriaHidden).toEqual('true');

// iframe security code element
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
// iframe security code element
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);

// Type amex number and see the contextual element change in the CVC field
await card.typeCardNumber(AMEX_CARD);
// Type amex number and see the contextual element change in the CVC field
await card.typeCardNumber(AMEX_CARD);

await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_4_DIGITS);
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_4_DIGITS);
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_4_DIGITS);
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_4_DIGITS);

// Delete the card number and see the contextual element reset in the CVC field
await card.deleteCardNumber();
// Delete the card number and see the contextual element reset in the CVC field
await card.deleteCardNumber();

await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
});
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
});

test('#2 Should inspect the cvc input for a contextual text set, then it should be replaced by an error, then reset', async ({ cardPage }) => {
const { card, page } = cardPage;
test('#2 Should inspect the cvc input for a contextual text set, then it should be replaced by an error, then reset', async ({ cardPage }) => {
const { card, page } = cardPage;

await card.isComponentVisible();
await card.isComponentVisible();

// checkout security code contextual element
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
let cvcAriaHidden = await card.cvcContextualElement.getAttribute('aria-hidden');
await expect(cvcAriaHidden).toEqual('true');
// checkout security code contextual element
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
let cvcAriaHidden = await card.cvcContextualElement.getAttribute('aria-hidden');
await expect(cvcAriaHidden).toEqual('true');

// error element hidden
await expect(card.cvcErrorElement).not.toBeVisible();
// error element hidden
await expect(card.cvcErrorElement).not.toBeVisible();

// iframe security code contextual element
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
// iframe security code contextual element
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);

// press pay to generate errors
await cardPage.pay();
// press pay to generate errors
await cardPage.pay();

// checkout security code error element
await expect(card.cvcErrorElement).toBeVisible();
await expect(card.cvcErrorElement).toHaveText(CVC_ERROR);
cvcAriaHidden = await card.cvcErrorElement.getAttribute('aria-hidden');
await expect(cvcAriaHidden).toEqual('true');
// checkout security code error element
await expect(card.cvcErrorElement).toBeVisible();
await expect(card.cvcErrorElement).toHaveText(CVC_ERROR);
cvcAriaHidden = await card.cvcErrorElement.getAttribute('aria-hidden');
await expect(cvcAriaHidden).toEqual('true');

// contextual element being hidden
await expect(card.cvcContextualElement).not.toBeVisible();
// contextual element being hidden
await expect(card.cvcContextualElement).not.toBeVisible();

// iframe contextual (error) element
await expect(card.cvcIframeContextualElement).toHaveText(CVC_ERROR);
// iframe contextual (error) element
await expect(card.cvcIframeContextualElement).toHaveText(CVC_ERROR);

// Allow default focusing after validation to happen
await page.waitForTimeout(1000);
// Allow default focusing after validation to happen
await page.waitForTimeout(1000);

// type
await card.typeCvc('737');
// type
await card.typeCvc('737');

// reset
await expect(card.cvcContextualElement).toBeVisible();
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
// error element hidden
await expect(card.cvcErrorElement).not.toBeVisible();
// reset
await expect(card.cvcContextualElement).toBeVisible();
await expect(card.cvcContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
// error element hidden
await expect(card.cvcErrorElement).not.toBeVisible();

await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
});
await expect(card.cvcIframeContextualElement).toHaveText(CVC_CONTEXTUAL_TEXT_3_DIGITS);
});

test('#3 Should find no contextualElements because the config says to not show them', async ({ cardNoContextualElementPage }) => {
const { card, page } = cardNoContextualElementPage;
test('#3 Should find no contextualElements because the config says to not show them', async ({ cardNoContextualElementPage }) => {
const { card, page } = cardNoContextualElementPage;

await card.isComponentVisible();
await card.isComponentVisible();

// checkout contextual elements not present
await expect(card.expiryDateContextualElement).not.toBeVisible();
await expect(card.cvcContextualElement).not.toBeVisible();
// checkout contextual elements not present
await expect(card.expiryDateContextualElement).not.toBeVisible();
await expect(card.cvcContextualElement).not.toBeVisible();

// iframe contextual elements - present but without text
await expect(card.expiryDateIframeContextualElement).toHaveText('');
await expect(card.cvcIframeContextualElement).toHaveText('');
// iframe contextual elements - present but without text
await expect(card.expiryDateIframeContextualElement).toHaveText('');
await expect(card.cvcIframeContextualElement).toHaveText('');
});
});
Loading

0 comments on commit 2fb4dec

Please sign in to comment.