@elliemae/pui-app-bridge 2.23.6 → 2.24.0

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.
Files changed (61) hide show
  1. package/dist/cjs/appBridge.js +31 -1
  2. package/dist/cjs/e2e-host.html +505 -0
  3. package/dist/cjs/e2e-index.html +100 -0
  4. package/dist/cjs/index.html +51 -11
  5. package/dist/cjs/microfeHost.js +5 -1
  6. package/dist/esm/appBridge.js +31 -1
  7. package/dist/esm/e2e-host.html +505 -0
  8. package/dist/esm/e2e-index.html +100 -0
  9. package/dist/esm/index.html +51 -11
  10. package/dist/esm/microfeHost.js +5 -1
  11. package/dist/public/e2e-host.html +4 -0
  12. package/dist/public/e2e-host.js +7 -0
  13. package/dist/public/e2e-host.js.br +0 -0
  14. package/dist/public/e2e-host.js.gz +0 -0
  15. package/dist/public/e2e-host.js.map +1 -0
  16. package/dist/public/e2e-index.html +1 -0
  17. package/dist/public/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js +17 -0
  18. package/dist/public/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js.br +0 -0
  19. package/dist/public/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js.gz +0 -0
  20. package/dist/public/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js.map +1 -0
  21. package/dist/public/e2eIntermediateGuest/latest/manifest.json +3 -0
  22. package/dist/public/e2eTestGuest/latest/e2eTestGuest.checksum.js +48 -0
  23. package/dist/public/e2eTestGuest/latest/e2eTestGuest.checksum.js.br +0 -0
  24. package/dist/public/e2eTestGuest/latest/e2eTestGuest.checksum.js.gz +0 -0
  25. package/dist/public/e2eTestGuest/latest/e2eTestGuest.checksum.js.map +1 -0
  26. package/dist/public/e2eTestGuest/latest/manifest.json +3 -0
  27. package/dist/public/frame.html +1 -1
  28. package/dist/public/index.html +1 -1
  29. package/dist/public/js/{emuiAppBridge.cd5a9c6779f9aab2eec6.js → emuiAppBridge.5a6bc2ea1f03ee954a75.js} +8 -8
  30. package/dist/public/js/emuiAppBridge.5a6bc2ea1f03ee954a75.js.br +0 -0
  31. package/dist/public/js/emuiAppBridge.5a6bc2ea1f03ee954a75.js.gz +0 -0
  32. package/dist/public/js/emuiAppBridge.5a6bc2ea1f03ee954a75.js.map +1 -0
  33. package/dist/public/latest/app.config.json +20 -0
  34. package/dist/types/lib/typings/host.d.ts +7 -0
  35. package/dist/types/tsconfig.tsbuildinfo +1 -1
  36. package/dist/umd/e2e-host.html +4 -0
  37. package/dist/umd/e2e-host.js +7 -0
  38. package/dist/umd/e2e-host.js.br +0 -0
  39. package/dist/umd/e2e-host.js.gz +0 -0
  40. package/dist/umd/e2e-host.js.map +1 -0
  41. package/dist/umd/e2e-index.html +1 -0
  42. package/dist/umd/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js +17 -0
  43. package/dist/umd/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js.br +0 -0
  44. package/dist/umd/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js.gz +0 -0
  45. package/dist/umd/e2eIntermediateGuest/latest/e2eIntermediateGuest.checksum.js.map +1 -0
  46. package/dist/umd/e2eIntermediateGuest/latest/manifest.json +3 -0
  47. package/dist/umd/e2eTestGuest/latest/e2eTestGuest.checksum.js +48 -0
  48. package/dist/umd/e2eTestGuest/latest/e2eTestGuest.checksum.js.br +0 -0
  49. package/dist/umd/e2eTestGuest/latest/e2eTestGuest.checksum.js.gz +0 -0
  50. package/dist/umd/e2eTestGuest/latest/e2eTestGuest.checksum.js.map +1 -0
  51. package/dist/umd/e2eTestGuest/latest/manifest.json +3 -0
  52. package/dist/umd/index.html +1 -1
  53. package/dist/umd/index.js +7 -7
  54. package/dist/umd/index.js.br +0 -0
  55. package/dist/umd/index.js.gz +0 -0
  56. package/dist/umd/index.js.map +1 -1
  57. package/dist/umd/latest/app.config.json +20 -0
  58. package/package.json +4 -4
  59. package/dist/public/js/emuiAppBridge.cd5a9c6779f9aab2eec6.js.br +0 -0
  60. package/dist/public/js/emuiAppBridge.cd5a9c6779f9aab2eec6.js.gz +0 -0
  61. package/dist/public/js/emuiAppBridge.cd5a9c6779f9aab2eec6.js.map +0 -1
@@ -84,6 +84,10 @@ class CAppBridge {
84
84
  * list of active apps
85
85
  */
86
86
  #activeApps = /* @__PURE__ */ new Map();
87
+ /**
88
+ * host-supplied metadata per guest, keyed by app id
89
+ */
90
+ #guestMetadata = /* @__PURE__ */ new Map();
87
91
  /**
88
92
  * instance of the app registry
89
93
  */
@@ -417,6 +421,22 @@ class CAppBridge {
417
421
  } else if (this.#isFunction(propValue)) {
418
422
  Object.defineProperty(so, propName, {
419
423
  value: async (...args) => {
424
+ const callerCtx = so[propName]?.callContext;
425
+ if (callerCtx?.guest) {
426
+ const existingChain = callerCtx.callChain ?? [];
427
+ const guestId = callerCtx.guest.id;
428
+ const meta = this.#guestMetadata.get(guestId);
429
+ const callerEntry = { id: guestId };
430
+ if (meta) callerEntry.metadata = meta;
431
+ Object.defineProperty(propValue, "callContext", {
432
+ value: {
433
+ callChain: [...existingChain, callerEntry]
434
+ },
435
+ configurable: true,
436
+ enumerable: true,
437
+ writable: true
438
+ });
439
+ }
420
440
  const retVal = await propValue(...args);
421
441
  return (0, import_microfe_common.isScriptingObjectProxy)(retVal) ? this.cloneScriptingObject(retVal) : retVal;
422
442
  },
@@ -485,6 +505,7 @@ class CAppBridge {
485
505
  });
486
506
  }
487
507
  this.#activeApps.delete(instanceId);
508
+ this.#guestMetadata.delete(id);
488
509
  import_frame.Frame.remove(instanceId);
489
510
  }
490
511
  };
@@ -555,8 +576,17 @@ class CAppBridge {
555
576
  * @param {OpenAppParams} params - options to open guest application
556
577
  */
557
578
  openApp = async (params) => {
558
- const { id, frameOptions, history, theme, homeRoute, initialRoute } = params;
579
+ const {
580
+ id,
581
+ frameOptions,
582
+ history,
583
+ theme,
584
+ homeRoute,
585
+ initialRoute,
586
+ metadata
587
+ } = params;
559
588
  const instanceId = (0, import_uuid.v4)();
589
+ if (metadata) this.#guestMetadata.set(id, metadata);
560
590
  const appConfig = this.#microFEConfig.getConfigById(id);
561
591
  if (!appConfig) {
562
592
  throw new Error(`Application ${id} is not found in app config`);
@@ -0,0 +1,505 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>AppBridge E2E — Comprehensive Host Test</title>
7
+ <script src="https://cdn.tailwindcss.com?plugins=forms"></script>
8
+ <script src="https://cdn.mortgagetech.q1.ice.com/pui-diagnostics@3"></script>
9
+ </head>
10
+ <body class="bg-gray-50">
11
+ <header
12
+ class="bg-indigo-600 text-white px-4 py-3 flex items-center justify-between"
13
+ >
14
+ <h1 class="text-lg font-semibold">
15
+ AppBridge E2E — Comprehensive Host Test
16
+ </h1>
17
+ <a
18
+ href="./e2e-index.html"
19
+ class="text-indigo-200 hover:text-white text-sm"
20
+ >&larr; Back to dashboard</a
21
+ >
22
+ </header>
23
+
24
+ <main class="mx-auto max-w-7xl px-4 py-4">
25
+ <!-- Instructions -->
26
+ <div class="bg-blue-50 border border-blue-200 rounded-md p-3 mb-4">
27
+ <h2 class="text-sm font-bold text-blue-900 mb-1">
28
+ How to Use This Page
29
+ </h2>
30
+ <ol class="text-xs text-blue-800 list-decimal ml-4 space-y-1">
31
+ <li>Wait for <strong>"E2E Host ready"</strong> in the Event Log.</li>
32
+ <li>Use buttons in each section to test AppBridge features.</li>
33
+ <li>Check Event Log and result panels for expected output.</li>
34
+ <li>Work through the Verification Checklist at the bottom.</li>
35
+ </ol>
36
+ </div>
37
+
38
+ <div class="grid grid-cols-3 gap-4">
39
+ <!-- Column 1: Controls -->
40
+ <div class="col-span-2 space-y-4">
41
+ <!-- App Loading -->
42
+ <div class="bg-white rounded-lg shadow p-4">
43
+ <h2 class="text-sm font-semibold text-gray-700 mb-2">
44
+ App Loading
45
+ </h2>
46
+ <div class="flex flex-wrap gap-2">
47
+ <button
48
+ data-testid="btn-open-app"
49
+ id="btnOpenApp"
50
+ class="rounded bg-indigo-600 px-3 py-1 text-xs text-white hover:bg-indigo-700"
51
+ >
52
+ Open App (pricingservice)
53
+ </button>
54
+ <button
55
+ data-testid="btn-open-credit"
56
+ id="btnOpenCredit"
57
+ class="rounded bg-indigo-600 px-3 py-1 text-xs text-white hover:bg-indigo-700"
58
+ >
59
+ Open App (creditservice)
60
+ </button>
61
+ <button
62
+ data-testid="btn-open-validation"
63
+ id="btnOpenValidation"
64
+ class="rounded bg-indigo-600 px-3 py-1 text-xs text-white hover:bg-indigo-700"
65
+ >
66
+ Open App (loanvalidation)
67
+ </button>
68
+ <button
69
+ data-testid="btn-open-with-metadata"
70
+ id="btnOpenWithMetadata"
71
+ class="rounded bg-purple-600 px-3 py-1 text-xs text-white hover:bg-purple-700"
72
+ >
73
+ Open App with Metadata
74
+ </button>
75
+ <button
76
+ data-testid="btn-open-e2e-guest"
77
+ id="btnOpenE2EGuest"
78
+ class="rounded bg-teal-600 px-3 py-1 text-xs text-white hover:bg-teal-700"
79
+ >
80
+ Open E2E Test Guest
81
+ </button>
82
+ <button
83
+ data-testid="btn-open-nested-chain"
84
+ id="btnOpenNestedChain"
85
+ class="rounded bg-orange-600 px-3 py-1 text-xs text-white hover:bg-orange-700"
86
+ >
87
+ Open Nested Chain (A→B→C)
88
+ </button>
89
+ </div>
90
+ <p class="text-xs text-gray-400 mt-1">
91
+ <strong>Expected:</strong> App loads into the container below. Log
92
+ shows "openApp" succeeded. The E2E Test Guest provides interactive
93
+ buttons to test guest→host communication. The Nested Chain (A→B→C)
94
+ opens an intermediate that clones Loan and re-exposes it to a
95
+ grandchild — use C's buttons to verify callChain propagation on
96
+ Host A.
97
+ </p>
98
+ </div>
99
+
100
+ <!-- Scripting Object Management -->
101
+ <div class="bg-white rounded-lg shadow p-4">
102
+ <h2 class="text-sm font-semibold text-gray-700 mb-2">
103
+ Scripting Object Management
104
+ </h2>
105
+ <div class="flex flex-wrap gap-2">
106
+ <button
107
+ data-testid="btn-add-so"
108
+ id="btnAddSO"
109
+ class="rounded bg-green-600 px-3 py-1 text-xs text-white hover:bg-green-700"
110
+ >
111
+ Add "Inventory" Object
112
+ </button>
113
+ <button
114
+ data-testid="btn-remove-so"
115
+ id="btnRemoveSO"
116
+ class="rounded bg-red-600 px-3 py-1 text-xs text-white hover:bg-red-700"
117
+ >
118
+ Remove "Inventory" Object
119
+ </button>
120
+ <button
121
+ data-testid="btn-remove-all-so"
122
+ id="btnRemoveAllSO"
123
+ class="rounded bg-red-600 px-3 py-1 text-xs text-white hover:bg-red-700"
124
+ >
125
+ Remove All Objects
126
+ </button>
127
+ </div>
128
+ <p class="text-xs text-gray-400 mt-1">
129
+ <strong>Expected:</strong> Add succeeds. Remove succeeds. Guest
130
+ apps can/cannot call removed objects.
131
+ </p>
132
+ </div>
133
+
134
+ <!-- Event Dispatching -->
135
+ <div class="bg-white rounded-lg shadow p-4">
136
+ <h2 class="text-sm font-semibold text-gray-700 mb-2">
137
+ Event Dispatching
138
+ </h2>
139
+ <div class="flex flex-wrap gap-2">
140
+ <button
141
+ data-testid="btn-dispatch-presave"
142
+ id="btnDispatchPreSave"
143
+ class="rounded bg-yellow-600 px-3 py-1 text-xs text-white hover:bg-yellow-700"
144
+ >
145
+ Dispatch onPreSave (all apps)
146
+ </button>
147
+ <button
148
+ data-testid="btn-dispatch-amount"
149
+ id="btnDispatchAmount"
150
+ class="rounded bg-yellow-600 px-3 py-1 text-xs text-white hover:bg-yellow-700"
151
+ >
152
+ Dispatch onLoanAmountChanged
153
+ </button>
154
+ <button
155
+ data-testid="btn-dispatch-term"
156
+ id="btnDispatchTerm"
157
+ class="rounded bg-yellow-600 px-3 py-1 text-xs text-white hover:bg-yellow-700"
158
+ >
159
+ Dispatch onLoanTermChanged
160
+ </button>
161
+ </div>
162
+ <div
163
+ data-testid="dispatch-result"
164
+ id="dispatchResult"
165
+ class="mt-2 text-xs bg-gray-100 rounded p-2 min-h-[40px]"
166
+ >
167
+ Dispatch results appear here...
168
+ </div>
169
+ </div>
170
+
171
+ <!-- callContext Display -->
172
+ <div class="bg-white rounded-lg shadow p-4">
173
+ <h2 class="text-sm font-semibold text-gray-700 mb-2">
174
+ callContext (from last scripting object invocation)
175
+ </h2>
176
+ <div class="grid grid-cols-2 gap-2">
177
+ <div>
178
+ <h3 class="text-xs font-medium text-gray-500 mb-1">
179
+ callContext.guest
180
+ </h3>
181
+ <pre
182
+ data-testid="call-context-guest"
183
+ id="callContextGuest"
184
+ class="text-xs bg-gray-100 rounded p-2 min-h-[30px] whitespace-pre-wrap"
185
+ >
186
+ Waiting for invocation...</pre
187
+ >
188
+ </div>
189
+ <div>
190
+ <h3 class="text-xs font-medium text-gray-500 mb-1">
191
+ callContext.callChain
192
+ </h3>
193
+ <pre
194
+ data-testid="call-context-chain"
195
+ id="callContextChain"
196
+ class="text-xs bg-gray-100 rounded p-2 min-h-[30px] whitespace-pre-wrap"
197
+ >
198
+ Waiting for invocation...</pre
199
+ >
200
+ </div>
201
+ </div>
202
+ </div>
203
+
204
+ <!-- Lifecycle -->
205
+ <div class="bg-white rounded-lg shadow p-4">
206
+ <h2 class="text-sm font-semibold text-gray-700 mb-2">
207
+ App Lifecycle
208
+ </h2>
209
+ <div class="flex flex-wrap gap-2">
210
+ <button
211
+ data-testid="btn-close-app"
212
+ id="btnCloseApp"
213
+ class="rounded bg-red-600 px-3 py-1 text-xs text-white hover:bg-red-700"
214
+ >
215
+ Close First App
216
+ </button>
217
+ <button
218
+ data-testid="btn-close-all"
219
+ id="btnCloseAll"
220
+ class="rounded bg-red-800 px-3 py-1 text-xs text-white hover:bg-red-900"
221
+ >
222
+ Close All Apps
223
+ </button>
224
+ <button
225
+ data-testid="btn-list-apps"
226
+ id="btnListApps"
227
+ class="rounded bg-gray-600 px-3 py-1 text-xs text-white hover:bg-gray-700"
228
+ >
229
+ List Apps
230
+ </button>
231
+ </div>
232
+ <pre
233
+ data-testid="app-list"
234
+ id="appList"
235
+ class="mt-2 text-xs bg-gray-100 rounded p-2 min-h-[30px] whitespace-pre-wrap"
236
+ >
237
+ (no apps)</pre
238
+ >
239
+ </div>
240
+ </div>
241
+
242
+ <!-- Column 2: App container + Event Log -->
243
+ <div class="space-y-4">
244
+ <div class="bg-white rounded-lg shadow p-3">
245
+ <h2 class="text-sm font-semibold text-gray-700 mb-2">
246
+ Guest App Container
247
+ </h2>
248
+ <div
249
+ data-testid="app-container"
250
+ id="appContainer"
251
+ class="border-2 border-dashed border-indigo-300 rounded-lg"
252
+ style="height: 700px; overflow: auto"
253
+ ></div>
254
+ </div>
255
+
256
+ <div class="bg-white rounded-lg shadow p-3">
257
+ <div class="flex justify-between items-center mb-2">
258
+ <h2 class="text-sm font-semibold text-gray-700">Event Log</h2>
259
+ <button
260
+ data-testid="btn-clear-log"
261
+ id="btnClearLog"
262
+ class="rounded bg-gray-200 px-2 py-0.5 text-xs text-gray-600 hover:bg-gray-300"
263
+ >
264
+ Clear
265
+ </button>
266
+ </div>
267
+ <div
268
+ data-testid="event-log"
269
+ id="eventLog"
270
+ class="text-xs bg-gray-100 rounded p-2 min-h-[200px] max-h-[400px] overflow-y-auto"
271
+ ></div>
272
+ </div>
273
+ </div>
274
+ </div>
275
+
276
+ <!-- Verification Checklist -->
277
+ <div class="bg-gray-100 border border-gray-300 rounded-md p-3 mt-4">
278
+ <h2 class="text-sm font-bold text-gray-800 mb-2">
279
+ Verification Checklist
280
+ </h2>
281
+ <div class="grid grid-cols-2 gap-2 text-xs">
282
+ <label class="flex items-start gap-2">
283
+ <input type="checkbox" class="mt-0.5" />
284
+ <span
285
+ ><strong>TC-APP-01:</strong> openApp loads pricingservice into
286
+ container, log shows mounted</span
287
+ >
288
+ </label>
289
+ <label class="flex items-start gap-2">
290
+ <input type="checkbox" class="mt-0.5" />
291
+ <span
292
+ ><strong>TC-APP-02:</strong> openApp loads creditservice into
293
+ container</span
294
+ >
295
+ </label>
296
+ <label class="flex items-start gap-2">
297
+ <input type="checkbox" class="mt-0.5" />
298
+ <span
299
+ ><strong>TC-APP-03:</strong> openApp loads loanvalidation into
300
+ container</span
301
+ >
302
+ </label>
303
+ <label class="flex items-start gap-2">
304
+ <input type="checkbox" class="mt-0.5" />
305
+ <span
306
+ ><strong>TC-APP-04:</strong> openApp with metadata — metadata
307
+ stored for callChain</span
308
+ >
309
+ </label>
310
+ <label class="flex items-start gap-2">
311
+ <input type="checkbox" class="mt-0.5" />
312
+ <span
313
+ ><strong>TC-SO-01:</strong> Loan object registered on init (guest
314
+ apps can call getLoanDetails)</span
315
+ >
316
+ </label>
317
+ <label class="flex items-start gap-2">
318
+ <input type="checkbox" class="mt-0.5" />
319
+ <span
320
+ ><strong>TC-SO-02:</strong> Add Inventory object succeeds</span
321
+ >
322
+ </label>
323
+ <label class="flex items-start gap-2">
324
+ <input type="checkbox" class="mt-0.5" />
325
+ <span
326
+ ><strong>TC-SO-03:</strong> Remove Inventory object succeeds</span
327
+ >
328
+ </label>
329
+ <label class="flex items-start gap-2">
330
+ <input type="checkbox" class="mt-0.5" />
331
+ <span
332
+ ><strong>TC-SO-04:</strong> removeAllScriptingObjects clears
333
+ everything</span
334
+ >
335
+ </label>
336
+ <label class="flex items-start gap-2">
337
+ <input type="checkbox" class="mt-0.5" />
338
+ <span
339
+ ><strong>TC-SO-05:</strong> callContext.guest populated when guest
340
+ invokes scripting object method</span
341
+ >
342
+ </label>
343
+ <label class="flex items-start gap-2">
344
+ <input type="checkbox" class="mt-0.5" />
345
+ <span
346
+ ><strong>TC-SO-06:</strong> Loan.getLoanDetails returns expected
347
+ loan data</span
348
+ >
349
+ </label>
350
+ <label class="flex items-start gap-2">
351
+ <input type="checkbox" class="mt-0.5" />
352
+ <span
353
+ ><strong>TC-EVT-01:</strong> Dispatch onPreSave reaches all
354
+ subscribed apps, results returned</span
355
+ >
356
+ </label>
357
+ <label class="flex items-start gap-2">
358
+ <input type="checkbox" class="mt-0.5" />
359
+ <span
360
+ ><strong>TC-EVT-02:</strong> Dispatch onLoanAmountChanged reaches
361
+ subscribed apps</span
362
+ >
363
+ </label>
364
+ <label class="flex items-start gap-2">
365
+ <input type="checkbox" class="mt-0.5" />
366
+ <span
367
+ ><strong>TC-EVT-03:</strong> Dispatch onLoanTermChanged reaches
368
+ subscribed apps</span
369
+ >
370
+ </label>
371
+ <label class="flex items-start gap-2">
372
+ <input type="checkbox" class="mt-0.5" />
373
+ <span
374
+ ><strong>TC-LIFE-01:</strong> closeApp removes first app from
375
+ list</span
376
+ >
377
+ </label>
378
+ <label class="flex items-start gap-2">
379
+ <input type="checkbox" class="mt-0.5" />
380
+ <span
381
+ ><strong>TC-LIFE-02:</strong> List Apps shows all active apps with
382
+ instanceIds</span
383
+ >
384
+ </label>
385
+ <label class="flex items-start gap-2">
386
+ <input type="checkbox" class="mt-0.5" />
387
+ <span
388
+ ><strong>TC-LIFE-03:</strong> closeAllApps removes all apps</span
389
+ >
390
+ </label>
391
+ <label class="flex items-start gap-2">
392
+ <input type="checkbox" class="mt-0.5" />
393
+ <span
394
+ ><strong>TC-LIFE-04:</strong> No console errors during any
395
+ operation</span
396
+ >
397
+ </label>
398
+ <label class="flex items-start gap-2">
399
+ <input type="checkbox" class="mt-0.5" />
400
+ <span
401
+ ><strong>TC-META-01:</strong> openApp with metadata —
402
+ callContext.callChain contains metadata when guest invokes cloned
403
+ object</span
404
+ >
405
+ </label>
406
+ <label class="flex items-start gap-2">
407
+ <input type="checkbox" class="mt-0.5" />
408
+ <span
409
+ ><strong>TC-GUEST-01:</strong> Guest getObject("Loan") returns
410
+ proxy with expected methods (getLoanDetails, setCreditScore)</span
411
+ >
412
+ </label>
413
+ <label class="flex items-start gap-2">
414
+ <input type="checkbox" class="mt-0.5" />
415
+ <span
416
+ ><strong>TC-GUEST-02:</strong> Guest Loan.getLoanDetails() returns
417
+ loan data, host callContext.guest shows e2etestguest</span
418
+ >
419
+ </label>
420
+ <label class="flex items-start gap-2">
421
+ <input type="checkbox" class="mt-0.5" />
422
+ <span
423
+ ><strong>TC-GUEST-03:</strong> Guest Loan.setCreditScore(800)
424
+ returns {updated: true}, host callContext updates</span
425
+ >
426
+ </label>
427
+ <label class="flex items-start gap-2">
428
+ <input type="checkbox" class="mt-0.5" />
429
+ <span
430
+ ><strong>TC-GUEST-04:</strong> Guest getObject("Inventory")
431
+ returns proxy after host adds it; null before</span
432
+ >
433
+ </label>
434
+ <label class="flex items-start gap-2">
435
+ <input type="checkbox" class="mt-0.5" />
436
+ <span
437
+ ><strong>TC-GUEST-05:</strong> Guest Inventory.getItems() returns
438
+ item array</span
439
+ >
440
+ </label>
441
+ <label class="flex items-start gap-2">
442
+ <input type="checkbox" class="mt-0.5" />
443
+ <span
444
+ ><strong>TC-GUEST-06:</strong> Guest getObject("NonExistent")
445
+ returns null</span
446
+ >
447
+ </label>
448
+ <label class="flex items-start gap-2">
449
+ <input type="checkbox" class="mt-0.5" />
450
+ <span
451
+ ><strong>TC-GUEST-07:</strong> Guest subscribes to onPreSave —
452
+ receives event when host dispatches</span
453
+ >
454
+ </label>
455
+ <label class="flex items-start gap-2">
456
+ <input type="checkbox" class="mt-0.5" />
457
+ <span
458
+ ><strong>TC-GUEST-08:</strong> Guest subscribes to
459
+ onLoanAmountChanged — receives event when host dispatches</span
460
+ >
461
+ </label>
462
+ <label class="flex items-start gap-2">
463
+ <input type="checkbox" class="mt-0.5" />
464
+ <span
465
+ ><strong>TC-GUEST-09:</strong> Guest unsubscribe all — no more
466
+ events received after unsubscribe</span
467
+ >
468
+ </label>
469
+ <label class="flex items-start gap-2">
470
+ <input type="checkbox" class="mt-0.5" />
471
+ <span
472
+ ><strong>TC-CHAIN-01:</strong> Open Nested Chain — Intermediate B
473
+ loads, shows "CAppBridge B initialized"</span
474
+ >
475
+ </label>
476
+ <label class="flex items-start gap-2">
477
+ <input type="checkbox" class="mt-0.5" />
478
+ <span
479
+ ><strong>TC-CHAIN-02:</strong> Grandchild C (E2E Test Guest)
480
+ appears inside Intermediate B</span
481
+ >
482
+ </label>
483
+ <label class="flex items-start gap-2">
484
+ <input type="checkbox" class="mt-0.5" />
485
+ <span
486
+ ><strong>TC-CHAIN-03:</strong> In C: getObject("Loan") →
487
+ Loan.getLoanDetails() → Host A shows callContext.guest =
488
+ e2eintermediateguest, callChain = [{id: "e2etestguest", metadata:
489
+ {role: "grandchild", ...}}]</span
490
+ >
491
+ </label>
492
+ <label class="flex items-start gap-2">
493
+ <input type="checkbox" class="mt-0.5" />
494
+ <span
495
+ ><strong>TC-CHAIN-04:</strong> In C: Loan.setCreditScore(800) →
496
+ Host A callChain includes e2etestguest with metadata from B</span
497
+ >
498
+ </label>
499
+ </div>
500
+ </div>
501
+ </main>
502
+
503
+ <script src="./e2e-host.js" type="module"></script>
504
+ </body>
505
+ </html>
@@ -0,0 +1,100 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>AppBridge E2E Test Suite</title>
7
+ <script src="https://cdn.tailwindcss.com?plugins=forms"></script>
8
+ </head>
9
+ <body class="bg-gray-50">
10
+ <header class="bg-gray-900 text-white px-6 py-4">
11
+ <h1 class="text-xl font-bold">AppBridge End-to-End Test Suite</h1>
12
+ <p class="text-sm text-gray-400 mt-1">
13
+ Comprehensive blackbox tests for AppBridge (in-process micro-frontend
14
+ framework). Each page includes test steps, expected values, and a
15
+ verification checklist.
16
+ </p>
17
+ </header>
18
+
19
+ <main class="mx-auto max-w-5xl px-6 py-6">
20
+ <section
21
+ class="mb-6 bg-yellow-50 border border-yellow-200 rounded-lg p-4"
22
+ >
23
+ <h2 class="text-sm font-semibold text-yellow-800 mb-2">
24
+ Setup Instructions
25
+ </h2>
26
+ <ol class="text-xs text-yellow-700 list-decimal ml-4 space-y-1">
27
+ <li>
28
+ Install dependencies:
29
+ <code class="bg-yellow-100 px-1 rounded">pnpm install</code>
30
+ </li>
31
+ <li>
32
+ Start AppBridge dev server:
33
+ <code class="bg-yellow-100 px-1 rounded"
34
+ >cd libs/app-bridge && pnpm start</code
35
+ >
36
+ (default port 3000)
37
+ </li>
38
+ <li>
39
+ Open
40
+ <code class="bg-yellow-100 px-1 rounded"
41
+ >http://localhost:3000/e2e-index.html</code
42
+ >
43
+ in the browser
44
+ </li>
45
+ <li>
46
+ Each test page has
47
+ <code class="bg-yellow-100 px-1 rounded">data-testid</code>
48
+ attributes for Playwright/Cypress selectors
49
+ </li>
50
+ </ol>
51
+ </section>
52
+
53
+ <section class="mb-6">
54
+ <h2 class="text-lg font-semibold text-gray-800 border-b pb-1 mb-3">
55
+ 1. Core AppBridge Host Tests
56
+ </h2>
57
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
58
+ <a
59
+ href="./e2e-host.html"
60
+ data-testid="link-e2e-host"
61
+ class="block bg-white rounded-lg shadow p-4 hover:shadow-md transition"
62
+ >
63
+ <h3 class="font-medium text-indigo-700">Comprehensive E2E Host</h3>
64
+ <p class="text-xs text-gray-500 mt-1">
65
+ All host scenarios: openApp, closeApp, scripting objects, events,
66
+ lifecycle, metadata, callContext.
67
+ </p>
68
+ <p class="text-xs text-gray-400 mt-2">
69
+ <strong>What to verify:</strong> Apps open and mount into
70
+ containers. Scripting objects can be added/removed/invoked with
71
+ correct callContext. Events reach subscribed apps.
72
+ closeApp/closeAllApps cleans up properly.
73
+ </p>
74
+ <div class="mt-2 text-xs text-gray-400">
75
+ <strong>Test Cases:</strong>
76
+ TC-APP-01..04 &bull; TC-SO-01..06 &bull; TC-EVT-01..03 &bull;
77
+ TC-LIFE-01..04 &bull; TC-META-01
78
+ </div>
79
+ </a>
80
+ <a
81
+ href="./index.html"
82
+ data-testid="link-main-demo"
83
+ class="block bg-white rounded-lg shadow p-4 hover:shadow-md transition"
84
+ >
85
+ <h3 class="font-medium text-indigo-700">Main Demo App</h3>
86
+ <p class="text-xs text-gray-500 mt-1">
87
+ Original Loan Application demo with credit, pricing, and loan
88
+ validation micro-apps.
89
+ </p>
90
+ <p class="text-xs text-gray-400 mt-2">
91
+ <strong>What to verify:</strong> Loan form data flows to guest
92
+ apps. Events (onLoanAmountChanged, etc.) update guest UIs. Credit
93
+ score updates from guest. Save dispatches onPreSave with feedback.
94
+ </p>
95
+ </a>
96
+ </div>
97
+ </section>
98
+ </main>
99
+ </body>
100
+ </html>