Skip to content

Commit

Permalink
Adding support for Custom URLs (#2262)
Browse files Browse the repository at this point in the history
* feat: supporting custom urls

* fix: reverting safety checks

* feat: using url when resolving

* feat: changeset + change in the environments + test
  • Loading branch information
ribeiroguilherme authored Aug 24, 2023
1 parent ea00111 commit 1532d70
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .changeset/soft-clouds-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@adyen/adyen-web': minor
---

Added environmentUrls parameter to Core, which allows PBL to use custom URLs for the API and assets
25 changes: 21 additions & 4 deletions packages/lib/src/components/Dropin/Dropin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('Dropin', () => {
let dropin: DropinElement;

beforeEach(async () => {
const checkout = await AdyenCheckout({ analytics: { enabled: false } });
const checkout = await AdyenCheckout({ environment: 'test', clientKey: 'test_123456', analytics: { enabled: false } });
dropin = checkout.create('dropin');
});

Expand Down Expand Up @@ -65,7 +65,7 @@ describe('Dropin', () => {
});

test('should handle new challenge action', async () => {
const checkout = await AdyenCheckout({ analytics: { enabled: false } });
const checkout = await AdyenCheckout({ environment: 'test', clientKey: 'test_123456', analytics: { enabled: false } });

const dropin = checkout.create('dropin');

Expand All @@ -77,7 +77,11 @@ describe('Dropin', () => {
});

test('new challenge action gets challengeWindowSize from paymentMethodsConfiguration', async () => {
const checkout = await AdyenCheckout({ paymentMethodsConfiguration: { threeDS2: { challengeWindowSize: '02' } } });
const checkout = await AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
paymentMethodsConfiguration: { threeDS2: { challengeWindowSize: '02' } }
});

const dropin = checkout.create('dropin');

Expand All @@ -87,7 +91,12 @@ describe('Dropin', () => {
});

test('new challenge action gets challengeWindowSize from handleAction config', async () => {
const checkout = await AdyenCheckout({ analytics: { enabled: false }, challengeWindowSize: '04' });
const checkout = await AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
analytics: { enabled: false },
challengeWindowSize: '04'
});

const dropin = checkout.create('dropin');
mount(dropin.render());
Expand All @@ -103,6 +112,8 @@ describe('Dropin', () => {
describe('Instant Payments feature', () => {
test('formatProps formats instantPaymentTypes removing duplicates and invalid values', async () => {
const checkout = await AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
analytics: { enabled: false }
});
const dropin = checkout.create('dropin', { instantPaymentTypes: ['alipay', 'paywithgoogle', 'paywithgoogle', 'paypal'] });
Expand All @@ -112,6 +123,8 @@ describe('Dropin', () => {

test('formatProps filter out instantPaymentMethods from paymentMethods list ', async () => {
const checkout = await AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
analytics: { enabled: false },
paymentMethodsResponse: {
paymentMethods: [
Expand All @@ -135,6 +148,8 @@ describe('Dropin', () => {
];

const checkout = await AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
analytics: { enabled: false },
paymentMethodsResponse: {
paymentMethods
Expand All @@ -153,6 +168,8 @@ describe('Dropin', () => {
beforeEach(async () => {
const paymentMethods = [{ name: 'AliPay', type: 'alipay' }];
const checkout = await AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
analytics: { enabled: false },
paymentMethodsResponse: {
paymentMethods
Expand Down
4 changes: 3 additions & 1 deletion packages/lib/src/components/UIElement.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ describe('UIElement', () => {
type: 'threeDS2'
};

const checkout = await AdyenCheckout({ analytics: { enabled: false } });
const checkout = await AdyenCheckout({ environment: 'test', clientKey: 'test_123456', analytics: { enabled: false } });
const comp = checkout.create('card').mount('body');

const pa = comp.handleAction(fingerprintAction);
Expand All @@ -151,6 +151,8 @@ describe('UIElement', () => {

test('should handle new challenge action', async () => {
const checkout = await AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
analytics: { enabled: false },
paymentMethodsConfiguration: {
threeDS2: { challengeWindowSize: '02' }
Expand Down
43 changes: 37 additions & 6 deletions packages/lib/src/core/Environment/Environment.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,47 @@
import { resolveEnvironment } from './Environment';
import { resolveCDNEnvironment, resolveEnvironment } from './Environment';

describe('Environment', () => {
test('resolves set environments', () => {
describe('Resolving API environment', () => {
test('should return the proper URL according to the environment type', () => {
expect(resolveEnvironment('test')).toBe('https://checkoutshopper-test.adyen.com/checkoutshopper/');
expect(resolveEnvironment('TEST')).toBe('https://checkoutshopper-test.adyen.com/checkoutshopper/');
expect(resolveEnvironment('live')).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
expect(resolveEnvironment('LIVE')).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
});

test('resolves a URL environment', () => {
expect(resolveEnvironment('https://example.com/')).toBe('https://example.com/');
test('should return environmentUrl if provided', () => {
expect(resolveEnvironment('devl', 'http://localhost:8080/checkoutshopper/')).toBe('http://localhost:8080/checkoutshopper/');
expect(resolveEnvironment('test', 'https://checkout-zeta.com/checkoutshopper/')).toBe('https://checkout-zeta.com/checkoutshopper/');
});

test('resolves to the live environment as a fallback', () => {
test('should return the live environment URL if environment type is not valid', () => {
expect(resolveEnvironment('invalid-environment')).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
});

test('should return the live environment URL if environment type is not provided', () => {
// @ts-ignore It can happen that 'environment' property is not be passed by the merchant
expect(resolveEnvironment()).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
});
});

describe('Resolving CDN Environment', () => {
test('should return the proper URL according to the environment type', () => {
expect(resolveCDNEnvironment('beta')).toBe('https://cdf6519016.cdn.adyen.com/checkoutshopper/');
expect(resolveCDNEnvironment('BETA')).toBe('https://cdf6519016.cdn.adyen.com/checkoutshopper/');
expect(resolveCDNEnvironment('live')).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
expect(resolveCDNEnvironment('LIVE')).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
});

test('should return environmentUrl if provided', () => {
expect(resolveCDNEnvironment('devl', 'http://localhost:8080/checkoutshopper/')).toBe('http://localhost:8080/checkoutshopper/');
expect(resolveCDNEnvironment('beta', 'https://testing-beta-cdn.com/')).toBe('https://testing-beta-cdn.com/');
});

test('should return the live environment URL if environment type is not valid', () => {
expect(resolveCDNEnvironment('invalid-environment')).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
});

test('should return the live environment URL if environment type is not provided', () => {
// @ts-ignore It can happen that 'environment' property is not be passed by the merchant
expect(resolveCDNEnvironment()).toBe('https://checkoutshopper-live.adyen.com/checkoutshopper/');
});
});
14 changes: 10 additions & 4 deletions packages/lib/src/core/Environment/Environment.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export const FALLBACK_CONTEXT = 'https://checkoutshopper-live.adyen.com/checkoutshopper/';
export const resolveEnvironment = (env = '', environmentUrl?: string): string => {
if (environmentUrl) {
return environmentUrl;
}

export const resolveEnvironment = (env: string = FALLBACK_CONTEXT): string => {
const environments = {
test: 'https://checkoutshopper-test.adyen.com/checkoutshopper/',
live: 'https://checkoutshopper-live.adyen.com/checkoutshopper/',
Expand All @@ -10,12 +13,15 @@ export const resolveEnvironment = (env: string = FALLBACK_CONTEXT): string => {
'live-in': 'https://checkoutshopper-live-in.adyen.com/checkoutshopper/'
};

return environments[env] || environments[env.toLowerCase()] || env;
return environments[env.toLowerCase()] || FALLBACK_CONTEXT;
};

export const FALLBACK_CDN_CONTEXT = 'https://checkoutshopper-live.adyen.com/checkoutshopper/';
export const resolveCDNEnvironment = (env = '', environmentUrl?: string) => {
if (environmentUrl) {
return environmentUrl;
}

export const resolveCDNEnvironment = (env: string = FALLBACK_CDN_CONTEXT) => {
const environments = {
beta: 'https://cdf6519016.cdn.adyen.com/checkoutshopper/',
test: 'https://checkoutshopper-test.adyen.com/checkoutshopper/',
Expand All @@ -26,5 +32,5 @@ export const resolveCDNEnvironment = (env: string = FALLBACK_CDN_CONTEXT) => {
'live-in': 'https://checkoutshopper-live-in.adyen.com/checkoutshopper/'
};

return environments[env] || environments[env.toLowerCase()] || env;
return environments[env.toLowerCase()] || FALLBACK_CDN_CONTEXT;
};
4 changes: 2 additions & 2 deletions packages/lib/src/core/core.component.props.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ const checkoutConfig = {
value: 19000
},
shopperLocale: 'en-US',
clientKey: 'test_F7_FEKJHF',
environment: 'test',
clientKey: 'test_F7_FEKJHF',
paymentMethodsResponse,
paymentMethodsConfiguration: paymentMethodsConfiguration as PaymentMethodsConfiguration
};
Expand Down Expand Up @@ -420,7 +420,7 @@ describe('Trying to add a "scheme" property to the paymentMethodsConfiguration t
};

test('Trying to create a card component with a paymentMethodsConfiguration with a "scheme" property shows a warning in the console ', () => {
new AdyenCheckout({ paymentMethodsConfiguration });
new AdyenCheckout({ environment: 'test', clientKey: 'test_123456', paymentMethodsConfiguration });
// expect warning in console
expect(console.warn).toHaveBeenCalled();
});
Expand Down
54 changes: 43 additions & 11 deletions packages/lib/src/core/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,24 @@ beforeEach(() => {

describe('Core', () => {
test('should default to the FALLBACK_LOCALE', async () => {
const checkout = new AdyenCheckout({});
const checkout = new AdyenCheckout({ environment: 'test', clientKey: 'test_123456' });
await checkout.initialize();

expect(checkout.modules.i18n.locale).toBe('en-US');
});

test('should create the modules when initializing on Advanced Flow', async () => {
const checkout = new AdyenCheckout({});
const checkout = new AdyenCheckout({ environment: 'test', clientKey: 'test_123456' });
await checkout.initialize();

expect(Object.keys(checkout.modules).length).toBeGreaterThan(1);
});

test('should create the modules when initializing on Sesssions flow', async () => {
const checkout = new AdyenCheckout({
session: { id: 'session-id', sessionData: 'sesssion-data' },
environment: 'test',
clientKey: 'xxxx'
clientKey: 'test_123456',
session: { id: 'session-id', sessionData: 'sesssion-data' }
});

await checkout.initialize();
Expand All @@ -56,15 +56,15 @@ describe('Core', () => {
});

test('should set a custom locale', async () => {
const checkout = new AdyenCheckout({ locale: 'es-ES' });
const checkout = new AdyenCheckout({ environment: 'test', clientKey: 'test_123456', locale: 'es-ES' });
await checkout.initialize();

expect(checkout.modules.i18n.locale).toBe('es-ES');
});

describe('create', () => {
test('should create a component if it exists', async () => {
const checkout = new AdyenCheckout({});
const checkout = new AdyenCheckout({ environment: 'test', clientKey: 'test_123456' });
await checkout.initialize();

expect(checkout.create('dropin')).toBeTruthy();
Expand All @@ -77,15 +77,15 @@ describe('Core', () => {
const onSubmitMockComponent = jest.fn().mockName('onSubmitMockComponent');

test('component props receive global props if not defined elsewhere', async () => {
const checkout = new AdyenCheckout({ onSubmit: onSubmitMockGlobal });
const checkout = new AdyenCheckout({ environment: 'test', clientKey: 'test_123456', onSubmit: onSubmitMockGlobal });
await checkout.initialize();
const component = checkout.create('card');

expect(component.props.onSubmit).toBe(onSubmitMockGlobal);
});

test('component props take precedence over global props', async () => {
const checkout = new AdyenCheckout({ onSubmit: onSubmitMockGlobal });
const checkout = new AdyenCheckout({ environment: 'test', clientKey: 'test_123456', onSubmit: onSubmitMockGlobal });
await checkout.initialize();
const component = checkout.create('card', { onSubmit: onSubmitMockComponent });

Expand All @@ -94,6 +94,8 @@ describe('Core', () => {

test('paymentMethodsConfiguration props take precedence over global props', async () => {
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
onSubmit: onSubmitMockGlobal,
paymentMethodsConfiguration: { card: { onSubmit: onSubmitMockPMConfig } }
});
Expand All @@ -105,6 +107,8 @@ describe('Core', () => {

test('component props take precedence over paymentMethodsConfiguration props', async () => {
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
paymentMethodsConfiguration: { card: { onSubmit: onSubmitMockPMConfig } }
});
await checkout.initialize();
Expand All @@ -117,7 +121,10 @@ describe('Core', () => {

describe('createFromAction', () => {
test('should create a component from an action object', async () => {
const checkout = new AdyenCheckout({});
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456'
});
await checkout.initialize();

const paymentAction = checkout.createFromAction({
Expand All @@ -131,7 +138,11 @@ describe('Core', () => {
});

test('should handle new fingerprint action', async () => {
const checkout = new AdyenCheckout({ paymentMethodsConfiguration: { threeDS2: { challengeWindowSize: '04' } } });
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
paymentMethodsConfiguration: { threeDS2: { challengeWindowSize: '04' } }
});
await checkout.initialize();

const fingerprintAction = {
Expand All @@ -155,6 +166,8 @@ describe('Core', () => {

test('should handle new challenge action', async () => {
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
paymentMethodsConfiguration: {
threeDS2: {
challengeWindowSize: '03'
Expand Down Expand Up @@ -187,6 +200,8 @@ describe('Core', () => {

test('paymentMethodsConfiguration properties take precedence over global configuration', async () => {
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
onAdditionalDetails: onAdditionalDetailsGlobal,
paymentMethodsConfiguration: { qrCode: { onAdditionalDetails: onAdditionalDetailsBCMC } }
});
Expand All @@ -203,6 +218,8 @@ describe('Core', () => {

test('createFromAction props take precedence over paymentMethodsConfiguration and global configuration', async () => {
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456',
onAdditionalDetails: onAdditionalDetailsGlobal,
paymentMethodsConfiguration: { qrCode: { onAdditionalDetails: onAdditionalDetailsBCMC } }
});
Expand All @@ -226,7 +243,10 @@ describe('Core', () => {

describe('update', () => {
test('Should update all components under main instance', async () => {
const checkout = new AdyenCheckout({});
const checkout = new AdyenCheckout({
environment: 'test',
clientKey: 'test_123456'
});
await checkout.initialize();

const component = checkout.create('dropin').mount('body');
Expand All @@ -249,4 +269,16 @@ describe('Core', () => {
expect(checkout.paymentMethodsResponse).toHaveProperty('paymentMethods', paymentMethodsResponse.paymentMethods);
});
});

test('should use custom checkoutshopper URL url if available', () => {
const checkout = new AdyenCheckout({
environment: 'test',
environmentUrls: {
api: 'https://localhost:8080/checkoutshopper/'
},
clientKey: 'devl_FX923810'
});

expect(checkout.loadingContext).toBe('https://localhost:8080/checkoutshopper/');
});
});
6 changes: 3 additions & 3 deletions packages/lib/src/core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ class Core {

this.setOptions(props);

this.loadingContext = resolveEnvironment(this.options.environment);
this.cdnContext = resolveCDNEnvironment(this.options.resourceEnvironment || this.options.environment);
this.loadingContext = resolveEnvironment(this.options.environment, this.options.environmentUrls?.api);
this.cdnContext = resolveCDNEnvironment(this.options.resourceEnvironment || this.options.environment, this.options.environmentUrls?.api);

const clientKeyType = this.options.clientKey?.substr(0, 4);
if ((clientKeyType === 'test' || clientKeyType === 'live') && !this.loadingContext.includes(clientKeyType)) {
throw new Error(`Error: you are using a ${clientKeyType} clientKey against the ${this.options.environment} environment`);
throw new Error(`Error: you are using a '${clientKeyType}' clientKey against the '${this.options.environment}' environment`);
}

// Expose version number for npm builds
Expand Down
Loading

0 comments on commit 1532d70

Please sign in to comment.