From a1a51e4af675320773c92e56e75615f3cc5c75d4 Mon Sep 17 00:00:00 2001 From: mayuran-deriv-dev96 Date: Mon, 16 Sep 2024 21:26:13 +0400 Subject: [PATCH 1/4] fix: test cases --- .../src/utils/__tests__/dom-observer.spec.ts | 36 +++++++++ .../src/utils/__tests__/gtm.spec.ts | 14 ++++ .../__tests__/xml-dom-quick-strategy.spec.ts | 81 +++++++++++++++++++ .../src/utils/xml-dom-quick-strategy.ts | 2 +- 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts create mode 100644 packages/bot-web-ui/src/utils/__tests__/xml-dom-quick-strategy.spec.ts diff --git a/packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts b/packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts new file mode 100644 index 000000000000..0d0b23eb952a --- /dev/null +++ b/packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts @@ -0,0 +1,36 @@ +import { waitForDomElement } from 'Utils/dom-observer'; + +describe('waitForDomElement', () => { + beforeEach(() => { + document.body.innerHTML = ''; + jest.clearAllMocks(); + }); + + test('should resolve immediately if the element is already in the DOM', async () => { + const elementId = 'testElement'; + const div = document.createElement('div'); + div.id = elementId; + document.body.appendChild(div); + const result = await waitForDomElement(`#${elementId}`); + + expect(result).toBeDefined(); + expect(result.id).toBe(elementId); + }); + + test('should resolve when the element is added to the DOM after some time', async () => { + const elementId = 'dynamicElement'; + + const promise = waitForDomElement(`#${elementId}`); + + setTimeout(() => { + const div = document.createElement('div'); + div.id = elementId; + document.body.appendChild(div); + }, 100); + + const result = await promise; + + expect(result).toBeDefined(); + expect(result.id).toBe(elementId); + }); +}); diff --git a/packages/bot-web-ui/src/utils/__tests__/gtm.spec.ts b/packages/bot-web-ui/src/utils/__tests__/gtm.spec.ts index 86d3f1314b5f..c06f8e75585c 100644 --- a/packages/bot-web-ui/src/utils/__tests__/gtm.spec.ts +++ b/packages/bot-web-ui/src/utils/__tests__/gtm.spec.ts @@ -59,6 +59,20 @@ describe('GTM Module', () => { ); }); + it('should directly push data layer', () => { + const mockPushDataLayer = jest.fn(); + mock_store.gtm.pushDataLayer = mockPushDataLayer; + + const sampleData = { + event: 'test_event', + data: { key: 'value' }, + }; + + GTM.pushDataLayer(sampleData); + + expect(mockPushDataLayer).toHaveBeenCalledWith(sampleData); + }); + it('should fail on sending null for init', () => { // eslint-disable-next-line no-console console.warn = jest.fn(); diff --git a/packages/bot-web-ui/src/utils/__tests__/xml-dom-quick-strategy.spec.ts b/packages/bot-web-ui/src/utils/__tests__/xml-dom-quick-strategy.spec.ts new file mode 100644 index 000000000000..5343ab9012a2 --- /dev/null +++ b/packages/bot-web-ui/src/utils/__tests__/xml-dom-quick-strategy.spec.ts @@ -0,0 +1,81 @@ +import { addDynamicBlockToDOM } from 'Utils/xml-dom-quick-strategy'; + +describe('addDynamicBlockToDOM', () => { + let strategyDom: HTMLElement; + + beforeEach(() => { + document.body.innerHTML = ` +
+ + + + +
+ `; + strategyDom = document.getElementById('strategy-dom')!; + }); + + afterEach(() => { + document.body.innerHTML = ''; + }); + + it('should add a block to the DOM when trade_type_cat is "digits"', () => { + addDynamicBlockToDOM('testBlock', 'testValue', 'digits', strategyDom); + + const valueBlock = document.querySelector('value[name="testBlock"]') as HTMLElement; + expect(valueBlock).not.toBeNull(); + expect(valueBlock).toHaveAttribute('strategy_value', 'testValue'); + + const shadowBlock = valueBlock.querySelector('shadow') as HTMLElement; + expect(shadowBlock).not.toBeNull(); + expect(shadowBlock).toHaveAttribute('type', 'math_number_positive'); + expect(shadowBlock).toHaveAttribute('id', 'p0O]7-M{ZORlORxGuIEb'); + + const fieldBlock = shadowBlock.querySelector('field') as HTMLElement; + expect(fieldBlock).not.toBeNull(); + expect(fieldBlock).toHaveAttribute('name', 'NUM'); + expect(fieldBlock).toHaveTextContent('0'); + + const amountBlock = strategyDom.querySelector('value[name="AMOUNT"]'); + const insertedBlock = amountBlock?.nextSibling as HTMLElement; + expect(insertedBlock).toBe(valueBlock); + }); + + it('should add a block to the DOM when trade_type_cat is "highlowticks"', () => { + addDynamicBlockToDOM('testBlockHighLow', 'testValueHighLow', 'highlowticks', strategyDom); + + const valueBlock = document.querySelector('value[name="testBlockHighLow"]') as HTMLElement; + expect(valueBlock).not.toBeNull(); + expect(valueBlock).toHaveAttribute('strategy_value', 'testValueHighLow'); + + const shadowBlock = valueBlock.querySelector('shadow') as HTMLElement; + expect(shadowBlock).not.toBeNull(); + expect(shadowBlock).toHaveAttribute('type', 'math_number_positive'); + expect(shadowBlock).toHaveAttribute('id', 'p0O]7-M{ZORlORxGuIEb'); + + const fieldBlock = shadowBlock.querySelector('field') as HTMLElement; + expect(fieldBlock).not.toBeNull(); + expect(fieldBlock).toHaveAttribute('name', 'NUM'); + expect(fieldBlock).toHaveTextContent('0'); + + const amountBlock = strategyDom.querySelector('value[name="AMOUNT"]'); + const insertedBlock = amountBlock?.nextSibling as HTMLElement; + expect(insertedBlock).toBe(valueBlock); + }); + + it('should set has_prediction attribute when name_block is "PREDICTION"', () => { + addDynamicBlockToDOM('PREDICTION', 'testValue', '', strategyDom); + + const mutationElement = strategyDom.querySelector( + 'block[type="trade_definition_tradeoptions"] > mutation' + ) as HTMLElement; + expect(mutationElement).not.toBeNull(); + expect(mutationElement).toHaveAttribute('has_prediction', 'true'); + }); + + it('should not modify DOM if strategy_dom is null', () => { + const initialDOM = document.body.innerHTML; + addDynamicBlockToDOM('testBlock', 'testValue', 'digits', null as unknown as HTMLElement); + expect(document.body.innerHTML).toBe(initialDOM); + }); +}); diff --git a/packages/bot-web-ui/src/utils/xml-dom-quick-strategy.ts b/packages/bot-web-ui/src/utils/xml-dom-quick-strategy.ts index 6c2bd6defa32..9a2d574f4ad9 100644 --- a/packages/bot-web-ui/src/utils/xml-dom-quick-strategy.ts +++ b/packages/bot-web-ui/src/utils/xml-dom-quick-strategy.ts @@ -20,7 +20,7 @@ export const addDynamicBlockToDOM = ( shadow_block.appendChild(field_block); block.appendChild(shadow_block); - const amount_block = strategy_dom.querySelector('value[name="AMOUNT"]'); + const amount_block = strategy_dom?.querySelector('value[name="AMOUNT"]'); if (amount_block) { const parent_node = amount_block.parentNode; if (parent_node) { From b96f68c5bdf9ffd01ae14fab1b61f8914e196c4c Mon Sep 17 00:00:00 2001 From: mayuran-deriv-dev96 Date: Tue, 17 Sep 2024 19:39:57 +0400 Subject: [PATCH 2/4] fix: test case download added --- .../src/utils/__tests__/download.spec.ts | 90 +++++++++++++++++++ packages/bot-web-ui/src/utils/download.ts | 2 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 packages/bot-web-ui/src/utils/__tests__/download.spec.ts diff --git a/packages/bot-web-ui/src/utils/__tests__/download.spec.ts b/packages/bot-web-ui/src/utils/__tests__/download.spec.ts new file mode 100644 index 000000000000..7644f840dced --- /dev/null +++ b/packages/bot-web-ui/src/utils/__tests__/download.spec.ts @@ -0,0 +1,90 @@ +import { LogTypes } from '@deriv/bot-skeleton'; +import { localize } from '@deriv/translations'; +import { getCurrentDateTimeLocale, getSuccessJournalMessage } from 'Utils/download'; + +jest.mock('@deriv/translations', () => ({ + localize: jest.fn((message, values) => { + let result = message; + if (values) { + Object.keys(values).forEach(key => { + result = result.replace(`{{${key}}}`, values[key]); + }); + } + return result; + }), +})); +jest.mock('@deriv/bot-skeleton', () => ({ + LogTypes: { + LOAD_BLOCK: 'load_block', + PURCHASE: 'purchase', + SELL: 'sell', + NOT_OFFERED: 'not_offered', + PROFIT: 'profit', + LOST: 'lost', + WELCOME_BACK: 'welcome_back', + WELCOME: 'welcome', + }, +})); +describe('getCurrentDateTimeLocale', () => { + it('should return the current date and time in UTC with the format YYYY-MM-DD HHMMSS', () => { + const result = getCurrentDateTimeLocale(); + const now = new Date(); + const year = now.getUTCFullYear(); + const month = (now.getUTCMonth() + 1).toString().padStart(2, '0'); + const day = now.getUTCDate().toString().padStart(2, '0'); + const hours = now.getUTCHours().toString().padStart(2, '0'); + const minutes = now.getUTCMinutes().toString().padStart(2, '0'); + const seconds = now.getUTCSeconds().toString().padStart(2, '0'); + const expected = `${year}-${month}-${day} ${hours}${minutes}${seconds}`; + expect(result).toBe(expected); + }); +}); +describe('getSuccessJournalMessage', () => { + it('should return localized message for LOAD_BLOCK', () => { + const result = getSuccessJournalMessage(LogTypes.LOAD_BLOCK, {}); + expect(result).toBe('Blocks are loaded successfully'); + }); + it('should return localized message for PURCHASE with longcode and transaction_id', () => { + const extra = { longcode: 'Sample Longcode', transaction_id: '1234' }; + const result = getSuccessJournalMessage(LogTypes.PURCHASE, extra); + expect(result).toBe('Bought: Sample Longcode (ID: 1234)'); + }); + it('should return localized message for SELL with sold_for', () => { + const extra = { sold_for: '100 USD' }; + const result = getSuccessJournalMessage(LogTypes.SELL, extra); + expect(result).toBe('Sold for: 100 USD'); + }); + it('should return localized message for PROFIT with profit', () => { + const extra = { profit: '50 USD' }; + const result = getSuccessJournalMessage(LogTypes.PROFIT, extra); + expect(result).toBe('Profit amount: 50 USD'); + }); + it('should return localized message for LOST with profit', () => { + const extra = { profit: '20 USD' }; + const result = getSuccessJournalMessage(LogTypes.LOST, extra); + expect(result).toBe('Loss amount: 20 USD'); + }); + it('should return localized message for WELCOME_BACK with current_currency', () => { + const extra = { current_currency: 'USD' }; + const result = getSuccessJournalMessage(LogTypes.WELCOME_BACK, extra); + expect(result).toBe('Welcome back! Your messages have been restored. You are using your USD account.'); + }); + it('should return localized message for WELCOME_BACK without current_currency', () => { + const extra = {}; // No current_currency provided + const result = getSuccessJournalMessage(LogTypes.WELCOME_BACK, extra); + expect(result).toBe('Welcome back! Your messages have been restored.'); + }); + it('should return localized message for WELCOME with current_currency', () => { + const extra = { current_currency: 'EUR' }; + const result = getSuccessJournalMessage(LogTypes.WELCOME, extra); + expect(result).toBe('You are using your EUR account.'); + }); + it('should return localized message for NOT_OFFERED with empty extra', () => { + const result = getSuccessJournalMessage(LogTypes.NOT_OFFERED, {}); + expect(result).toBe('Resale of this contract is not offered.'); + }); + it('should return empty string for unknown log type', () => { + const result = getSuccessJournalMessage('unknown_log_type' as LogTypes[keyof LogTypes], {}); + expect(result).toBe(''); + }); +}); diff --git a/packages/bot-web-ui/src/utils/download.ts b/packages/bot-web-ui/src/utils/download.ts index f3b79eb5928b..ac69514c5a1d 100644 --- a/packages/bot-web-ui/src/utils/download.ts +++ b/packages/bot-web-ui/src/utils/download.ts @@ -33,7 +33,7 @@ export type TExtra = { current_currency?: string; }; -const getCurrentDateTimeLocale = () => { +export const getCurrentDateTimeLocale = () => { const date = new Date(); // This will be the current date and time const year = date.getUTCFullYear(); From bf3210f03fd0f5409dc6c0e984da349739b862ac Mon Sep 17 00:00:00 2001 From: mayuran-deriv-dev96 Date: Thu, 19 Sep 2024 11:14:13 +0400 Subject: [PATCH 3/4] fix: pr comments --- packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts b/packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts index 0d0b23eb952a..a6e4483cbb30 100644 --- a/packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts +++ b/packages/bot-web-ui/src/utils/__tests__/dom-observer.spec.ts @@ -6,7 +6,7 @@ describe('waitForDomElement', () => { jest.clearAllMocks(); }); - test('should resolve immediately if the element is already in the DOM', async () => { + it('should resolve immediately if the element is already in the DOM', async () => { const elementId = 'testElement'; const div = document.createElement('div'); div.id = elementId; @@ -17,7 +17,7 @@ describe('waitForDomElement', () => { expect(result.id).toBe(elementId); }); - test('should resolve when the element is added to the DOM after some time', async () => { + it('should resolve when the element is added to the DOM after some time', async () => { const elementId = 'dynamicElement'; const promise = waitForDomElement(`#${elementId}`); From 1150cf69731466124d2ef8d473d25f5198df94e6 Mon Sep 17 00:00:00 2001 From: mayuran-deriv-dev96 Date: Tue, 24 Sep 2024 12:35:17 +0400 Subject: [PATCH 4/4] fix: comment --- .../bot-web-ui/src/utils/__tests__/download.spec.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/bot-web-ui/src/utils/__tests__/download.spec.ts b/packages/bot-web-ui/src/utils/__tests__/download.spec.ts index 7644f840dced..76cafac0c223 100644 --- a/packages/bot-web-ui/src/utils/__tests__/download.spec.ts +++ b/packages/bot-web-ui/src/utils/__tests__/download.spec.ts @@ -2,17 +2,6 @@ import { LogTypes } from '@deriv/bot-skeleton'; import { localize } from '@deriv/translations'; import { getCurrentDateTimeLocale, getSuccessJournalMessage } from 'Utils/download'; -jest.mock('@deriv/translations', () => ({ - localize: jest.fn((message, values) => { - let result = message; - if (values) { - Object.keys(values).forEach(key => { - result = result.replace(`{{${key}}}`, values[key]); - }); - } - return result; - }), -})); jest.mock('@deriv/bot-skeleton', () => ({ LogTypes: { LOAD_BLOCK: 'load_block',