@bleedingdev/modern-js-boundary-debugger 3.9.0-ultramodern.6 → 3.9.0-ultramodern.7

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/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "directory": "packages/runtime/boundary-debugger"
12
12
  },
13
13
  "license": "MIT",
14
- "version": "3.9.0-ultramodern.6",
14
+ "version": "3.9.0-ultramodern.7",
15
15
  "engines": {
16
16
  "node": ">=26.7.0"
17
17
  },
@@ -36,7 +36,7 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.6"
39
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.7"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@rslib/core": "1.0.0",
@@ -272,11 +272,6 @@ describe('ultramodern boundary debugger browser overlay', () => {
272
272
  ).not.toBeNull();
273
273
  });
274
274
 
275
- const overlay = document.querySelector(
276
- '[data-modern-boundary-overlay-label="Checkout"]',
277
- ) as HTMLElement;
278
- expect(overlay.style.width).toBe('160px');
279
-
280
275
  rects.set('late-checkout', new DOMRect(24, 48, 220, 56));
281
276
  const boundaryObserver = resizeObservers.find(observer =>
282
277
  observer.elements.has(boundary),
@@ -294,4 +289,41 @@ describe('ultramodern boundary debugger browser overlay', () => {
294
289
  expect(resizedOverlay?.style.height).toBe('56px');
295
290
  });
296
291
  });
292
+ test('renders non-intrusive overlays naming the boundary owner and exposed module', async () => {
293
+ let WrappedApp: React.ComponentType | undefined;
294
+ ultramodernBoundaryDebuggerPlugin({
295
+ enabledByDefault: true,
296
+ metadata: {
297
+ appId: 'shell',
298
+ boundaries: [
299
+ { appId: 'checkout', label: 'Checkout', mfName: 'verticalCheckout' },
300
+ ],
301
+ schemaVersion: 1,
302
+ },
303
+ }).setup?.({
304
+ wrapRoot(factory: (App: React.ComponentType) => React.ComponentType) {
305
+ WrappedApp = factory(() => (
306
+ <main>
307
+ <section
308
+ data-modern-boundary-id="verticalCheckout"
309
+ data-modern-mf-expose="./Controls"
310
+ data-testid="checkout-control"
311
+ />
312
+ </main>
313
+ ));
314
+ },
315
+ } as any);
316
+ const App = WrappedApp!;
317
+ render(<App />);
318
+
319
+ await waitFor(() => {
320
+ const overlay = document.querySelector(
321
+ '[data-modern-boundary-overlay-label="Checkout"]',
322
+ ) as HTMLElement | null;
323
+ expect(overlay?.style.position).toBe('fixed');
324
+ expect(overlay?.style.pointerEvents).toBe('none');
325
+ expect(overlay?.textContent).toContain('Checkout');
326
+ expect(overlay?.textContent).toContain('./Controls');
327
+ });
328
+ });
297
329
  });
@@ -1,252 +0,0 @@
1
- import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
- import { createRequire } from 'node:module';
3
- import { tmpdir } from 'node:os';
4
- import path from 'node:path';
5
- import { pathToFileURL } from 'node:url';
6
- import { build } from 'esbuild';
7
-
8
- type BrowserType = {
9
- launch: (options?: Record<string, unknown>) => Promise<{
10
- close: () => Promise<void>;
11
- newPage: () => Promise<{
12
- click: (selector: string) => Promise<void>;
13
- evaluate: <T>(callback: () => T | Promise<T>) => Promise<T>;
14
- goto: (url: string) => Promise<unknown>;
15
- waitForFunction: (
16
- callback: () => boolean,
17
- arg?: unknown,
18
- options?: Record<string, unknown>,
19
- ) => Promise<unknown>;
20
- on: (event: string, handler: (value: any) => void) => void;
21
- }>;
22
- }>;
23
- };
24
-
25
- const requireFromRstestBrowserFixture = createRequire(
26
- path.resolve(
27
- __dirname,
28
- '../../../../../tests/integration/rstest/basic-app-rstest-browser/package.json',
29
- ),
30
- );
31
- const { chromium }: { chromium: BrowserType } =
32
- requireFromRstestBrowserFixture('playwright');
33
-
34
- describe('ultramodern boundary debugger chromium overlay', () => {
35
- test('keeps overlays out of layout and renders Checkout ownership inside Decide', async () => {
36
- const tempDir = mkdtempSync(
37
- path.join(tmpdir(), 'modern-boundary-debugger-'),
38
- );
39
- const entryPath = path.join(tempDir, 'entry.tsx');
40
- const bundlePath = path.join(tempDir, 'bundle.js');
41
- const htmlPath = path.join(tempDir, 'index.html');
42
-
43
- try {
44
- writeFileSync(
45
- entryPath,
46
- `import { runtime } from '@modern-js/plugin/runtime';
47
- import React from 'react';
48
- import { createRoot } from 'react-dom/client';
49
- import ultramodernBoundaryDebuggerPlugin from ${JSON.stringify(
50
- path.resolve(__dirname, '../../src/boundary-debugger/index.tsx'),
51
- )};
52
-
53
- globalThis.React = React;
54
-
55
- function App() {
56
- return (
57
- <main style={{ minHeight: 1600, padding: 48 }}>
58
- <button
59
- data-testid="primary-control"
60
- style={{ height: 44, width: 180 }}
61
- type="button"
62
- >
63
- Decide
64
- </button>
65
- <section
66
- data-modern-boundary-id="shellSuperApp"
67
- data-modern-mf-expose="./Decide"
68
- data-testid="decide-surface"
69
- style={{
70
- border: '1px solid #d1d5db',
71
- height: 260,
72
- marginTop: 48,
73
- padding: 36,
74
- width: 720,
75
- }}
76
- >
77
- <button
78
- data-modern-boundary-id="verticalCheckout"
79
- data-modern-mf-expose="./Controls"
80
- data-testid="checkout-control"
81
- style={{ height: 48, width: 220 }}
82
- type="button"
83
- >
84
- Pay now
85
- </button>
86
- </section>
87
- </main>
88
- );
89
- }
90
-
91
- const { runtimeContext } = runtime.run({
92
- config: {},
93
- plugins: [ultramodernBoundaryDebuggerPlugin({
94
- metadata: {
95
- appId: 'shell',
96
- boundaries: [
97
- {
98
- appId: 'shell',
99
- label: 'Decide',
100
- mfName: 'shellSuperApp',
101
- role: 'host',
102
- },
103
- {
104
- appId: 'checkout',
105
- label: 'Checkout',
106
- mfName: 'verticalCheckout',
107
- ownerTeam: 'checkout-platform',
108
- role: 'vertical',
109
- },
110
- ],
111
- schemaVersion: 1,
112
- },
113
- })],
114
- });
115
- const WrappedApp = runtimeContext.hooks.wrapRoot.call(App);
116
-
117
- createRoot(document.getElementById('root')).render(
118
- React.createElement(WrappedApp),
119
- );
120
- `,
121
- 'utf8',
122
- );
123
- await build({
124
- absWorkingDir: path.resolve(__dirname, '../..'),
125
- bundle: true,
126
- define: {
127
- 'process.env.NODE_ENV': '"test"',
128
- },
129
- entryPoints: [entryPath],
130
- format: 'esm',
131
- jsx: 'transform',
132
- jsxFactory: 'React.createElement',
133
- jsxFragment: 'React.Fragment',
134
- nodePaths: [
135
- path.resolve(__dirname, '../../node_modules'),
136
- path.resolve(__dirname, '../../../../../node_modules'),
137
- ],
138
- outfile: bundlePath,
139
- platform: 'browser',
140
- });
141
- writeFileSync(
142
- htmlPath,
143
- `<!doctype html><html><body><div id="root"></div><script type="module">${readFileSync(
144
- bundlePath,
145
- 'utf8',
146
- )}</script></body></html>`,
147
- 'utf8',
148
- );
149
-
150
- const browser = await chromium.launch({ headless: true });
151
- try {
152
- const page = await browser.newPage();
153
- const browserErrors: string[] = [];
154
- page.on('console', message => {
155
- if (message.type?.() === 'error') {
156
- browserErrors.push(message.text?.() ?? String(message));
157
- }
158
- });
159
- page.on('pageerror', error => {
160
- browserErrors.push(
161
- error instanceof Error ? error.message : String(error),
162
- );
163
- });
164
- await page.goto(pathToFileURL(htmlPath).href);
165
- try {
166
- await page.waitForFunction(
167
- () =>
168
- Boolean(
169
- document.querySelector('[data-testid="primary-control"]'),
170
- ),
171
- undefined,
172
- { timeout: 5000 },
173
- );
174
- } catch (error) {
175
- const bodyHtml = await page.evaluate(() => document.body.innerHTML);
176
- throw new Error(
177
- `${error instanceof Error ? error.message : String(error)}\n` +
178
- `browserErrors=${JSON.stringify(browserErrors)}\n` +
179
- `body=${bodyHtml.slice(0, 500)}`,
180
- );
181
- }
182
- expect(browserErrors).toEqual([]);
183
-
184
- const before = await page.evaluate(() => {
185
- const control = document.querySelector(
186
- '[data-testid="primary-control"]',
187
- ) as HTMLElement;
188
- const rect = control.getBoundingClientRect();
189
- return {
190
- rect: {
191
- height: rect.height,
192
- left: rect.left,
193
- top: rect.top,
194
- width: rect.width,
195
- },
196
- scrollHeight: document.documentElement.scrollHeight,
197
- };
198
- });
199
-
200
- await page.click('text=show team boundaries');
201
- await page.waitForFunction(
202
- () =>
203
- document.querySelectorAll('[data-modern-boundary-overlay]')
204
- .length === 2,
205
- undefined,
206
- { timeout: 5000 },
207
- );
208
-
209
- const after = await page.evaluate(() => {
210
- const control = document.querySelector(
211
- '[data-testid="primary-control"]',
212
- ) as HTMLElement;
213
- const rect = control.getBoundingClientRect();
214
- const checkoutOverlay = document.querySelector(
215
- '[data-modern-boundary-overlay-label="Checkout"]',
216
- ) as HTMLElement | null;
217
- return {
218
- checkoutOverlayStyle: checkoutOverlay
219
- ? {
220
- boxSizing: checkoutOverlay.style.boxSizing,
221
- pointerEvents: checkoutOverlay.style.pointerEvents,
222
- position: checkoutOverlay.style.position,
223
- }
224
- : null,
225
- checkoutOverlayText: checkoutOverlay?.textContent ?? '',
226
- rect: {
227
- height: rect.height,
228
- left: rect.left,
229
- top: rect.top,
230
- width: rect.width,
231
- },
232
- scrollHeight: document.documentElement.scrollHeight,
233
- };
234
- });
235
-
236
- expect(after.scrollHeight).toBe(before.scrollHeight);
237
- expect(after.rect).toEqual(before.rect);
238
- expect(after.checkoutOverlayStyle).toEqual({
239
- boxSizing: 'border-box',
240
- pointerEvents: 'none',
241
- position: 'fixed',
242
- });
243
- expect(after.checkoutOverlayText).toContain('Checkout');
244
- expect(after.checkoutOverlayText).toContain('./Controls');
245
- } finally {
246
- await browser.close();
247
- }
248
- } finally {
249
- rmSync(tempDir, { force: true, recursive: true });
250
- }
251
- });
252
- });