Skip to content

Commit 69f90b7

Browse files
fix streamServerRenderedReactComponent and helper specs
1 parent 67e17c7 commit 69f90b7

File tree

3 files changed

+42
-19
lines changed

3 files changed

+42
-19
lines changed

lib/react_on_rails/react_component/render_options.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def initialize(react_component_name: required("react_component_name"), options:
2121
# Therefore, we need an additional unique identifier that can be used both on the client and server.
2222
# This ID can also be used to associate specific data with a particular rendered component
2323
# on either the server or client.
24-
@render_request_id = SecureRandom.uuid
24+
@render_request_id = self.class.generate_request_id
2525
end
2626

2727
attr_reader :react_component_name, :render_request_id
@@ -146,6 +146,10 @@ def store_dependencies
146146
options[:store_dependencies]
147147
end
148148

149+
def self.generate_request_id
150+
SecureRandom.uuid
151+
end
152+
149153
private
150154

151155
attr_reader :options

node_package/tests/streamServerRenderedReactComponent.test.jsx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as React from 'react';
66
import * as PropTypes from 'prop-types';
77
import streamServerRenderedReactComponent from '../src/streamServerRenderedReactComponent.ts';
88
import * as ComponentRegistry from '../src/ComponentRegistry.ts';
9+
import ReactOnRails from '../src/ReactOnRails.node.ts';
910

1011
const AsyncContent = async ({ throwAsyncError }) => {
1112
await new Promise((resolve) => {
@@ -64,29 +65,29 @@ describe('streamServerRenderedReactComponent', () => {
6465
} = {}) => {
6566
switch (componentType) {
6667
case 'reactComponent':
67-
ComponentRegistry.register({ TestComponentForStreaming });
68+
ReactOnRails.register({ TestComponentForStreaming });
6869
break;
6970
case 'renderFunction':
70-
ComponentRegistry.register({
71+
ReactOnRails.register({
7172
TestComponentForStreaming: (props, _railsContext) => () => <TestComponentForStreaming {...props} />,
7273
});
7374
break;
7475
case 'asyncRenderFunction':
75-
ComponentRegistry.register({
76+
ReactOnRails.register({
7677
TestComponentForStreaming: (props, _railsContext) => () =>
7778
Promise.resolve(<TestComponentForStreaming {...props} />),
7879
});
7980
break;
8081
case 'erroneousRenderFunction':
81-
ComponentRegistry.register({
82+
ReactOnRails.register({
8283
TestComponentForStreaming: (_props, _railsContext) => {
8384
// The error happen inside the render function itself not inside the returned React component
8485
throw new Error('Sync Error from render function');
8586
},
8687
});
8788
break;
8889
case 'erroneousAsyncRenderFunction':
89-
ComponentRegistry.register({
90+
ReactOnRails.register({
9091
TestComponentForStreaming: (_props, _railsContext) =>
9192
// The error happen inside the render function itself not inside the returned React component
9293
Promise.reject(new Error('Async Error from render function')),
@@ -101,6 +102,11 @@ describe('streamServerRenderedReactComponent', () => {
101102
trace: false,
102103
props: { throwSyncError, throwAsyncError },
103104
throwJsErrors,
105+
railsContext: {
106+
componentSpecificMetadata: {
107+
renderRequestId: '123',
108+
},
109+
},
104110
});
105111

106112
const chunks = [];
@@ -173,13 +179,15 @@ describe('streamServerRenderedReactComponent', () => {
173179
expect(chunks.length).toBeGreaterThanOrEqual(2);
174180
expect(chunks[0].html).toContain('Header In The Shell');
175181
expect(chunks[0].consoleReplayScript).toBe('');
176-
expect(chunks[0].hasErrors).toBe(false);
177182
expect(chunks[0].isShellReady).toBe(true);
178183
// Script that fallbacks the render to client side
179184
expect(chunks[1].html).toMatch(/the server rendering errored:\\n\\nAsync Error/);
180185
expect(chunks[1].consoleReplayScript).toBe('');
181-
expect(chunks[1].hasErrors).toBe(true);
182186
expect(chunks[1].isShellReady).toBe(true);
187+
188+
// One of the chunks should have a hasErrors property of true
189+
expect(chunks[0].hasErrors || chunks[1].hasErrors).toBe(true);
190+
expect(chunks[0].hasErrors && chunks[1].hasErrors).toBe(false);
183191
});
184192

185193
it("doesn't emit an error if there is an error in the async content and throwJsErrors is false", async () => {
@@ -194,13 +202,15 @@ describe('streamServerRenderedReactComponent', () => {
194202
expect(chunks.length).toBeGreaterThanOrEqual(2);
195203
expect(chunks[0].html).toContain('Header In The Shell');
196204
expect(chunks[0].consoleReplayScript).toBe('');
197-
expect(chunks[0].hasErrors).toBe(false);
198205
expect(chunks[0].isShellReady).toBe(true);
199206
// Script that fallbacks the render to client side
200207
expect(chunks[1].html).toMatch(/the server rendering errored:\\n\\nAsync Error/);
201208
expect(chunks[1].consoleReplayScript).toBe('');
202-
expect(chunks[1].hasErrors).toBe(true);
203209
expect(chunks[1].isShellReady).toBe(true);
210+
211+
// One of the chunks should have a hasErrors property of true
212+
expect(chunks[0].hasErrors || chunks[1].hasErrors).toBe(true);
213+
expect(chunks[0].hasErrors && chunks[1].hasErrors).toBe(false);
204214
});
205215

206216
it.each(['asyncRenderFunction', 'renderFunction'])(
@@ -250,12 +260,14 @@ describe('streamServerRenderedReactComponent', () => {
250260
expect(chunks.length).toBeGreaterThanOrEqual(2);
251261
expect(chunks[0].html).toContain('Header In The Shell');
252262
expect(chunks[0].consoleReplayScript).toBe('');
253-
expect(chunks[0].hasErrors).toBe(false);
254263
expect(chunks[0].isShellReady).toBe(true);
255264
expect(chunks[1].html).toMatch(/the server rendering errored:\\n\\nAsync Error/);
256265
expect(chunks[1].consoleReplayScript).toBe('');
257-
expect(chunks[1].hasErrors).toBe(true);
258266
expect(chunks[1].isShellReady).toBe(true);
267+
268+
// One of the chunks should have a hasErrors property of true
269+
expect(chunks[0].hasErrors || chunks[1].hasErrors).toBe(true);
270+
expect(chunks[0].hasErrors && chunks[1].hasErrors).toBe(false);
259271
},
260272
);
261273

@@ -308,13 +320,18 @@ describe('streamServerRenderedReactComponent', () => {
308320

309321
it('streams a string from a Promise that resolves to a string', async () => {
310322
const StringPromiseComponent = () => Promise.resolve('<div>String from Promise</div>');
311-
ComponentRegistry.register({ StringPromiseComponent });
323+
ReactOnRails.register({ StringPromiseComponent });
312324

313325
const renderResult = streamServerRenderedReactComponent({
314326
name: 'StringPromiseComponent',
315327
domNodeId: 'stringPromiseId',
316328
trace: false,
317329
throwJsErrors: false,
330+
railsContext: {
331+
componentSpecificMetadata: {
332+
renderRequestId: '123',
333+
},
334+
},
318335
});
319336

320337
const chunks = [];

spec/dummy/spec/helpers/react_on_rails_helper_spec.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class PlainReactOnRailsHelper
2121
{ "HTTP_ACCEPT_LANGUAGE" => "en" }
2222
)
2323
}
24+
25+
allow(ReactOnRails::ReactComponent::RenderOptions).to receive(:generate_request_id).and_return("123")
2426
end
2527

2628
let(:hash) do
@@ -195,7 +197,7 @@ def helper.append_javascript_pack_tag(name, **options)
195197
<script type="application/json" class="js-react-on-rails-component" \
196198
id="js-react-on-rails-component-App-react-component" \
197199
data-component-name="App" data-dom-id="App-react-component"
198-
data-force-load="true">{"name":"My Test Name"}</script>
200+
data-force-load="true" data-render-request-id="123">{"name":"My Test Name"}</script>
199201
SCRIPT
200202
end
201203

@@ -204,7 +206,7 @@ def helper.append_javascript_pack_tag(name, **options)
204206
<script type="application/json" class="js-react-on-rails-component" \
205207
id="js-react-on-rails-component-App-react-component" \
206208
data-component-name="App" data-dom-id="App-react-component"
207-
data-force-load="true">{}</script>
209+
data-force-load="true" data-render-request-id="123">{}</script>
208210
SCRIPT
209211
end
210212

@@ -253,7 +255,7 @@ def helper.append_javascript_pack_tag(name, **options)
253255
<script type="application/json" class="js-react-on-rails-component" \
254256
id="js-react-on-rails-component-App-react-component" \
255257
data-component-name="App" data-dom-id="App-react-component"
256-
data-force-load="true">{"name":"My Test Name"}</script>
258+
data-force-load="true" data-render-request-id="123">{"name":"My Test Name"}</script>
257259
SCRIPT
258260
end
259261

@@ -269,7 +271,7 @@ def helper.append_javascript_pack_tag(name, **options)
269271
<script type="application/json" class="js-react-on-rails-component" \
270272
id="js-react-on-rails-component-App-react-component-0" \
271273
data-component-name="App" data-dom-id="App-react-component-0"
272-
data-force-load="true">{"name":"My Test Name"}</script>
274+
data-force-load="true" data-render-request-id="123">{"name":"My Test Name"}</script>
273275
SCRIPT
274276
end
275277

@@ -291,7 +293,7 @@ def helper.append_javascript_pack_tag(name, **options)
291293
<script type="application/json" class="js-react-on-rails-component" \
292294
id="js-react-on-rails-component-App-react-component" \
293295
data-component-name="App" data-dom-id="App-react-component"
294-
data-force-load="true">{"name":"My Test Name"}</script>
296+
data-force-load="true" data-render-request-id="123">{"name":"My Test Name"}</script>
295297
SCRIPT
296298
end
297299

@@ -309,7 +311,7 @@ def helper.append_javascript_pack_tag(name, **options)
309311
<script type="application/json" class="js-react-on-rails-component" \
310312
id="js-react-on-rails-component-shaka_div" \
311313
data-component-name="App" data-dom-id="shaka_div"
312-
data-force-load="true">{"name":"My Test Name"}</script>
314+
data-force-load="true" data-render-request-id="123">{"name":"My Test Name"}</script>
313315
SCRIPT
314316
end
315317

0 commit comments

Comments
 (0)