From 136e100f89d5c1038498f1e5254a9ac4b9a495f6 Mon Sep 17 00:00:00 2001 From: skyflow-sapanreddy Date: Tue, 17 Oct 2023 14:41:59 +0530 Subject: [PATCH] SK-1096 Fix domReady to use timeout --- package.json | 4 ---- src/core/internal/index.ts | 9 ++++---- src/utils/helpers/index.ts | 31 ++++++++++++++++++++++----- tests/utils/helpers.test.js | 42 +++++++++++++++++++++---------------- 4 files changed, 55 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 175ed5aa..e059803d 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, -<<<<<<< HEAD - "version": "1.31.0-dev.895b5a8", -======= "version": "1.31.1", ->>>>>>> 536327b ([AUTOMATED] Public Release - 1.31.1) "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", diff --git a/src/core/internal/index.ts b/src/core/internal/index.ts index c610ec32..d9c79cdc 100644 --- a/src/core/internal/index.ts +++ b/src/core/internal/index.ts @@ -286,12 +286,10 @@ export class FrameElement { this.options?.cardSeperator, ); this.iFrameFormElement.setMask(cardNumberMask as string[]); - this.applyMask(); } else if (this.iFrameFormElement.fieldType === ELEMENTS.EXPIRATION_MONTH.name || this.iFrameFormElement.fieldType === ELEMENTS.EXPIRATION_DATE.name) { if (this.domInput) { this.domInput.value = state.value || ''; - this.applyMask(); } } @@ -325,6 +323,9 @@ export class FrameElement { ) { this.updateStyleClasses(state); } + if (this.iFrameFormElement.mask) { + this.applyMask(); + } }); this.iFrameFormElement.on(ELEMENT_EVENTS_TO_IFRAME.SET_VALUE, (data) => { @@ -756,8 +757,7 @@ export class FrameElement { if (this.domLabel) this.domLabel.textContent = this.options.label; domReady(() => { - const id: any = this.domInput || `#${this.iFrameFormElement.iFrameName}`; - + const id: any = this.domInput; this.iFrameFormElement.setValidation(this.options.validations); this.iFrameFormElement.setReplacePattern(this.options.replacePattern); if (options.elementType === ElementType.EXPIRATION_DATE) { @@ -813,6 +813,7 @@ export class FrameElement { output = getMaskedOutput(value, mask[0], translation); if (this.domInput) { this.domInput.value = output; + if (!this.domInput.getAttribute('maxlength')) { this.domInput.setAttribute('maxlength', mask[0].length); } } if (output !== this.iFrameFormElement.getValue()) { this.iFrameFormElement.setValue(output); diff --git a/src/utils/helpers/index.ts b/src/utils/helpers/index.ts index d67e032a..86f30bb3 100644 --- a/src/utils/helpers/index.ts +++ b/src/utils/helpers/index.ts @@ -84,12 +84,33 @@ export const getReturnValue = (value: string | Blob, element: string, doesReturn } return undefined; }; + +const fns : Function[] = []; export function domReady(fn) { - if (document.readyState !== 'loading') { - fn(); - return; - } - document.addEventListener('DOMContentLoaded', fn); + (() => { + let listener; + const doc = typeof document === 'object' ? document : undefined; + const domContentLoaded = 'DOMContentLoaded'; + let loaded = doc && (/^loaded|^i|^c/).test(doc.readyState); + if (!loaded && doc) { + doc.addEventListener(domContentLoaded, listener = () => { + doc.removeEventListener(domContentLoaded, listener); + loaded = true; + listener = fns.shift(); + while (listener) { + listener(); + listener = fns.shift(); + } + }); + } + return (fun): void => { + if (loaded) { + setTimeout(fun, 0); + } else { + fns.push(fun); + } + }; + })()(fn); } export const getMaskedOutput = (input: string, format: string, translation: any): string => { diff --git a/tests/utils/helpers.test.js b/tests/utils/helpers.test.js index 9fc0ff53..413ffaeb 100644 --- a/tests/utils/helpers.test.js +++ b/tests/utils/helpers.test.js @@ -564,34 +564,40 @@ describe('test domReady function', () => { Object.defineProperty(document, "readyState", { get() { return pagestate; } }); + jest.useFakeTimers(); - test('should add function to eventListener DOMContentLoaded if readyState is loading', () => { + test('should not call function right away if readyState is loading', () => { const testSpyFunction = jest.fn(); - document.addEventListener = jest - .fn() - .mockImplementationOnce((event, callback) => { - callback(); - }); pagestate="loading"; - domReady(testSpyFunction); - expect(document.addEventListener).toBeCalledWith( - "DOMContentLoaded", - testSpyFunction - ); + jest.runAllTimers(); + expect(testSpyFunction).not.toBeCalled() }) test('should call function directly if readyState is not loading', () => { const testSpyFunction = jest.fn(); - document.addEventListener = jest - .fn() - .mockImplementationOnce((event, callback) => { - callback(); - }); pagestate="complete"; domReady(testSpyFunction); - expect(document.addEventListener).toBeCalledTimes(0) - expect(testSpyFunction).toBeCalled() + jest.runAllTimers(); + expect(testSpyFunction).toBeCalled() + }) + + test('should call multiple functions in sequence when page is loading',()=>{ + const testSpyFunction1 = jest.fn(); + const testSpyFunction2 = jest.fn(); + domReady(testSpyFunction1); + domReady(testSpyFunction2); + pagestate="loading"; + expect(testSpyFunction1).not.toBeCalled() + expect(testSpyFunction2).not.toBeCalled() + pagestate='complete' + window.document.dispatchEvent(new Event("DOMContentLoaded", { + bubbles: true, + cancelable: true + })); + jest.runAllTimers(); + expect(testSpyFunction1).toBeCalled() + expect(testSpyFunction2).toBeCalled() }) })