diff --git a/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/checkoutConfiguration.js b/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/checkoutConfiguration.js index 92dd2d3a0..d26ffd95d 100644 --- a/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/checkoutConfiguration.js +++ b/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/checkoutConfiguration.js @@ -189,9 +189,8 @@ function getGiftCardConfig() { async: false, success: (data) => { giftcardBalance = data.balance; - document.querySelector( - 'button[value="submit-payment"]', - ).disabled = false; + document.querySelector('button[value="submit-payment"]').disabled = + false; if (data.resultCode === constants.SUCCESS) { const { giftCardsInfoMessageContainer, @@ -217,9 +216,8 @@ function getGiftCardConfig() { initialPartialObject.totalDiscountedAmount; }); - document.querySelector( - 'button[value="submit-payment"]', - ).disabled = true; + document.querySelector('button[value="submit-payment"]').disabled = + true; giftCardsInfoMessageContainer.innerHTML = ''; giftCardsInfoMessageContainer.classList.remove( 'gift-cards-info-message-container', @@ -274,7 +272,8 @@ function getGiftCardConfig() { } function handleOnChange(state) { - const { type } = state.data.paymentMethod; + const { paymentMethod } = state.data; + const { type } = paymentMethod; store.isValid = state.isValid; if (!store.componentsObj[type]) { store.componentsObj[type] = {}; diff --git a/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/renderGiftcardComponent.js b/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/renderGiftcardComponent.js index ed41bb58e..2f4401f6c 100644 --- a/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/renderGiftcardComponent.js +++ b/src/cartridges/app_adyen_SFRA/cartridge/client/default/js/adyen_checkout/renderGiftcardComponent.js @@ -96,9 +96,8 @@ function removeGiftCards() { giftCardsInfoMessageContainer.classList.remove( 'gift-cards-info-message-container', ); - document.querySelector( - 'button[value="submit-payment"]', - ).disabled = false; + document.querySelector('button[value="submit-payment"]').disabled = + false; if (res.resultCode === constants.RECEIVED) { document diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/__tests__/analyticsService.test.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/__tests__/analyticsService.test.js new file mode 100644 index 000000000..ccee8f27c --- /dev/null +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/__tests__/analyticsService.test.js @@ -0,0 +1,66 @@ +const { createCheckoutAttemptId } = require('../analyticsService'); + +const AdyenHelper = { + getApplicationInfo: jest.fn(), +}; + +const execute = jest.fn(); +const constants = { + SERVICE: { + ADYEN_ANALYTICS: 'ADYEN_ANALYTICS', + }, +}; + +const AdyenLogs = { + error_log: jest.fn(), +}; + +global.AdyenHelper = AdyenHelper; +global.execute = execute; +global.constants = constants; +global.AdyenLogs = AdyenLogs; + +describe('createCheckoutAttemptId', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return checkoutAttemptId when the execute function is successful', () => { + const mockCheckoutAttemptId = 'test-checkout-attempt-id'; + const mockApplicationInfo = { name: 'testApp' }; + + AdyenHelper.getApplicationInfo.mockReturnValue(mockApplicationInfo); + execute.mockReturnValue({ checkoutAttemptId: mockCheckoutAttemptId }); + + const result = createCheckoutAttemptId(); + + setTimeout(() => { + expect(AdyenHelper.getApplicationInfo).toHaveBeenCalled(); + expect(execute).toHaveBeenCalledWith(constants.SERVICE.ADYEN_ANALYTICS, { + applicationInfo: mockApplicationInfo, + channel: 'Web', + platform: 'Web', + }); + expect(result).toEqual({ data: mockCheckoutAttemptId }); + }, 0) + }); + + it('should return an error object and log error when execute throws an error', () => { + const mockError = new Error('Execution failed'); + AdyenHelper.getApplicationInfo.mockReturnValue({}); + execute.mockImplementation(() => { + throw mockError; + }); + + const result = createCheckoutAttemptId(); + + setTimeout(() => { + expect(AdyenHelper.getApplicationInfo).toHaveBeenCalled(); + expect(AdyenLogs.error_log).toHaveBeenCalledWith( + 'createCheckoutAttemptId for /analytics call failed:', + mockError + ); + expect(result).toEqual({ error: true }); + }, 0) + }); +}); \ No newline at end of file diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsEvents.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsEvents.js index 9a613d530..172b57f58 100644 --- a/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsEvents.js +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsEvents.js @@ -21,6 +21,8 @@ function createAnalyticsEvent( customObj.custom.eventType = eventType; customObj.custom.eventStatus = eventStatus; customObj.custom.eventCode = eventCode; + customObj.custom.processingStatus = + constants.processingStatus.NOT_PROCESSED; }); } diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsService.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsService.js index 7818994c4..317fa75a9 100644 --- a/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsService.js +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/analyticsService.js @@ -1,24 +1,52 @@ +const UUIDUtils = require('dw/util/UUIDUtils'); + const AdyenHelper = require('*/cartridge/adyen/utils/adyenHelper'); +const AdyenConfigs = require('*/cartridge/adyen/utils/adyenConfigs'); const constants = require('*/cartridge/adyen/config/constants'); const AdyenLogs = require('*/cartridge/adyen/logs/adyenCustomLogs'); +function execute(serviceType, requestObject, checkoutAttemptID = '') { + const service = AdyenHelper.getService(serviceType); + if (service === null) { + throw new Error(`Could not create ${serviceType} service object`); + } + + const clientKey = AdyenConfigs.getAdyenClientKey(); + let serviceUrl = service.getURL(); + serviceUrl += `/${checkoutAttemptID}?clientKey=${clientKey}`; + service.setURL(serviceUrl); + + const apiKey = AdyenConfigs.getAdyenApiKey(); + const uuid = UUIDUtils.createUUID(); + service.addHeader('Content-type', 'application/json'); + service.addHeader('charset', 'UTF-8'); + service.addHeader('X-API-KEY', apiKey); + service.addHeader('Idempotency-Key', uuid); + + const callResult = service.call(JSON.stringify(requestObject)); + if (!callResult.isOk()) { + throw new Error( + `${serviceType} service call error code${callResult + .getError() + .toString()} Error => ResponseStatus: ${callResult.getStatus()} | ResponseErrorText: ${callResult.getErrorMessage()} | ResponseText: ${callResult.getMsg()}`, + ); + } + + const parsedResponse = JSON.parse(callResult.object?.getText()); + return parsedResponse || callResult.status; +} + function createCheckoutAttemptId() { try { - const analyticsResponse = {}; const requestObject = { applicationInfo: AdyenHelper.getApplicationInfo(), channel: 'Web', platform: 'Web', }; - const response = AdyenHelper.executeCall( - constants.SERVICE.ADYEN_ANALYTICS, - requestObject, - ); - - analyticsResponse.attemptId = response.checkoutAttemptId; + const response = execute(constants.SERVICE.ADYEN_ANALYTICS, requestObject); - return analyticsResponse; + return { data: response.checkoutAttemptId }; } catch (error) { AdyenLogs.error_log( 'createCheckoutAttemptId for /analytics call failed:', @@ -32,19 +60,18 @@ function submitData(requestObject, attemptIdParam = null) { try { let attemptId = attemptIdParam; - // If attemptId is not provided as a parameter, generate it if (!attemptId) { const initialAnalyticsCall = createCheckoutAttemptId(); - attemptId = initialAnalyticsCall.attemptId; + attemptId = initialAnalyticsCall.data; } - const response = AdyenHelper.executeCall( + const response = execute( constants.SERVICE.ADYEN_ANALYTICS, requestObject, attemptId, ); - return response; + return { data: response }; } catch (error) { AdyenLogs.error_log('submitData for /analytics call failed:', error); return { error: true }; @@ -54,4 +81,5 @@ function submitData(requestObject, attemptIdParam = null) { module.exports = { createCheckoutAttemptId, submitData, + execute, }; diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/job/analyticsJob.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/job/analyticsJob.js index c1dc6e332..ead0f65cf 100644 --- a/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/job/analyticsJob.js +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/analytics/job/analyticsJob.js @@ -110,14 +110,13 @@ function processData() { ); const payload = createRequestObjectForAllReferenceIds(groupedObjects); - const submissionSuccess = AnalyticsService.submitData(payload); - if (submissionSuccess) { + const submission = AnalyticsService.submitData(payload); + if (submission.data) { customObjectsToDelete.forEach((customObject) => { deleteCustomObject(customObject); }); } else { AdyenLogs.error_log('Failed to submit full payload for grouped objects.'); - // This will be triggered upon completion of SFI-991 customObjectsToDelete.forEach((customObject) => { updateProcessingStatus( customObject, diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js index 6d294829d..675378e64 100644 --- a/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js @@ -926,7 +926,7 @@ let adyenHelperObj = { } }, - executeCall(serviceType, requestObject, checkoutAttemptID = '') { + executeCall(serviceType, requestObject = '') { const service = this.getService(serviceType); if (service === null) { throw new Error(`Could not create ${serviceType} service object`); @@ -938,13 +938,6 @@ let adyenHelperObj = { service.setURL(serviceUrl); } - if (serviceType === constants.SERVICE.ADYEN_ANALYTICS) { - const clientKey = AdyenConfigs.getAdyenClientKey(); - let serviceUrl = service.getURL(); - serviceUrl += `/${checkoutAttemptID}?clientKey=${clientKey}`; - service.setURL(serviceUrl); - } - const maxRetries = constants.MAX_API_RETRIES; const apiKey = AdyenConfigs.getAdyenApiKey(); const uuid = UUIDUtils.createUUID(); @@ -975,10 +968,15 @@ let adyenHelperObj = { if (!resultObject || !resultObject.getText()) { throw new Error(`No correct response from ${serviceType} service call`); } - // Once analytics executeCall is separated in SFI-991, this if condition can be removed - if (serviceType !== constants.SERVICE.ADYEN_ANALYTICS) { - analyticsEvent.createAnalyticsEvent(session.sessionID, serviceType, analyticsConstants.eventType.END, analyticsConstants.eventStatus.EXPECTED, analyticsConstants.eventCode.INFO); - } + + analyticsEvent.createAnalyticsEvent( + session.sessionID, + serviceType, + analyticsConstants.eventType.END, + analyticsConstants.eventStatus.EXPECTED, + analyticsConstants.eventCode.INFO + ); + return JSON.parse(resultObject.getText()); }, }; diff --git a/tests/playwright/package.json b/tests/playwright/package.json index 03eaaeec9..b79768534 100644 --- a/tests/playwright/package.json +++ b/tests/playwright/package.json @@ -106,7 +106,7 @@ "yazl": "^2.5.1" }, "devDependencies": { - "@playwright/test": "^1.42.1" + "@playwright/test": "^1.47.2" }, "scripts": { "test": "npx playwright test",