@notabene/javascript-sdk 2.0.4-NEXT.0 → 2.0.4-NEXT.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/notabene.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var w=Object.defineProperty;var I=(t,e,r)=>e in t?w(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var o=(t,e,r)=>I(t,typeof e!="symbol"?e+"":e,r);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var c=(t=>(t.PRIVATE="WALLET",t.VASP="VASP",t))(c||{}),m=(t=>(t.NATURAL="natural",t.LEGAL="legal",t.SELF="self",t))(m||{}),u=(t=>(t.EMPTY="empty",t.VERIFY="verify",t.PENDING="pending",t.VERIFIED="verified",t.BANNED="banned",t))(u||{}),E=(t=>(t.ALLOWED="allowed",t.PENDING="pending",t))(E||{}),f=(t=>(t.ASSET="asset",t.DESTINATION="destination",t.COUNTERPARTY="counterparty",t.AGENT="agent",t))(f||{}),a=(t=>(t.COMPLETE="complete",t.RESIZE="resize",t.RESULT="result",t.INVALID="invalid",t.ERROR="error",t.CANCEL="cancel",t))(a||{}),d=(t=>(t.UPDATE="update",t.REQUEST_RESPONSE="requestResponse",t))(d||{}),p=(t=>(t.PENDING="pending",t.FAILED="rejected",t.FLAGGED="flagged",t.VERIFIED="verified",t))(p||{}),v=(t=>(t.SelfDeclaration="self-declaration",t.SIWE="siwe",t.SIWX="siwx",t.EIP191="eip-191",t.EIP712="eip-712",t.EIP1271="eip-1271",t.BIP137="bip-137",t.BIP137_XPUB="xpub",t.ED25519="ed25519",t.MicroTransfer="microtransfer",t.Screenshot="screenshot",t.Connect="connect",t))(v||{});class C{constructor(){o(this,"listeners",new Map);o(this,"port");this.handleMessage=this.handleMessage.bind(this)}setPort(e){this.port=e,this.port.onmessage=this.handleMessage,this.port.start()}on(e,r){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(r),()=>this.off(e,r)}off(e,r){const i=this.listeners.get(e);i&&(i.delete(r),i.size===0&&this.listeners.delete(e))}handleMessage(e){const r=e.data;if(typeof r=="object"&&r!==null&&"type"in r){const i=r.type,s=this.listeners.get(i);s&&s.forEach(n=>n(r))}}send(e){this.port&&this.port.postMessage(e)}}class g{constructor(e,r,i){o(this,"_url");o(this,"_value");o(this,"_options");o(this,"_errors",[]);o(this,"iframe");o(this,"eventManager");o(this,"modal");this._url=e,this._value=r,this._options=i,this.eventManager=new C,this.on(a.INVALID,s=>{s.type===a.INVALID&&(this._errors=s.errors,this._value=s.value)}),this.on(a.RESIZE,s=>{s.type===a.RESIZE&&this.iframe&&(this.iframe.style.height=`${s.height}px`)})}get url(){return this._url}get value(){return this._value}get options(){return this._options}get errors(){return this._errors}open(){document.location.href=this.url}mount(e){const r=document.querySelector(e);if(!r)throw new Error(`parentID ${e} not found`);this.embed(r)}embed(e,r=!1){var i,s;this.removeEmbed(),this.iframe=document.createElement("iframe"),this.iframe.src=this.url+(r?"":"&embedded=true"),this.iframe.allow="web-share; clipboard-write; hid; bluetooth;",this.iframe.style.width="100%",this.iframe.style.height="0px",this.iframe.style.border="none",this.iframe.style.overflow="hidden",this.iframe.scrolling="no",e.appendChild(this.iframe),window.addEventListener("message",n=>{var l,h;n.source===((l=this.iframe)==null?void 0:l.contentWindow)&&((h=this.eventManager)==null||h.setPort(n.ports[0]))}),(s=(i=this.iframe)==null?void 0:i.contentWindow)==null||s.focus()}removeEmbed(){this.iframe&&this.iframe.remove()}send(e){this.eventManager.send(e)}on(e,r){return this.eventManager.on(e,r)}off(e,r){this.eventManager.off(e,r)}update(e,r){this._value=e,r&&(this._options=r),this.send({type:d.UPDATE,value:e,options:this._options})}completion(){return new Promise((e,r)=>{let i,s,n;function l(){i&&i(),s&&s(),n&&n()}i=this.on(a.COMPLETE,h=>{e(h.response),l()}),s=this.on(a.CANCEL,()=>{r(new Error("User cancelled")),l()}),n=this.on("error",h=>{r(new Error(h.message)),l()})})}openModal(){this.modal&&this.closeModal(),this.modal=document.createElement("dialog"),this.modal.style.border="none",this.modal.style.backgroundColor="white",this.modal.style.maxWidth="100vw",this.modal.style.maxHeight="100vh",this.modal.style.width="600px",this.modal.style.height="600px",document.body.appendChild(this.modal),this.embed(this.modal,!0);const e=this.on(a.CANCEL,()=>{this.closeModal()}),r=this.on(a.COMPLETE,()=>{this.closeModal()});return this.modal.showModal(),this.modal.addEventListener("click",()=>{this.closeModal()}),this.completion().finally(()=>{e(),r()})}closeModal(){var e;this.modal&&((e=this.modal)==null||e.close(),this.modal.remove(),this.modal=void 0)}popup(){const e=window.open(this.url,"_blank","popup=true");window.addEventListener("message",s=>{var n;s.source===e&&(console.log("received message from popup",s.data),(n=this.eventManager)==null||n.setPort(s.ports[0]))});const r=this.on(a.CANCEL,()=>{e==null||e.close()}),i=this.on(a.COMPLETE,()=>{e==null||e.close()});return this.completion().finally(()=>{r(),i()})}}function b(t){return Object.entries(t).map(([e,r])=>{if(r==null)return;const i=encodeURIComponent(e),s=encodeURIComponent(typeof r=="object"?JSON.stringify(r):String(r));return`${i}=${s}`}).filter(e=>e!==void 0).join("&")}function U(t){const e=t.slice(1);return e?e.split("&").filter(Boolean).reduce((i,s)=>{const[n,l]=s.split("=");return n&&(i[decodeURIComponent(n)]=l?decodeURIComponent(l):""),i},{}):{}}class L{constructor(e){o(this,"nodeUrl");o(this,"authToken");o(this,"uxUrl");o(this,"theme");o(this,"locale");this.uxUrl=e.uxUrl||"https://connect.notabene.id",this.nodeUrl=e.nodeUrl,this.authToken=e.authToken,this.theme=e.theme,this.locale=e.locale}componentUrl(e,r,i,s){const n=new URL(this.uxUrl);n.pathname=e;const l=b({authToken:this.authToken,value:r,configuration:i});return n.hash=l,this.nodeUrl&&n.searchParams.set("nodeUrl",this.nodeUrl),this.theme&&n.searchParams.set("theme",JSON.stringify(this.theme)),this.locale&&n.searchParams.set("locale",this.locale),s&&(s.callback&&n.searchParams.set("callback_url",s.callback),s.redirectUri&&n.searchParams.set("redirect_uri",s.redirectUri)),n.toString()}createComponent(e,r,i,s){return new g(this.componentUrl(e,r,i,s),r,i)}createWithdrawalAssist(e,r,i){return this.createComponent("withdrawal-assist",e,r,i)}createConnectWallet(e,r,i){return this.createComponent("connect",e,r,i)}createDepositRequest(e,r,i){return this.createComponent("deposit-request",e,r,i)}}exports.AgentType=c;exports.CMType=a;exports.EmbeddedComponent=g;exports.HMType=d;exports.PersonType=m;exports.ProofStatus=p;exports.ProofTypes=v;exports.Status=u;exports.VASPSearchControl=E;exports.ValidationSections=f;exports.decodeFragmentToObject=U;exports.default=L;
|
|
1
|
+
"use strict";var w=Object.defineProperty;var I=(t,e,r)=>e in t?w(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var o=(t,e,r)=>I(t,typeof e!="symbol"?e+"":e,r);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var c=(t=>(t.PRIVATE="WALLET",t.VASP="VASP",t))(c||{}),m=(t=>(t.NATURAL="natural",t.LEGAL="legal",t.SELF="self",t))(m||{}),u=(t=>(t.EMPTY="empty",t.VERIFY="verify",t.PENDING="pending",t.VERIFIED="verified",t.BANNED="banned",t))(u||{}),E=(t=>(t.ALLOWED="allowed",t.PENDING="pending",t))(E||{}),f=(t=>(t.ASSET="asset",t.DESTINATION="destination",t.COUNTERPARTY="counterparty",t.AGENT="agent",t))(f||{}),a=(t=>(t.COMPLETE="complete",t.RESIZE="resize",t.RESULT="result",t.INVALID="invalid",t.ERROR="error",t.CANCEL="cancel",t))(a||{}),d=(t=>(t.UPDATE="update",t.REQUEST_RESPONSE="requestResponse",t))(d||{}),p=(t=>(t.PENDING="pending",t.FAILED="rejected",t.FLAGGED="flagged",t.VERIFIED="verified",t))(p||{}),v=(t=>(t.SelfDeclaration="self-declaration",t.SIWE="siwe",t.SIWX="siwx",t.EIP191="eip-191",t.EIP712="eip-712",t.EIP1271="eip-1271",t.BIP137="bip-137",t.BIP137_XPUB="xpub",t.ED25519="ed25519",t.MicroTransfer="microtransfer",t.Screenshot="screenshot",t.Connect="connect",t))(v||{});class C{constructor(){o(this,"listeners",new Map);o(this,"port");this.handleMessage=this.handleMessage.bind(this)}setPort(e){this.port=e,this.port.onmessage=this.handleMessage,this.port.start()}on(e,r){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(r),()=>this.off(e,r)}off(e,r){const i=this.listeners.get(e);i&&(i.delete(r),i.size===0&&this.listeners.delete(e))}handleMessage(e){const r=e.data;if(typeof r=="object"&&r!==null&&"type"in r){const i=r.type,s=this.listeners.get(i);s&&s.forEach(n=>n(r))}}send(e){this.port&&this.port.postMessage(e)}}class g{constructor(e,r,i){o(this,"_url");o(this,"_value");o(this,"_options");o(this,"_errors",[]);o(this,"iframe");o(this,"eventManager");o(this,"modal");this._url=e,this._value=r,this._options=i,this.eventManager=new C,this.on(a.INVALID,s=>{s.type===a.INVALID&&(this._errors=s.errors,this._value=s.value)}),this.on(a.RESIZE,s=>{s.type===a.RESIZE&&this.iframe&&(this.iframe.style.height=`${s.height}px`)})}get url(){return this._url}get value(){return this._value}get options(){return this._options}get errors(){return this._errors}open(){document.location.href=this.url}mount(e){const r=document.querySelector(e);if(!r)throw new Error(`parentID ${e} not found`);this.embed(r)}embed(e,r=!1){var i,s;this.removeEmbed(),this.iframe=document.createElement("iframe"),this.iframe.src=this.url+(r?"":"&embedded=true"),this.iframe.allow="web-share; clipboard-write; hid; bluetooth;",this.iframe.style.width="100%",this.iframe.style.height="0px",this.iframe.style.border="none",this.iframe.style.overflow="hidden",this.iframe.scrolling="no",e.appendChild(this.iframe),window.addEventListener("message",n=>{var l,h;n.source===((l=this.iframe)==null?void 0:l.contentWindow)&&((h=this.eventManager)==null||h.setPort(n.ports[0]))}),(s=(i=this.iframe)==null?void 0:i.contentWindow)==null||s.focus()}removeEmbed(){this.iframe&&this.iframe.remove()}send(e){this.eventManager.send(e)}on(e,r){return this.eventManager.on(e,r)}off(e,r){this.eventManager.off(e,r)}update(e,r){this._value=e,r&&(this._options=r),this.send({type:d.UPDATE,value:e,options:this._options})}completion(){return new Promise((e,r)=>{let i,s,n;function l(){i&&i(),s&&s(),n&&n()}i=this.on(a.COMPLETE,h=>{e(h.response),l()}),s=this.on(a.CANCEL,()=>{r(new Error("User cancelled")),l()}),n=this.on("error",h=>{r(new Error(h.message)),l()})})}openModal(){this.modal&&this.closeModal(),this.modal=document.createElement("dialog"),this.modal.style.border="none",this.modal.style.backgroundColor="white",this.modal.style.maxWidth="100vw",this.modal.style.maxHeight="100vh",this.modal.style.width="600px",this.modal.style.height="600px",document.body.appendChild(this.modal),this.embed(this.modal,!0);const e=this.on(a.CANCEL,()=>{this.closeModal()}),r=this.on(a.COMPLETE,()=>{this.closeModal()});return this.modal.showModal(),this.modal.addEventListener("click",()=>{this.closeModal()}),this.completion().finally(()=>{e(),r()})}closeModal(){var e;this.modal&&((e=this.modal)==null||e.close(),this.modal.remove(),this.modal=void 0)}popup(){const e=window.open(this.url,"_blank","popup=true,width=600,height=600");window.addEventListener("message",s=>{var n;s.source===e&&(console.log("received message from popup",s.data),(n=this.eventManager)==null||n.setPort(s.ports[0]))});const r=this.on(a.CANCEL,()=>{e==null||e.close()}),i=this.on(a.COMPLETE,()=>{e==null||e.close()});return this.completion().finally(()=>{r(),i()})}}function b(t){return Object.entries(t).map(([e,r])=>{if(r==null)return;const i=encodeURIComponent(e),s=encodeURIComponent(typeof r=="object"?JSON.stringify(r):String(r));return`${i}=${s}`}).filter(e=>e!==void 0).join("&")}function U(t){const e=t.slice(1);return e?e.split("&").filter(Boolean).reduce((i,s)=>{const[n,l]=s.split("=");return n&&(i[decodeURIComponent(n)]=l?decodeURIComponent(l):""),i},{}):{}}class L{constructor(e){o(this,"nodeUrl");o(this,"authToken");o(this,"uxUrl");o(this,"theme");o(this,"locale");this.uxUrl=e.uxUrl||"https://connect.notabene.id",this.nodeUrl=e.nodeUrl,this.authToken=e.authToken,this.theme=e.theme,this.locale=e.locale}componentUrl(e,r,i,s){const n=new URL(this.uxUrl);n.pathname=e;const l=b({authToken:this.authToken,value:r,configuration:i});return n.hash=l,this.nodeUrl&&n.searchParams.set("nodeUrl",this.nodeUrl),this.theme&&n.searchParams.set("theme",JSON.stringify(this.theme)),this.locale&&n.searchParams.set("locale",this.locale),s&&(s.callback&&n.searchParams.set("callback_url",s.callback),s.redirectUri&&n.searchParams.set("redirect_uri",s.redirectUri)),n.toString()}createComponent(e,r,i,s){return new g(this.componentUrl(e,r,i,s),r,i)}createWithdrawalAssist(e,r,i){return this.createComponent("withdrawal-assist",e,r,i)}createConnectWallet(e,r,i){return this.createComponent("connect",e,r,i)}createDepositRequest(e,r,i){return this.createComponent("deposit-request",e,r,i)}}exports.AgentType=c;exports.CMType=a;exports.EmbeddedComponent=g;exports.HMType=d;exports.PersonType=m;exports.ProofStatus=p;exports.ProofTypes=v;exports.Status=u;exports.VASPSearchControl=E;exports.ValidationSections=f;exports.decodeFragmentToObject=U;exports.default=L;
|
package/dist/notabene.js
CHANGED
|
@@ -218,7 +218,11 @@ class C {
|
|
|
218
218
|
* @see [Cross-Origin-Opener-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy)
|
|
219
219
|
*/
|
|
220
220
|
popup() {
|
|
221
|
-
const e = window.open(
|
|
221
|
+
const e = window.open(
|
|
222
|
+
this.url,
|
|
223
|
+
"_blank",
|
|
224
|
+
"popup=true,width=600,height=600"
|
|
225
|
+
);
|
|
222
226
|
window.addEventListener("message", (s) => {
|
|
223
227
|
var n;
|
|
224
228
|
s.source === e && (console.log("received message from popup", s.data), (n = this.eventManager) == null || n.setPort(s.ports[0]));
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Notabene <developers@notabene.id>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"packageManager": "yarn@4.5.1",
|
|
13
|
-
"version": "2.0.4-NEXT.
|
|
13
|
+
"version": "2.0.4-NEXT.1",
|
|
14
14
|
"source": "src/notabene.ts",
|
|
15
15
|
"main": "dist/notabene.js",
|
|
16
16
|
"types": "dist/notabene.d.ts",
|
|
@@ -72,7 +72,6 @@
|
|
|
72
72
|
"lint-staged": {
|
|
73
73
|
"*.ts": [
|
|
74
74
|
"yarn format:check",
|
|
75
|
-
"organize-imports-cli",
|
|
76
75
|
"yarn lint:fix",
|
|
77
76
|
"yarn test --run"
|
|
78
77
|
]
|
|
@@ -253,7 +253,11 @@ export default class EmbeddedComponent<V, O> {
|
|
|
253
253
|
* @see [Cross-Origin-Opener-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy)
|
|
254
254
|
*/
|
|
255
255
|
public popup(): Promise<TransactionResponse<V>> {
|
|
256
|
-
const popup = window.open(
|
|
256
|
+
const popup = window.open(
|
|
257
|
+
this.url,
|
|
258
|
+
'_blank',
|
|
259
|
+
'popup=true,width=600,height=600',
|
|
260
|
+
);
|
|
257
261
|
window.addEventListener('message', (event: MessageEvent) => {
|
|
258
262
|
if (event.source !== popup) {
|
|
259
263
|
return;
|
|
@@ -1,653 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
AgentType,
|
|
4
|
-
CMType,
|
|
5
|
-
HMType,
|
|
6
|
-
type HostMessage,
|
|
7
|
-
type Transaction,
|
|
8
|
-
type TransactionOptions,
|
|
9
|
-
type Withdrawal,
|
|
10
|
-
} from '../../types';
|
|
11
|
-
import { MessageEventManager } from '../../utils/MessageEventManager';
|
|
12
|
-
import EmbeddedComponent from '../EmbeddedComponent';
|
|
13
|
-
|
|
14
|
-
const url = 'https://example.com';
|
|
15
|
-
const parentId = 'parent-container';
|
|
16
|
-
const value: Partial<Transaction> = { amountDecimal: 100 };
|
|
17
|
-
|
|
18
|
-
describe('EmbeddedComponent', () => {
|
|
19
|
-
describe('creation', () => {
|
|
20
|
-
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(url, {
|
|
23
|
-
amountDecimal: 100,
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test('sets value', () => {
|
|
28
|
-
expect(component.value).toStrictEqual(value);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('sets url', () => {
|
|
32
|
-
expect(component.url).toBe(url);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('iframe', () => {
|
|
37
|
-
let document: Document;
|
|
38
|
-
let parentElement: HTMLElement;
|
|
39
|
-
let iframe: HTMLIFrameElement;
|
|
40
|
-
let window: Window;
|
|
41
|
-
|
|
42
|
-
beforeEach(() => {
|
|
43
|
-
parentElement = {
|
|
44
|
-
appendChild: vi.fn(),
|
|
45
|
-
} as unknown as HTMLElement;
|
|
46
|
-
|
|
47
|
-
iframe = {
|
|
48
|
-
style: {},
|
|
49
|
-
src: '',
|
|
50
|
-
contentWindow: {
|
|
51
|
-
focus: vi.fn(),
|
|
52
|
-
} as unknown as Window,
|
|
53
|
-
remove: vi.fn(),
|
|
54
|
-
setAttribute: vi.fn(),
|
|
55
|
-
addEventListener: vi.fn(),
|
|
56
|
-
} as unknown as HTMLIFrameElement;
|
|
57
|
-
|
|
58
|
-
document = {
|
|
59
|
-
createElement: vi.fn().mockReturnValue(iframe),
|
|
60
|
-
querySelector: vi.fn().mockReturnValue(parentElement),
|
|
61
|
-
} as unknown as Document;
|
|
62
|
-
|
|
63
|
-
window = {
|
|
64
|
-
addEventListener: vi.fn(),
|
|
65
|
-
} as unknown as Window;
|
|
66
|
-
|
|
67
|
-
vi.stubGlobal('document', document);
|
|
68
|
-
vi.stubGlobal('window', window);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
afterEach(() => {
|
|
72
|
-
vi.unstubAllGlobals();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('mount', () => {
|
|
76
|
-
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
77
|
-
url,
|
|
78
|
-
value,
|
|
79
|
-
);
|
|
80
|
-
component.mount(parentId);
|
|
81
|
-
expect(iframe?.src).toBe(url + '&embedded=true');
|
|
82
|
-
expect(parentElement.appendChild).toHaveBeenCalledWith(iframe);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('on', () => {
|
|
86
|
-
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
87
|
-
url,
|
|
88
|
-
value,
|
|
89
|
-
);
|
|
90
|
-
const messageType = 'customEvent';
|
|
91
|
-
const callback = vi.fn();
|
|
92
|
-
component.on(messageType, callback);
|
|
93
|
-
component.mount(parentId);
|
|
94
|
-
|
|
95
|
-
// Simulate receiving a message of the specified type
|
|
96
|
-
// and assert that the callback is called with the correct payload.
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test('off', () => {
|
|
100
|
-
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
101
|
-
url,
|
|
102
|
-
value,
|
|
103
|
-
);
|
|
104
|
-
const messageType = 'customEvent';
|
|
105
|
-
const callback = vi.fn();
|
|
106
|
-
component.on(messageType, callback);
|
|
107
|
-
|
|
108
|
-
// Simulate receiving a message of the specified type
|
|
109
|
-
// and assert that the callback is called with the correct payload.
|
|
110
|
-
|
|
111
|
-
component.off(messageType, callback);
|
|
112
|
-
|
|
113
|
-
// Simulate receiving another message of the specified type
|
|
114
|
-
// and assert that the callback is not called.
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe('connected to iframe', () => {
|
|
118
|
-
let messageHandler: (event: MessageEvent) => void;
|
|
119
|
-
let port: MessagePort;
|
|
120
|
-
let handshake: MessageEvent;
|
|
121
|
-
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
122
|
-
let options: TransactionOptions;
|
|
123
|
-
|
|
124
|
-
beforeEach(() => {
|
|
125
|
-
port = {
|
|
126
|
-
postMessage: vi.fn(),
|
|
127
|
-
start: vi.fn(),
|
|
128
|
-
onmessage: null,
|
|
129
|
-
} as unknown as MessagePort;
|
|
130
|
-
handshake = {
|
|
131
|
-
source: iframe.contentWindow,
|
|
132
|
-
ports: [port],
|
|
133
|
-
} as unknown as MessageEvent;
|
|
134
|
-
window.addEventListener = vi
|
|
135
|
-
.fn()
|
|
136
|
-
.mockImplementation((event, handler) => {
|
|
137
|
-
messageHandler = handler;
|
|
138
|
-
});
|
|
139
|
-
options = { allowedAgentTypes: [AgentType.PRIVATE, AgentType.VASP] };
|
|
140
|
-
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
141
|
-
url,
|
|
142
|
-
value,
|
|
143
|
-
options,
|
|
144
|
-
);
|
|
145
|
-
component.mount(parentId);
|
|
146
|
-
|
|
147
|
-
expect(messageHandler).toBeDefined();
|
|
148
|
-
messageHandler(handshake);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test('send', () => {
|
|
152
|
-
const message: HostMessage<Withdrawal, TransactionOptions> = {
|
|
153
|
-
type: HMType.UPDATE,
|
|
154
|
-
value: {
|
|
155
|
-
requestId: 'id',
|
|
156
|
-
},
|
|
157
|
-
options: { allowedAgentTypes: [AgentType.PRIVATE] },
|
|
158
|
-
};
|
|
159
|
-
component.send(message);
|
|
160
|
-
expect(port.postMessage).toHaveBeenCalledWith(message);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
describe('update', () => {
|
|
164
|
-
test('with out options', () => {
|
|
165
|
-
const newValue: Partial<Transaction> = { amountDecimal: 200 };
|
|
166
|
-
|
|
167
|
-
const message: HostMessage<Withdrawal, TransactionOptions> = {
|
|
168
|
-
type: HMType.UPDATE,
|
|
169
|
-
value: newValue,
|
|
170
|
-
options,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
component.update(newValue);
|
|
174
|
-
|
|
175
|
-
expect(component.value).toBe(newValue);
|
|
176
|
-
expect(component.options).toBe(options);
|
|
177
|
-
expect(port.postMessage).toHaveBeenCalledWith(message);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
test('with options', () => {
|
|
181
|
-
const newValue: Partial<Transaction> = { amountDecimal: 200 };
|
|
182
|
-
const newOptions = { allowedAgentTypes: [AgentType.PRIVATE] };
|
|
183
|
-
|
|
184
|
-
const message: HostMessage<Withdrawal, TransactionOptions> = {
|
|
185
|
-
type: HMType.UPDATE,
|
|
186
|
-
value: newValue,
|
|
187
|
-
options: newOptions,
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
component.update(newValue, newOptions);
|
|
191
|
-
|
|
192
|
-
expect(component.value).toBe(newValue);
|
|
193
|
-
expect(component.options).toBe(newOptions);
|
|
194
|
-
expect(port.postMessage).toHaveBeenCalledWith(message);
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
// TODO not sure this actually does what I want it to do
|
|
198
|
-
describe('completion', () => {
|
|
199
|
-
test('resolves with response and cleans up listeners', async () => {
|
|
200
|
-
const response = { valid: true, value: 'completed' };
|
|
201
|
-
const completionPromise = component.completion();
|
|
202
|
-
|
|
203
|
-
port.onmessage!({
|
|
204
|
-
data: { type: CMType.COMPLETE, response },
|
|
205
|
-
} as unknown as MessageEvent);
|
|
206
|
-
|
|
207
|
-
const result = await completionPromise;
|
|
208
|
-
expect(result).toBe(response);
|
|
209
|
-
|
|
210
|
-
// Verify cleanup by sending another complete message - should not trigger anything
|
|
211
|
-
port.onmessage!({
|
|
212
|
-
data: { type: CMType.COMPLETE, response: { valid: false } },
|
|
213
|
-
} as unknown as MessageEvent);
|
|
214
|
-
|
|
215
|
-
// Original result should remain unchanged
|
|
216
|
-
expect(result).toBe(response);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
test('rejects with error and cleans up listeners', async () => {
|
|
220
|
-
const errorMessage = 'Test error';
|
|
221
|
-
const completionPromise = component.completion();
|
|
222
|
-
|
|
223
|
-
port.onmessage!({
|
|
224
|
-
data: { type: 'error', message: errorMessage },
|
|
225
|
-
} as unknown as MessageEvent);
|
|
226
|
-
|
|
227
|
-
await expect(completionPromise).rejects.toThrow(errorMessage);
|
|
228
|
-
|
|
229
|
-
// Verify cleanup by sending another error - should not trigger anything
|
|
230
|
-
port.onmessage!({
|
|
231
|
-
data: { type: 'error', message: 'Different error' },
|
|
232
|
-
} as unknown as MessageEvent);
|
|
233
|
-
|
|
234
|
-
// Original rejection should remain
|
|
235
|
-
await expect(completionPromise).rejects.toThrow(errorMessage);
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
describe('modal', () => {
|
|
242
|
-
let document: Document;
|
|
243
|
-
let dialog: HTMLDialogElement;
|
|
244
|
-
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
245
|
-
|
|
246
|
-
beforeEach(() => {
|
|
247
|
-
dialog = {
|
|
248
|
-
style: {},
|
|
249
|
-
showModal: vi.fn(),
|
|
250
|
-
close: vi.fn(),
|
|
251
|
-
remove: vi.fn(),
|
|
252
|
-
addEventListener: vi.fn(),
|
|
253
|
-
appendChild: vi.fn(), // Add this
|
|
254
|
-
} as unknown as HTMLDialogElement;
|
|
255
|
-
|
|
256
|
-
document = {
|
|
257
|
-
createElement: vi.fn().mockImplementation((tag) => {
|
|
258
|
-
if (tag === 'dialog') return dialog;
|
|
259
|
-
if (tag === 'iframe')
|
|
260
|
-
return {
|
|
261
|
-
style: {},
|
|
262
|
-
contentWindow: { focus: vi.fn() },
|
|
263
|
-
addEventListener: vi.fn(),
|
|
264
|
-
} as unknown as HTMLIFrameElement;
|
|
265
|
-
}),
|
|
266
|
-
body: {
|
|
267
|
-
appendChild: vi.fn(),
|
|
268
|
-
},
|
|
269
|
-
} as unknown as Document;
|
|
270
|
-
|
|
271
|
-
const mockDoc = document;
|
|
272
|
-
vi.stubGlobal('document', mockDoc); // Use intermediate variable
|
|
273
|
-
|
|
274
|
-
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
275
|
-
url,
|
|
276
|
-
value,
|
|
277
|
-
);
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
afterEach(() => {
|
|
281
|
-
vi.unstubAllGlobals();
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
test('modal closes on cancel message', async () => {
|
|
285
|
-
const completionPromise = component.openModal();
|
|
286
|
-
|
|
287
|
-
// Trigger cancel message through event manager
|
|
288
|
-
component['eventManager']['handleMessage']({
|
|
289
|
-
data: { type: CMType.CANCEL },
|
|
290
|
-
} as MessageEvent);
|
|
291
|
-
|
|
292
|
-
expect(dialog.close).toHaveBeenCalled();
|
|
293
|
-
expect(dialog.remove).toHaveBeenCalled();
|
|
294
|
-
|
|
295
|
-
// Add expectation for the rejection
|
|
296
|
-
await expect(completionPromise).rejects.toThrow('User cancelled');
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
test('modal closes on completion', async () => {
|
|
300
|
-
const completionPromise = component.openModal();
|
|
301
|
-
const response = { valid: true, value: 'completed' };
|
|
302
|
-
|
|
303
|
-
// Trigger complete message through event manager
|
|
304
|
-
component['eventManager']['handleMessage']({
|
|
305
|
-
data: { type: CMType.COMPLETE, response },
|
|
306
|
-
} as MessageEvent);
|
|
307
|
-
|
|
308
|
-
expect(dialog.close).toHaveBeenCalled();
|
|
309
|
-
expect(dialog.remove).toHaveBeenCalled();
|
|
310
|
-
await expect(completionPromise).resolves.toBe(response);
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
describe('error handling', () => {
|
|
315
|
-
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
316
|
-
let mockMessageManager: (typeof component)['eventManager'];
|
|
317
|
-
let document: Document;
|
|
318
|
-
let parentElement: HTMLElement;
|
|
319
|
-
|
|
320
|
-
beforeEach(() => {
|
|
321
|
-
parentElement = {
|
|
322
|
-
appendChild: vi.fn(),
|
|
323
|
-
} as unknown as HTMLElement;
|
|
324
|
-
|
|
325
|
-
document = {
|
|
326
|
-
createElement: vi.fn().mockReturnValue({
|
|
327
|
-
style: {},
|
|
328
|
-
contentWindow: { focus: vi.fn() },
|
|
329
|
-
} as unknown as HTMLIFrameElement),
|
|
330
|
-
querySelector: vi.fn().mockReturnValue(parentElement),
|
|
331
|
-
} as unknown as Document;
|
|
332
|
-
|
|
333
|
-
const mockDoc = document;
|
|
334
|
-
vi.stubGlobal('document', mockDoc);
|
|
335
|
-
|
|
336
|
-
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
337
|
-
url,
|
|
338
|
-
value,
|
|
339
|
-
);
|
|
340
|
-
mockMessageManager = component['eventManager'];
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
test('handles invalid messages', () => {
|
|
344
|
-
const errors = [{ attribute: 'test', message: 'error' }];
|
|
345
|
-
const newValue = { ...value, extra: 'data' };
|
|
346
|
-
|
|
347
|
-
mockMessageManager['handleMessage']({
|
|
348
|
-
data: {
|
|
349
|
-
type: CMType.INVALID,
|
|
350
|
-
errors,
|
|
351
|
-
value: newValue,
|
|
352
|
-
},
|
|
353
|
-
} as MessageEvent);
|
|
354
|
-
|
|
355
|
-
expect(component.errors).toEqual(errors);
|
|
356
|
-
expect(component.value).toEqual(newValue);
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
test('handles resize messages', () => {
|
|
360
|
-
const mockIframe = {
|
|
361
|
-
style: {},
|
|
362
|
-
contentWindow: { focus: vi.fn() },
|
|
363
|
-
} as unknown as HTMLIFrameElement;
|
|
364
|
-
|
|
365
|
-
document.createElement = vi.fn().mockReturnValue(mockIframe);
|
|
366
|
-
document.querySelector = vi.fn().mockReturnValue(parentElement);
|
|
367
|
-
|
|
368
|
-
component.mount(parentId);
|
|
369
|
-
|
|
370
|
-
mockMessageManager['handleMessage']({
|
|
371
|
-
data: {
|
|
372
|
-
type: CMType.RESIZE,
|
|
373
|
-
height: 500,
|
|
374
|
-
},
|
|
375
|
-
} as MessageEvent);
|
|
376
|
-
|
|
377
|
-
expect(mockIframe.style.height).toBe('500px');
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
describe('event management', () => {
|
|
382
|
-
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
383
|
-
let mockWindow: Window;
|
|
384
|
-
beforeEach(() => {
|
|
385
|
-
// Create a mock window without modifying global
|
|
386
|
-
mockWindow = {
|
|
387
|
-
addEventListener: vi.fn(),
|
|
388
|
-
dispatchEvent: vi.fn(),
|
|
389
|
-
} as unknown as Window;
|
|
390
|
-
|
|
391
|
-
vi.stubGlobal('window', mockWindow);
|
|
392
|
-
|
|
393
|
-
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
394
|
-
url,
|
|
395
|
-
value,
|
|
396
|
-
);
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
afterEach(() => {
|
|
400
|
-
vi.unstubAllGlobals();
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
test('multiple listeners for same event type', () => {
|
|
404
|
-
const callback1 = vi.fn();
|
|
405
|
-
const callback2 = vi.fn();
|
|
406
|
-
|
|
407
|
-
component.on('test', callback1);
|
|
408
|
-
component.on('test', callback2);
|
|
409
|
-
|
|
410
|
-
// Trigger message via component's event manager
|
|
411
|
-
component['eventManager']['handleMessage']({
|
|
412
|
-
data: { type: 'test', payload: 'data' },
|
|
413
|
-
} as MessageEvent);
|
|
414
|
-
|
|
415
|
-
expect(callback1).toHaveBeenCalled();
|
|
416
|
-
expect(callback2).toHaveBeenCalled();
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
test('removal of specific listener', () => {
|
|
420
|
-
const callback1 = vi.fn();
|
|
421
|
-
const callback2 = vi.fn();
|
|
422
|
-
|
|
423
|
-
component.on('test', callback1);
|
|
424
|
-
component.on('test', callback2);
|
|
425
|
-
component.off('test', callback1);
|
|
426
|
-
|
|
427
|
-
component['eventManager']['handleMessage']({
|
|
428
|
-
data: { type: 'test', payload: 'data' },
|
|
429
|
-
} as MessageEvent);
|
|
430
|
-
|
|
431
|
-
expect(callback1).not.toHaveBeenCalled();
|
|
432
|
-
expect(callback2).toHaveBeenCalled();
|
|
433
|
-
});
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
describe('cleanup', () => {
|
|
437
|
-
let mockIframe: HTMLIFrameElement;
|
|
438
|
-
let parentElement: HTMLElement;
|
|
439
|
-
let document: Document;
|
|
440
|
-
|
|
441
|
-
beforeEach(() => {
|
|
442
|
-
mockIframe = {
|
|
443
|
-
style: {},
|
|
444
|
-
src: '',
|
|
445
|
-
contentWindow: {
|
|
446
|
-
focus: vi.fn(),
|
|
447
|
-
} as unknown as Window,
|
|
448
|
-
remove: vi.fn(),
|
|
449
|
-
} as unknown as HTMLIFrameElement;
|
|
450
|
-
|
|
451
|
-
parentElement = {
|
|
452
|
-
appendChild: vi.fn(),
|
|
453
|
-
} as unknown as HTMLElement;
|
|
454
|
-
|
|
455
|
-
document = {
|
|
456
|
-
createElement: vi.fn().mockReturnValue(mockIframe),
|
|
457
|
-
querySelector: vi.fn().mockReturnValue(parentElement),
|
|
458
|
-
} as unknown as Document;
|
|
459
|
-
|
|
460
|
-
const mockDoc = document;
|
|
461
|
-
vi.stubGlobal('document', mockDoc);
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
afterEach(() => {
|
|
465
|
-
vi.unstubAllGlobals();
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
test('removeEmbed cleans up iframe', () => {
|
|
469
|
-
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
470
|
-
url,
|
|
471
|
-
value,
|
|
472
|
-
);
|
|
473
|
-
component.mount(parentId);
|
|
474
|
-
|
|
475
|
-
component.removeEmbed();
|
|
476
|
-
expect(mockIframe.remove).toHaveBeenCalled();
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
test('cleanup on unmount', () => {
|
|
480
|
-
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
481
|
-
url,
|
|
482
|
-
value,
|
|
483
|
-
);
|
|
484
|
-
const callback = vi.fn();
|
|
485
|
-
component.on('test', callback);
|
|
486
|
-
|
|
487
|
-
component.mount(parentId);
|
|
488
|
-
|
|
489
|
-
component.removeEmbed();
|
|
490
|
-
|
|
491
|
-
// Create a new event manager to simulate cleanup
|
|
492
|
-
component['eventManager'] = new MessageEventManager();
|
|
493
|
-
|
|
494
|
-
// Try to trigger message after cleanup
|
|
495
|
-
component['eventManager']['handleMessage']({
|
|
496
|
-
data: { type: 'test', payload: 'data' },
|
|
497
|
-
} as MessageEvent);
|
|
498
|
-
|
|
499
|
-
expect(callback).not.toHaveBeenCalled();
|
|
500
|
-
});
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
describe('state management', () => {
|
|
504
|
-
test('maintains value and options state', () => {
|
|
505
|
-
const initialValue = { amountDecimal: 100 };
|
|
506
|
-
const initialOptions = { allowedAgentTypes: [AgentType.PRIVATE] };
|
|
507
|
-
|
|
508
|
-
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
509
|
-
url,
|
|
510
|
-
initialValue,
|
|
511
|
-
initialOptions,
|
|
512
|
-
);
|
|
513
|
-
|
|
514
|
-
expect(component.value).toEqual(initialValue);
|
|
515
|
-
expect(component.options).toEqual(initialOptions);
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
test('updates maintain state consistency', () => {
|
|
519
|
-
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
520
|
-
url,
|
|
521
|
-
value,
|
|
522
|
-
);
|
|
523
|
-
const newValue = { amountDecimal: 200 };
|
|
524
|
-
const newOptions = { allowedAgentTypes: [AgentType.VASP] };
|
|
525
|
-
|
|
526
|
-
component.update(newValue, newOptions);
|
|
527
|
-
|
|
528
|
-
expect(component.value).toEqual(newValue);
|
|
529
|
-
expect(component.options).toEqual(newOptions);
|
|
530
|
-
});
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
describe('popup', () => {
|
|
534
|
-
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
535
|
-
let mockWindow: Window;
|
|
536
|
-
let popupWindow: Window;
|
|
537
|
-
|
|
538
|
-
beforeEach(() => {
|
|
539
|
-
popupWindow = {
|
|
540
|
-
close: vi.fn(),
|
|
541
|
-
} as unknown as Window;
|
|
542
|
-
|
|
543
|
-
mockWindow = {
|
|
544
|
-
open: vi.fn().mockReturnValue(popupWindow),
|
|
545
|
-
addEventListener: vi.fn(),
|
|
546
|
-
} as unknown as Window;
|
|
547
|
-
|
|
548
|
-
vi.stubGlobal('window', mockWindow);
|
|
549
|
-
|
|
550
|
-
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
551
|
-
url,
|
|
552
|
-
value,
|
|
553
|
-
);
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
afterEach(() => {
|
|
557
|
-
vi.unstubAllGlobals();
|
|
558
|
-
});
|
|
559
|
-
|
|
560
|
-
test('opens popup window with correct parameters', () => {
|
|
561
|
-
component.popup();
|
|
562
|
-
expect(mockWindow.open).toHaveBeenCalledWith(url, '_blank', 'popup=true');
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
test('popup closes on cancel message', async () => {
|
|
566
|
-
const completionPromise = component.popup();
|
|
567
|
-
|
|
568
|
-
// Trigger cancel message through event manager
|
|
569
|
-
component['eventManager']['handleMessage']({
|
|
570
|
-
data: { type: CMType.CANCEL },
|
|
571
|
-
} as MessageEvent);
|
|
572
|
-
|
|
573
|
-
expect(popupWindow.close).toHaveBeenCalled();
|
|
574
|
-
await expect(completionPromise).rejects.toThrow('User cancelled');
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
test('popup closes on completion', async () => {
|
|
578
|
-
const completionPromise = component.popup();
|
|
579
|
-
const response = { valid: true, value: 'completed' };
|
|
580
|
-
|
|
581
|
-
// Trigger complete message through event manager
|
|
582
|
-
component['eventManager']['handleMessage']({
|
|
583
|
-
data: { type: CMType.COMPLETE, response },
|
|
584
|
-
} as MessageEvent);
|
|
585
|
-
|
|
586
|
-
expect(popupWindow.close).toHaveBeenCalled();
|
|
587
|
-
await expect(completionPromise).resolves.toBe(response);
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
test('handles message events from popup window', async () => {
|
|
591
|
-
const completionPromise = component.popup(); // Store the promise
|
|
592
|
-
|
|
593
|
-
// Get the event listener callback
|
|
594
|
-
const messageHandler =
|
|
595
|
-
// @ts-expect-error TS is getting confused with the mock
|
|
596
|
-
(mockWindow.addEventListener as vi.Mock).mock.calls.find(
|
|
597
|
-
// @ts-expect-error TS is getting confused with the mock
|
|
598
|
-
(call) => call[0] === 'message',
|
|
599
|
-
)?.[1];
|
|
600
|
-
|
|
601
|
-
expect(messageHandler).toBeDefined();
|
|
602
|
-
|
|
603
|
-
// Mock a message event from the popup
|
|
604
|
-
const mockPort = { start: vi.fn() };
|
|
605
|
-
const mockEvent = {
|
|
606
|
-
source: popupWindow,
|
|
607
|
-
ports: [mockPort],
|
|
608
|
-
};
|
|
609
|
-
|
|
610
|
-
// Call the handler
|
|
611
|
-
messageHandler(mockEvent);
|
|
612
|
-
|
|
613
|
-
// Verify the port was set in the event manager
|
|
614
|
-
expect(component['eventManager']['port']).toBe(mockPort);
|
|
615
|
-
|
|
616
|
-
// Clean up by completing the promise
|
|
617
|
-
component['eventManager']['handleMessage']({
|
|
618
|
-
data: { type: CMType.COMPLETE, response: { valid: true } },
|
|
619
|
-
} as MessageEvent);
|
|
620
|
-
|
|
621
|
-
await completionPromise; // Wait for the promise to complete
|
|
622
|
-
});
|
|
623
|
-
|
|
624
|
-
test('ignores message events from other sources', async () => {
|
|
625
|
-
const completionPromise = component.popup();
|
|
626
|
-
|
|
627
|
-
const messageHandler =
|
|
628
|
-
// @ts-expect-error TS is getting confused with the mock
|
|
629
|
-
(mockWindow.addEventListener as vi.Mock).mock.calls.find(
|
|
630
|
-
// @ts-expect-error TS is getting confused with the mock
|
|
631
|
-
(call) => call[0] === 'message',
|
|
632
|
-
)?.[1];
|
|
633
|
-
|
|
634
|
-
// Mock a message event from a different source
|
|
635
|
-
const mockEvent = {
|
|
636
|
-
source: {} as Window,
|
|
637
|
-
ports: [{ start: vi.fn() }],
|
|
638
|
-
};
|
|
639
|
-
|
|
640
|
-
messageHandler(mockEvent);
|
|
641
|
-
|
|
642
|
-
// Verify the port was not set in the event manager
|
|
643
|
-
expect(component['eventManager']['port']).toBeUndefined();
|
|
644
|
-
|
|
645
|
-
// Clean up by completing the promise
|
|
646
|
-
component['eventManager']['handleMessage']({
|
|
647
|
-
data: { type: CMType.COMPLETE, response: { valid: true } },
|
|
648
|
-
} as MessageEvent);
|
|
649
|
-
|
|
650
|
-
await completionPromise; // Wait for the promise to complete
|
|
651
|
-
});
|
|
652
|
-
});
|
|
653
|
-
});
|