@adobe/uix-core 0.7.0 → 0.7.1-nightly.20230115

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.
@@ -120,6 +120,199 @@ describe("function simulator exchanges functions and tickets", () => {
120
120
  await expect(loneFn()).resolves.not.toThrowError();
121
121
  expect(called).toBe(true);
122
122
  });
123
+ it("Unwraps prototypes and exchange all functions to tickets", async () => {
124
+ class ca {
125
+ pa: number;
126
+ constructor() {
127
+ this.pa = 4;
128
+ }
129
+ getPa() {
130
+ return this.pa;
131
+ }
132
+ }
133
+ class cb {
134
+ pb: number;
135
+ ca: ca;
136
+ constructor(aa: number) {
137
+ this.pb = aa;
138
+ this.ca = new ca();
139
+ }
140
+ getNumber() {
141
+ return this.pb;
142
+ }
143
+ giftOne() {
144
+ this.pb--;
145
+ }
146
+ }
147
+ class cd extends cb {
148
+ giftOne() {
149
+ this.pb++;
150
+ }
151
+ robOne() {
152
+ this.pb--;
153
+ }
154
+ }
155
+
156
+ const toBeTicketed = new cd(5);
157
+ const ticketed = objectSimulator.simulate(toBeTicketed);
158
+ expect(ticketed).toMatchInlineSnapshot(`
159
+ {
160
+ "ca": {
161
+ "getPa": {
162
+ "_\$pg": {
163
+ "fnId": "getPa_1",
164
+ },
165
+ },
166
+ "pa": 4,
167
+ },
168
+ "getNumber": {
169
+ "_\$pg": {
170
+ "fnId": "getNumber_4",
171
+ },
172
+ },
173
+ "giftOne": {
174
+ "_\$pg": {
175
+ "fnId": "giftOne_2",
176
+ },
177
+ },
178
+ "pb": 5,
179
+ "robOne": {
180
+ "_\$pg": {
181
+ "fnId": "robOne_3",
182
+ },
183
+ },
184
+ }
185
+ `);
186
+ const unticketed = objectSimulator.materialize(ticketed);
187
+ expect(unticketed).toMatchInlineSnapshot(`
188
+ {
189
+ "ca": {
190
+ "getPa": [Function],
191
+ "pa": 4,
192
+ },
193
+ "getNumber": [Function],
194
+ "giftOne": [Function],
195
+ "pb": 5,
196
+ "robOne": [Function],
197
+ }
198
+ `);
199
+
200
+ await expect(unticketed.getNumber()).resolves.toBe(5);
201
+ await unticketed.giftOne();
202
+ await expect(unticketed.getNumber()).resolves.toBe(6);
203
+ await unticketed.robOne();
204
+ await expect(unticketed.getNumber()).resolves.toBe(5);
205
+ await expect(unticketed.ca.getPa()).resolves.toBe(4);
206
+ });
207
+
208
+ it("Ignores circular dependencies in properties, but relove them through the methods", async () => {
209
+ class ca {
210
+ pa: ca;
211
+ constructor() {
212
+ this.pa = this;
213
+ }
214
+ getPa() {
215
+ return this.pa;
216
+ }
217
+ }
218
+
219
+ const toBeTicketed = new ca();
220
+ const ticketed = objectSimulator.simulate(toBeTicketed);
221
+ expect(ticketed).toMatchInlineSnapshot(`
222
+ {
223
+ "getPa": {
224
+ "_$pg": {
225
+ "fnId": "getPa_1",
226
+ },
227
+ },
228
+ "pa": "[[Circular]]",
229
+ }
230
+ `);
231
+ const unticketed = objectSimulator.materialize(ticketed);
232
+ expect(unticketed).toMatchInlineSnapshot(`
233
+ {
234
+ "getPa": [Function],
235
+ "pa": "[[Circular]]",
236
+ }
237
+ `);
238
+ expect(
239
+ Reflect.has(
240
+ await (await (await unticketed.getPa()).getPa()).getPa(),
241
+ "getPa"
242
+ )
243
+ ).toBeTruthy();
244
+ });
245
+ it("Supports classes wrapped in other classes", async () => {
246
+ class ca {
247
+ pa: number;
248
+ constructor() {
249
+ this.pa = 5;
250
+ }
251
+ getPa() {
252
+ return this.pa;
253
+ }
254
+ }
255
+ class cb {
256
+ pb: ca;
257
+ constructor() {
258
+ this.pb = new ca();
259
+ }
260
+ getCaValue() {
261
+ return this.pb.getPa();
262
+ }
263
+ }
264
+ const toBeTicketed = new cb();
265
+ const ticketed = objectSimulator.simulate(toBeTicketed);
266
+ expect(ticketed).toMatchInlineSnapshot(`
267
+ {
268
+ "getCaValue": {
269
+ "_$pg": {
270
+ "fnId": "getCaValue_2",
271
+ },
272
+ },
273
+ "pb": {
274
+ "getPa": {
275
+ "_$pg": {
276
+ "fnId": "getPa_1",
277
+ },
278
+ },
279
+ "pa": 5,
280
+ },
281
+ }
282
+ `);
283
+ const unticketed = objectSimulator.materialize(ticketed);
284
+ expect(unticketed).toMatchInlineSnapshot(`
285
+ {
286
+ "getCaValue": [Function],
287
+ "pb": {
288
+ "getPa": [Function],
289
+ "pa": 5,
290
+ },
291
+ }
292
+ `);
293
+ await expect(unticketed.pb.getPa()).resolves.toBe(5);
294
+ });
295
+
296
+ it("Supports objects with null prototypes", async () => {
297
+ const toBeTicketed = Object.create(null);
298
+ toBeTicketed["key1"] = "val1";
299
+ toBeTicketed["key2"] = "val2";
300
+ const ticketed = objectSimulator.simulate(toBeTicketed);
301
+ expect(ticketed).toMatchInlineSnapshot(`
302
+ {
303
+ "key1": "val1",
304
+ "key2": "val2",
305
+ }
306
+ `);
307
+ const unticketed = objectSimulator.materialize(ticketed);
308
+ expect(unticketed).toMatchInlineSnapshot(`
309
+ {
310
+ "key1": "val1",
311
+ "key2": "val2",
312
+ }
313
+ `);
314
+ });
315
+
123
316
  it("notifies remote when FinalizationRegistry calls cleanup handler", async () => {
124
317
  const willBeGCed = objectSimulator.simulate(() => {}) as DefMessage;
125
318
  objectSimulator.materialize(willBeGCed);
@@ -86,7 +86,7 @@ export class ObjectSimulator implements Simulator {
86
86
 
87
87
  // #region Public Methods
88
88
 
89
- makeReceiver(fn: CallableFunction) {
89
+ makeReceiver(fn: CallableFunction, parent?: Object) {
90
90
  if (typeof fn !== "function") {
91
91
  return NOT_TRANSFORMED;
92
92
  }
@@ -95,9 +95,18 @@ export class ObjectSimulator implements Simulator {
95
95
  fnTicket = {
96
96
  fnId: `${fn.name || "<anonymous>"}_${++this.fnCounter}`,
97
97
  };
98
- const cleanup = receiveCalls(fn, fnTicket, new WeakRef(this.subject));
98
+ // Bind function to parent object if it exists
99
+ let boundFunction = fn;
100
+ if (parent) {
101
+ boundFunction = fn.bind(parent);
102
+ }
103
+ const cleanup = receiveCalls(
104
+ boundFunction,
105
+ fnTicket,
106
+ new WeakRef(this.subject)
107
+ );
99
108
  this.subject.onOutOfScope(fnTicket, cleanup);
100
- this.receiverTicketCache.set(fn, fnTicket);
109
+ this.receiverTicketCache.set(boundFunction, fnTicket);
101
110
  }
102
111
  return wrap(fnTicket);
103
112
  }
@@ -5,6 +5,7 @@ import {
5
5
  isPlainObject,
6
6
  isPrimitive,
7
7
  isIterable,
8
+ isObjectWithPrototype,
8
9
  } from "./value-assertions";
9
10
 
10
11
  /**
@@ -58,35 +59,74 @@ export type Simulated<T> = {
58
59
  };
59
60
 
60
61
  export const NOT_TRANSFORMED = Symbol.for("NOT_TRANSFORMED");
62
+ export const CIRCULAR = "[[Circular]]";
61
63
 
62
64
  export function transformRecursive<To>(
63
- transform: (source: unknown) => To | typeof NOT_TRANSFORMED,
64
- value: unknown
65
+ transform: (source: unknown, parent?: Object) => To | typeof NOT_TRANSFORMED,
66
+ value: unknown,
67
+ parent?: Object,
68
+ _refs: WeakSet<object> = new WeakSet()
65
69
  ): To {
66
70
  if (isPrimitive(value)) {
67
71
  return value as To;
68
72
  }
69
- const transformed = transform(value);
73
+ const transformed = transform(value, parent);
70
74
  if (transformed !== NOT_TRANSFORMED) {
71
75
  return transformed;
72
76
  }
73
77
  if (isIterable(value)) {
74
78
  const outArray = [];
75
79
  for (const item of value) {
76
- outArray.push(transformRecursive(transform, item));
80
+ outArray.push(transformRecursive(transform, item, undefined, _refs));
77
81
  }
78
82
  return outArray as To;
79
83
  }
80
84
  if (isPlainObject(value)) {
85
+ if (_refs.has(value)) {
86
+ return CIRCULAR as To;
87
+ }
88
+ _refs.add(value);
81
89
  const outObj = {};
82
90
  for (const key of Reflect.ownKeys(value)) {
83
91
  Reflect.set(
84
92
  outObj,
85
93
  key,
86
- transformRecursive(transform, Reflect.get(value, key))
94
+ transformRecursive(transform, Reflect.get(value, key), undefined, _refs)
87
95
  );
88
96
  }
89
97
  return outObj as To;
90
98
  }
99
+ if (isObjectWithPrototype(value)) {
100
+ if (_refs.has(value)) {
101
+ return CIRCULAR as To;
102
+ }
103
+ _refs.add(value);
104
+ const getObjectKeys = (obj: Object): (string | symbol)[] => {
105
+ const result: Set<string | symbol> = new Set();
106
+ do {
107
+ if (Reflect.getPrototypeOf(obj) !== null) {
108
+ for (const prop of Object.getOwnPropertyNames(obj)) {
109
+ if (prop === "constructor") {
110
+ continue;
111
+ }
112
+ result.add(prop);
113
+ }
114
+ }
115
+ } while ((obj = Reflect.getPrototypeOf(obj)));
116
+
117
+ return [...result];
118
+ };
119
+ const outObj = {};
120
+ const properties = getObjectKeys(value);
121
+ for (const key of properties) {
122
+ Reflect.set(
123
+ outObj,
124
+ key,
125
+ transformRecursive(transform, Reflect.get(value, key), value, _refs)
126
+ );
127
+ }
128
+ return outObj as To;
129
+ }
130
+
91
131
  throw new Error(`Bad value! ${Object.prototype.toString.call(value)}`);
92
132
  }
@@ -0,0 +1,183 @@
1
+ import { NS_ROOT, VERSION } from "../constants";
2
+ import { TunnelMessenger } from "./tunnel-messenger";
3
+
4
+ const fakeConsole = {
5
+ error: jest.fn(),
6
+ warn: jest.fn(),
7
+ } as unknown as jest.Mocked<Console>;
8
+
9
+ describe("tunnel negotiation message factory", () => {
10
+ let messenger: TunnelMessenger;
11
+ beforeEach(() => {
12
+ messenger = new TunnelMessenger({
13
+ myOrigin: "https://me",
14
+ targetOrigin: "https://you",
15
+ logger: fakeConsole,
16
+ });
17
+ jest.clearAllMocks();
18
+ });
19
+ afterAll(() => {
20
+ jest.restoreAllMocks();
21
+ });
22
+ it("makeAccepted", () => {
23
+ expect(messenger.makeAccepted("test1")).toMatchObject({
24
+ [NS_ROOT]: {
25
+ accepts: "test1",
26
+ version: VERSION,
27
+ },
28
+ });
29
+ });
30
+ it("makeOffered", () => {
31
+ expect(messenger.makeOffered("test1")).toMatchObject({
32
+ [NS_ROOT]: {
33
+ offers: "test1",
34
+ version: VERSION,
35
+ },
36
+ });
37
+ });
38
+ it("isHandshakeOffer", () => {
39
+ expect(
40
+ messenger.isHandshakeOffer({
41
+ [NS_ROOT]: {
42
+ offers: "test2",
43
+ version: VERSION,
44
+ },
45
+ })
46
+ ).toBeTruthy();
47
+ expect(
48
+ messenger.isHandshakeOffer({
49
+ [NS_ROOT]: {
50
+ accepts: "test2",
51
+ version: VERSION,
52
+ },
53
+ })
54
+ ).toBeFalsy();
55
+ expect(messenger.isHandshakeOffer({})).toBeFalsy();
56
+ });
57
+ it("isHandshakeAccepting(message, id) matches on id", () => {
58
+ expect(
59
+ messenger.isHandshakeAccepting(
60
+ {
61
+ [NS_ROOT]: {
62
+ accepts: "test3",
63
+ version: VERSION,
64
+ },
65
+ },
66
+ "test3"
67
+ )
68
+ ).toBeTruthy();
69
+ expect(
70
+ messenger.isHandshakeAccepting(
71
+ {
72
+ accepts: "test3",
73
+ version: VERSION,
74
+ },
75
+ "mismatch"
76
+ )
77
+ ).toBeFalsy();
78
+ expect(messenger.isHandshakeAccepting({}, "test3")).toBeFalsy();
79
+ });
80
+ describe("isHandshake rejects malformed messages", () => {
81
+ it("non-plain-objects", () => {
82
+ expect(messenger.isHandshake([])).toBeFalsy();
83
+ expect(messenger.isHandshake("")).toBeFalsy();
84
+ expect(messenger.isHandshake(true)).toBeFalsy();
85
+ expect(fakeConsole.error).toHaveBeenCalledTimes(3);
86
+ expect(fakeConsole.error.mock.calls.map(([msg]) => msg))
87
+ .toMatchInlineSnapshot(`
88
+ [
89
+ "Malformed tunnel message sent from SDK at https://you to https://me:
90
+ []
91
+ Message must be an object with "_$pg" property, which must be an object with a "version" string and an either an "accepts" or "offers" property containing an ID string.",
92
+ "Malformed tunnel message sent from SDK at https://you to https://me:
93
+ ""
94
+ Message must be an object with "_$pg" property, which must be an object with a "version" string and an either an "accepts" or "offers" property containing an ID string.",
95
+ "Malformed tunnel message sent from SDK at https://you to https://me:
96
+ true
97
+ Message must be an object with "_$pg" property, which must be an object with a "version" string and an either an "accepts" or "offers" property containing an ID string.",
98
+ ]
99
+ `);
100
+ });
101
+ it("without a sub-object at the expected root property", () => {
102
+ expect(
103
+ messenger.isHandshakeOffer({
104
+ someOtherRoot: false,
105
+ })
106
+ ).toBeFalsy();
107
+ expect(
108
+ messenger.isHandshake({
109
+ [NS_ROOT]: 5,
110
+ })
111
+ ).toBeFalsy();
112
+ expect(fakeConsole.error.mock.calls.map(([msg]) => msg))
113
+ .toMatchInlineSnapshot(`
114
+ [
115
+ "Malformed tunnel message sent from SDK at https://you to https://me:
116
+ {
117
+ "someOtherRoot": false
118
+ }
119
+ Message must be an object with "_$pg" property, which must be an object with a "version" string and an either an "accepts" or "offers" property containing an ID string.",
120
+ "Malformed tunnel message sent from SDK at https://you to https://me:
121
+ {
122
+ "_$pg": 5
123
+ }
124
+ Message must be an object with "_$pg" property, which must be an object with a "version" string and an either an "accepts" or "offers" property containing an ID string.",
125
+ ]
126
+ `);
127
+ });
128
+ it("without accept or offers properties", () => {
129
+ expect(
130
+ messenger.isHandshake({
131
+ [NS_ROOT]: {
132
+ version: VERSION,
133
+ },
134
+ })
135
+ ).toBeFalsy();
136
+ });
137
+ it("with no version string", () => {
138
+ expect(
139
+ messenger.isHandshake({
140
+ [NS_ROOT]: {
141
+ offers: "test4",
142
+ },
143
+ })
144
+ ).toBeFalsy();
145
+ });
146
+ });
147
+ describe("version mismatch handling", () => {
148
+ const withVersion = (version: string) => ({
149
+ [NS_ROOT]: {
150
+ offers: "test5",
151
+ version,
152
+ },
153
+ });
154
+ it("warns in console, once for each version", () => {
155
+ expect(messenger.isHandshake(withVersion("bad-version"))).toBeTruthy();
156
+ expect(messenger.isHandshake(withVersion("worse-version"))).toBeTruthy();
157
+ expect(messenger.isHandshake(withVersion("bad-version"))).toBeTruthy();
158
+ expect(fakeConsole.warn).toHaveBeenCalledTimes(2);
159
+ expect(fakeConsole.warn.mock.calls.map(([msg]) => msg))
160
+ .toMatchInlineSnapshot(`
161
+ [
162
+ "SDK version mismatch. https://me is using v0.0.1-test, but received message from https://you using SDK vbad-version. Extensions may be broken or unresponsive.",
163
+ "SDK version mismatch. https://me is using v0.0.1-test, but received message from https://you using SDK vworse-version. Extensions may be broken or unresponsive.",
164
+ ]
165
+ `);
166
+ });
167
+ it("resetWarnings() resets seen version warnings so they'll log again", () => {
168
+ messenger.resetWarnings();
169
+ expect(
170
+ messenger.isHandshake(withVersion("same-bad-version"))
171
+ ).toBeTruthy();
172
+ expect(
173
+ messenger.isHandshake(withVersion("same-bad-version"))
174
+ ).toBeTruthy();
175
+ expect(fakeConsole.warn).toHaveBeenCalledTimes(1);
176
+ messenger.resetWarnings();
177
+ expect(
178
+ messenger.isHandshake(withVersion("same-bad-version"))
179
+ ).toBeTruthy();
180
+ expect(fakeConsole.warn).toHaveBeenCalledTimes(2);
181
+ });
182
+ });
183
+ });
@@ -0,0 +1,99 @@
1
+ import { NS_ROOT, VERSION } from "../constants";
2
+ import { isPlainObject } from "../value-assertions";
3
+ import { WrappedMessage, isWrapped, wrap, unwrap } from "../message-wrapper";
4
+ import { HandshakeAcceptedTicket, HandshakeOfferedTicket } from "../tickets";
5
+
6
+ type Handshake = HandshakeAcceptedTicket | HandshakeOfferedTicket;
7
+ type HandshakeAccepted = WrappedMessage<HandshakeAcceptedTicket>;
8
+ type HandshakeOffered = WrappedMessage<HandshakeOfferedTicket>;
9
+ type HandshakeMessage = HandshakeAccepted | HandshakeOffered;
10
+
11
+ export class TunnelMessenger {
12
+ private myOrigin: string;
13
+ private remoteOrigin: string;
14
+ private logger: Console;
15
+ private versionWarnings = new Set<string>();
16
+ constructor(opts: {
17
+ myOrigin: string;
18
+ targetOrigin: string;
19
+ logger: Console;
20
+ }) {
21
+ this.myOrigin = opts.myOrigin;
22
+ this.remoteOrigin =
23
+ opts.targetOrigin === "*" ? "remote document" : opts.targetOrigin;
24
+ this.logger = opts.logger;
25
+ }
26
+ resetWarnings() {
27
+ this.versionWarnings.clear();
28
+ }
29
+
30
+ makeAccepted(id: string): HandshakeAccepted {
31
+ return wrap({
32
+ accepts: id,
33
+ version: VERSION,
34
+ });
35
+ }
36
+ makeOffered(id: string): HandshakeOffered {
37
+ return wrap({
38
+ offers: id,
39
+ version: VERSION,
40
+ });
41
+ }
42
+ isHandshakeAccepting(
43
+ message: unknown,
44
+ id: string
45
+ ): message is HandshakeAccepted {
46
+ return (
47
+ this.isHandshake(message) &&
48
+ unwrap(message as HandshakeAccepted).accepts === id
49
+ );
50
+ }
51
+ isHandshakeOffer(message: unknown): message is HandshakeOffered {
52
+ return (
53
+ this.isHandshake(message) &&
54
+ typeof unwrap(message as HandshakeOffered).offers === "string"
55
+ );
56
+ }
57
+ isHandshake(message: unknown): message is HandshakeMessage {
58
+ if (!isWrapped(message)) {
59
+ this.logMalformed(message);
60
+ return false;
61
+ }
62
+ const tunnelData: Handshake = unwrap<Handshake>(
63
+ message as HandshakeMessage
64
+ );
65
+ if (
66
+ !isPlainObject(tunnelData) ||
67
+ typeof tunnelData.version !== "string" ||
68
+ !(Reflect.has(tunnelData, "accepts") || Reflect.has(tunnelData, "offers"))
69
+ ) {
70
+ this.logMalformed(message);
71
+ return false;
72
+ }
73
+ const { version } = tunnelData;
74
+ if (version !== VERSION && !this.versionWarnings.has(version)) {
75
+ this.versionWarnings.add(version);
76
+ this.logger.warn(
77
+ `SDK version mismatch. ${this.myOrigin} is using v${VERSION}, but received message from ${this.remoteOrigin} using SDK v${version}. Extensions may be broken or unresponsive.`
78
+ );
79
+ }
80
+ return true;
81
+ }
82
+ private logMalformed(message: unknown) {
83
+ let inspectedMessage: string;
84
+ try {
85
+ inspectedMessage = JSON.stringify(message, null, 2);
86
+ } catch (_) {
87
+ try {
88
+ inspectedMessage = message.toString();
89
+ } catch (e) {
90
+ inspectedMessage = Object.prototype.toString.call(message);
91
+ }
92
+ }
93
+ this.logger.error(
94
+ `Malformed tunnel message sent from SDK at ${this.remoteOrigin} to ${this.myOrigin}:
95
+ ${inspectedMessage}
96
+ Message must be an object with "${NS_ROOT}" property, which must be an object with a "version" string and an either an "accepts" or "offers" property containing an ID string.`
97
+ );
98
+ }
99
+ }
@@ -1,11 +1,17 @@
1
1
  import { fireEvent } from "@testing-library/dom";
2
2
  import { wait } from "../promises/wait";
3
3
  import { Tunnel } from "./tunnel";
4
- import { makeAccepted, makeOffered } from "./tunnel-message";
4
+ import { TunnelMessenger } from "./tunnel-messenger";
5
+
6
+ const fakeConsole = {
7
+ error: jest.fn(),
8
+ warn: jest.fn(),
9
+ } as unknown as jest.Mocked<Console>;
5
10
 
6
11
  const defaultTunnelConfig = {
7
12
  targetOrigin: "*",
8
13
  timeout: 4000,
14
+ logger: fakeConsole,
9
15
  };
10
16
  type TunnelHarness = { tunnel: Tunnel; port: MessagePort };
11
17
  const openPorts: MessagePort[] = [];
@@ -163,20 +169,26 @@ describe("static Tunnel.toIframe(iframe, options)", () => {
163
169
  let remoteTunnel: Tunnel;
164
170
  const connectMessageHandler = jest.fn();
165
171
  const acceptListener = jest.fn();
172
+ const targetOrigin = "https://example.com:4001";
166
173
  const loadedFrame = document.createElement("iframe");
167
- loadedFrame.src = "https://example.com:4001";
174
+ loadedFrame.src = targetOrigin;
168
175
  document.body.appendChild(loadedFrame);
169
176
  loadedFrame.contentWindow.addEventListener("message", acceptListener);
170
177
  const localTunnel = Tunnel.toIframe(loadedFrame, {
171
- targetOrigin: "https://example.com:4001",
178
+ targetOrigin,
172
179
  timeout: 9999,
173
180
  });
181
+ const messenger = new TunnelMessenger({
182
+ myOrigin: "https://example.com",
183
+ targetOrigin,
184
+ logger: fakeConsole,
185
+ });
174
186
  localTunnel.on("connected", connectMessageHandler);
175
187
  await wait(100);
176
188
  fireEvent(
177
189
  window,
178
190
  new MessageEvent("message", {
179
- data: makeOffered("iframe-test-1"),
191
+ data: messenger.makeOffered("iframe-test-1"),
180
192
  origin: loadedFrame.src,
181
193
  source: loadedFrame.contentWindow,
182
194
  })
@@ -184,7 +196,10 @@ describe("static Tunnel.toIframe(iframe, options)", () => {
184
196
  await wait(100);
185
197
  expect(acceptListener).toHaveBeenCalled();
186
198
  const acceptEvent = acceptListener.mock.lastCall[0];
187
- expect(acceptEvent).toHaveProperty("data", makeAccepted("iframe-test-1"));
199
+ expect(acceptEvent).toHaveProperty(
200
+ "data",
201
+ messenger.makeAccepted("iframe-test-1")
202
+ );
188
203
  expect(acceptEvent.ports).toHaveLength(1);
189
204
  remoteTunnel = new Tunnel(defaultTunnelConfig);
190
205
  remoteTunnel.connect(acceptEvent.ports[0]);