@bleedingdev/modern-js-runtime-renderer-extensions 3.9.0-ultramodern.13 → 3.9.0-ultramodern.15

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/renderer-extensions"
12
12
  },
13
13
  "license": "MIT",
14
- "version": "3.9.0-ultramodern.13",
14
+ "version": "3.9.0-ultramodern.15",
15
15
  "engines": {
16
16
  "node": ">=26.7.0"
17
17
  },
@@ -36,12 +36,12 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.13",
40
- "@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.13"
39
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.15",
40
+ "@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.15"
41
41
  },
42
42
  "devDependencies": {
43
- "@modern-js/render": "npm:@bleedingdev/modern-js-render@3.9.0-ultramodern.13",
44
- "@modern-js/tsconfig": "npm:@bleedingdev/modern-js-tsconfig@3.9.0-ultramodern.13",
43
+ "@modern-js/render": "npm:@bleedingdev/modern-js-render@3.9.0-ultramodern.15",
44
+ "@modern-js/tsconfig": "npm:@bleedingdev/modern-js-tsconfig@3.9.0-ultramodern.15",
45
45
  "@rslib/core": "1.0.2",
46
46
  "@scripts/rstest-config": "2.66.0",
47
47
  "@testing-library/dom": "^10.4.2",
@@ -24,16 +24,28 @@ const createRuntimeContext = () => ({
24
24
  },
25
25
  });
26
26
 
27
+ const renderDocument = async (root: React.ReactElement) => {
28
+ registerPlugin([rendererHeadPlugin()]);
29
+ const stream = await renderStreaming(new Request('http://localhost/'), root, {
30
+ resource: {
31
+ entryName: 'index',
32
+ htmlTemplate: '<html><head></head><body><!--<?- html ?>--></body></html>',
33
+ routeManifest: {},
34
+ },
35
+ runtimeContext: createRuntimeContext(),
36
+ config: {},
37
+ onError: () => {},
38
+ onTiming: () => {},
39
+ } as any);
40
+ return new Response(stream).text();
41
+ };
42
+
27
43
  describe('streaming Helmet collection', () => {
28
44
  it('publishes only Helmet markers present in the completed shell', async () => {
29
- registerPlugin([rendererHeadPlugin()]);
30
-
31
45
  const AbandonPrimary = (): null => {
32
46
  throw new Error('abandon primary');
33
47
  };
34
- const runtimeContext = createRuntimeContext();
35
- const stream = await renderStreaming(
36
- new Request('http://localhost/'),
48
+ const html = await renderDocument(
37
49
  <>
38
50
  <Helmet>
39
51
  <meta name="outside" content="committed" />
@@ -54,24 +66,36 @@ describe('streaming Helmet collection', () => {
54
66
  <AbandonPrimary />
55
67
  </React.Suspense>
56
68
  </>,
57
- {
58
- resource: {
59
- entryName: 'index',
60
- htmlTemplate:
61
- '<html><head></head><body><!--<?- html ?>--></body></html>',
62
- routeManifest: {},
63
- },
64
- runtimeContext,
65
- config: {},
66
- onError: () => {},
67
- onTiming: () => {},
68
- } as any,
69
69
  );
70
70
 
71
- const html = await new Response(stream).text();
72
71
  expect(html).toContain('name="outside" content="committed"');
73
72
  expect(html).toContain('name="fallback" content="committed"');
74
73
  expect(html).not.toContain('abandoned-unique');
75
74
  expect(html).not.toContain('data-modern-helmet');
76
75
  });
76
+
77
+ it('keeps the head of a large completed route boundary in the shell', async () => {
78
+ // Routes render inside Suspense below the app container. A completed
79
+ // boundary this large is one React would otherwise write after the shell,
80
+ // past the point where the document head is sealed.
81
+ const html = await renderDocument(
82
+ <div id="app">
83
+ <React.Suspense fallback="loading">
84
+ <main>{'Route content. '.repeat(1000)}</main>
85
+ <Helmet htmlAttributes={{ lang: 'cs' }}>
86
+ <title>Route title</title>
87
+ <meta name="description" content="Route description" />
88
+ </Helmet>
89
+ </React.Suspense>
90
+ </div>,
91
+ );
92
+
93
+ const head = html.slice(0, html.indexOf('</head>'));
94
+ expect(head).toContain('<html lang="cs">');
95
+ expect(head).toMatch(/<title[^>]*>Route title<\/title>/);
96
+ expect(head).toMatch(
97
+ /<meta(?=[^>]*name="description")(?=[^>]*content="Route description")/,
98
+ );
99
+ expect(html).toContain('<main>Route content. ');
100
+ });
77
101
  });