diff --git a/src/core/spy/form-spy/form-spy.spec.ts b/src/core/spy/form-spy/form-spy.spec.ts new file mode 100644 index 0000000..21d337b --- /dev/null +++ b/src/core/spy/form-spy/form-spy.spec.ts @@ -0,0 +1,49 @@ +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import { FormSpy } from './form-spy'; + +class Observer { + public formInitHandler(): void { + return; + } +} + +describe('FormSpy', () => { + let formSpy: FormSpy; + + beforeEach(() => { + container.clearInstances(); + formSpy = container.createChildContainer().resolve(FormSpy); + }); + + it('Should return true for init form', () => { + formSpy.formWasInit = true; + expect(formSpy.formWasInit).toBeTrue(); + }); + + it('Should call formWasInitHandler', () => { + const observer = new Observer(); + const spy = spyOn(observer, 'formInitHandler'); + formSpy.listenFormInit(observer.formInitHandler); + formSpy.formWasInit = true; + expect(spy).toHaveBeenCalled(); + }); + + it('Should call formWasInitHandler once', () => { + const observer = new Observer(); + const spy = spyOn(observer, 'formInitHandler'); + formSpy.listenFormInit(observer.formInitHandler); + formSpy.formWasInit = true; + formSpy.formWasInit = true; + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('Should call appWasInitHandler once', () => { + const observer = new Observer(); + const spy = spyOn(observer, 'formInitHandler'); + formSpy.listenFormInit(observer.formInitHandler); + formSpy.formWasInit = true; + formSpy.formWasInit = false; + expect(spy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/core/spy/form-spy/form-spy.ts b/src/core/spy/form-spy/form-spy.ts new file mode 100644 index 0000000..be2be54 --- /dev/null +++ b/src/core/spy/form-spy/form-spy.ts @@ -0,0 +1,29 @@ +import { singleton } from 'tsyringe'; + +@singleton() +export class FormSpy { + private _formWasInit = false; + private readonly _callbacks: Array<() => void> = []; + + public set formWasInit(value: boolean) { + if (this._formWasInit === value) { + return; + } + this._formWasInit = value; + if (value) { + this.formWasInitHandler(); + } + } + + public get formWasInit(): boolean { + return this._formWasInit; + } + + public listenFormInit(callback: () => void): void { + this._callbacks.push(callback); + } + + private formWasInitHandler(): void { + this._callbacks.forEach((callback) => callback()); + } +} diff --git a/src/core/headless-checkout-spy/headless-checkout-spy.spec.ts b/src/core/spy/headless-checkout-spy/headless-checkout-spy.spec.ts similarity index 100% rename from src/core/headless-checkout-spy/headless-checkout-spy.spec.ts rename to src/core/spy/headless-checkout-spy/headless-checkout-spy.spec.ts diff --git a/src/core/headless-checkout-spy/headless-checkout-spy.ts b/src/core/spy/headless-checkout-spy/headless-checkout-spy.ts similarity index 100% rename from src/core/headless-checkout-spy/headless-checkout-spy.ts rename to src/core/spy/headless-checkout-spy/headless-checkout-spy.ts diff --git a/src/core/web-components/secure-component/secure-component.abstract.ts b/src/core/web-components/secure-component/secure-component.abstract.ts index 01e71c6..fa8e35d 100644 --- a/src/core/web-components/secure-component/secure-component.abstract.ts +++ b/src/core/web-components/secure-component/secure-component.abstract.ts @@ -2,9 +2,13 @@ import { WebComponentAbstract } from '../web-component.abstract'; import { headlessCheckoutAppUrl } from '../../../features/headless-checkout/environment'; export abstract class SecureComponentAbstract extends WebComponentAbstract { - protected abstract componentName: string; + protected componentName: string | null = null; protected getSecureHtml(): string { + if (!this.componentName) { + throw new Error('Component name is required'); + } + return ``; } } diff --git a/src/core/web-components/web-component-tag-name.enum.ts b/src/core/web-components/web-component-tag-name.enum.ts index 7234557..ac9918f 100644 --- a/src/core/web-components/web-component-tag-name.enum.ts +++ b/src/core/web-components/web-component-tag-name.enum.ts @@ -1,5 +1,5 @@ export enum WebComponentTagName { - CardNumberComponent = 'psdk-card-number', + TextComponent = 'psdk-text-component', SubmitButtonComponent = 'psdk-submit-button', PaymentMethodsComponent = 'psdk-payment-methods', LegalComponent = 'psdk-legal', diff --git a/src/core/web-components/web-components.map.ts b/src/core/web-components/web-components.map.ts index 62cc671..ec4472e 100644 --- a/src/core/web-components/web-components.map.ts +++ b/src/core/web-components/web-components.map.ts @@ -1,4 +1,4 @@ -import { CardNumberComponent } from '../../features/headless-checkout/web-components/card-number/card-number.component'; +import { TextComponent } from '../../features/headless-checkout/web-components/text-component/text.component'; import { SubmitButtonComponent } from '../../features/headless-checkout/web-components/submit-button/submit-button.component'; import { WebComponentTagName } from './web-component-tag-name.enum'; import { PaymentMethodsComponent } from '../../features/headless-checkout/web-components/payment-methods/payment-methods.component'; @@ -7,7 +7,7 @@ import { LegalComponent } from '../../features/headless-checkout/web-components/ export const webComponents: { [key in WebComponentTagName]: CustomElementConstructor; } = { - [WebComponentTagName.CardNumberComponent]: CardNumberComponent, + [WebComponentTagName.TextComponent]: TextComponent, [WebComponentTagName.SubmitButtonComponent]: SubmitButtonComponent, [WebComponentTagName.PaymentMethodsComponent]: PaymentMethodsComponent, [WebComponentTagName.LegalComponent]: LegalComponent, diff --git a/src/features/headless-checkout/headless-checkout.ts b/src/features/headless-checkout/headless-checkout.ts index e0100c6..ef748c3 100644 --- a/src/features/headless-checkout/headless-checkout.ts +++ b/src/features/headless-checkout/headless-checkout.ts @@ -14,13 +14,14 @@ import { SavedMethod } from '../../core/saved-method.interface'; import { getSavedMethodsHandler } from './post-messages-handlers/get-saved-methods.handler'; import { UserBalance } from '../../core/user-balance.interface'; import { getUserBalanceHandler } from './post-messages-handlers/get-user-balance.handler'; -import { HeadlessCheckoutSpy } from '../../core/headless-checkout-spy/headless-checkout-spy'; +import { HeadlessCheckoutSpy } from '../../core/spy/headless-checkout-spy/headless-checkout-spy'; import { getRegularMethodsHandler } from './post-messages-handlers/get-regular-methods.handler'; import { FormConfiguration } from '../../core/form/form-configuration.interface'; import { initFormHandler } from './post-messages-handlers/init-form.handler'; import { Form } from '../../core/form/form.interface'; import { NextAction } from '../../core/actions/next-action.interface'; import { nextActionHandler } from './post-messages-handlers/next-action.handler'; +import { FormSpy } from '../../core/spy/form-spy/form-spy'; @singleton() export class HeadlessCheckout { @@ -65,9 +66,8 @@ export class HeadlessCheckout { }, }; - return this.postMessagesClient.send