Skip to content

Commit e4b30ea

Browse files
tmp
1 parent 99a2d71 commit e4b30ea

File tree

2 files changed

+178
-1
lines changed

2 files changed

+178
-1
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
3+
import * as React from 'react';
4+
import serverRenderReactComponent from '../src/serverRenderReactComponent';
5+
import ComponentRegistry from '../src/ComponentRegistry';
6+
import type {
7+
RenderParams,
8+
RenderResult,
9+
RailsContext,
10+
RenderFunction,
11+
RenderFunctionResult,
12+
ServerRenderResult,
13+
} from '../src/types';
14+
15+
const assertIsString: (value: unknown) => asserts value is string = (value: unknown) => {
16+
if (typeof value !== 'string') {
17+
throw new Error(`Expected value to be of type 'string', but received type '${typeof value}'`);
18+
}
19+
};
20+
21+
const assertIsPromise: <T>(value: null | string | Promise<T>) => asserts value is Promise<T> = <T>(
22+
value: null | string | Promise<T>,
23+
) => {
24+
if (!value || typeof (value as Promise<T>).then !== 'function') {
25+
throw new Error(`Expected value to be of type 'Promise', but received type '${typeof value}'`);
26+
}
27+
};
28+
29+
// This function is used to ensure type safety when matching objects in TypeScript tests
30+
const expectMatchObject = <T extends object>(actual: T, expected: T) => {
31+
expect(actual).toMatchObject(expected);
32+
};
33+
34+
describe('serverRenderReactComponent', () => {
35+
beforeEach(() => {
36+
ComponentRegistry.components().clear();
37+
});
38+
39+
it('serverRenderReactComponent renders a registered component', () => {
40+
const X1: React.FC = () => React.createElement('div', null, 'HELLO');
41+
ComponentRegistry.register({ X1 });
42+
43+
const renderParams: RenderParams = {
44+
name: 'X1',
45+
domNodeId: 'myDomId',
46+
trace: false,
47+
throwJsErrors: false,
48+
renderingReturnsPromises: false,
49+
};
50+
51+
const renderResult = serverRenderReactComponent(renderParams);
52+
assertIsString(renderResult);
53+
const { html, hasErrors }: RenderResult = JSON.parse(renderResult) as RenderResult;
54+
55+
const result = html && html.indexOf('>HELLO</div>') > 0;
56+
expect(result).toBeTruthy();
57+
expect(hasErrors).toBeFalsy();
58+
});
59+
60+
it('serverRenderReactComponent renders errors', () => {
61+
const X2: React.FC = () => {
62+
throw new Error('XYZ');
63+
};
64+
65+
ComponentRegistry.register({ X2 });
66+
67+
const renderParams: RenderParams = {
68+
name: 'X2',
69+
domNodeId: 'myDomId',
70+
trace: false,
71+
throwJsErrors: false,
72+
renderingReturnsPromises: false,
73+
};
74+
75+
const renderResult = serverRenderReactComponent(renderParams);
76+
assertIsString(renderResult);
77+
const { html, hasErrors }: RenderResult = JSON.parse(renderResult) as RenderResult;
78+
79+
const result = html && html.indexOf('XYZ') > 0 && html.indexOf('Exception in rendering!') > 0;
80+
expect(result).toBeTruthy();
81+
expect(hasErrors).toBeTruthy();
82+
});
83+
84+
it('serverRenderReactComponent renders html', () => {
85+
const expectedHtml = '<div>Hello</div>';
86+
const X3: RenderFunction = (_: unknown, __?: RailsContext): { renderedHtml: string } => ({
87+
renderedHtml: expectedHtml,
88+
});
89+
90+
ComponentRegistry.register({ X3 });
91+
92+
const renderParams: RenderParams = {
93+
name: 'X3',
94+
domNodeId: 'myDomId',
95+
trace: false,
96+
throwJsErrors: false,
97+
renderingReturnsPromises: false,
98+
};
99+
100+
const renderResult = serverRenderReactComponent(renderParams);
101+
assertIsString(renderResult);
102+
const { html, hasErrors }: RenderResult = JSON.parse(renderResult) as RenderResult;
103+
104+
expect(html).toEqual(expectedHtml);
105+
expect(hasErrors).toBeFalsy();
106+
});
107+
108+
it('serverRenderReactComponent renders an error if attempting to render a renderer', () => {
109+
const X4: RenderFunction = (
110+
_props: unknown,
111+
_railsContext?: RailsContext,
112+
_domNodeId?: string,
113+
): RenderFunctionResult => ({ renderedHtml: '' });
114+
115+
ComponentRegistry.register({ X4 });
116+
117+
const renderParams: RenderParams = {
118+
name: 'X4',
119+
domNodeId: 'myDomId',
120+
trace: false,
121+
throwJsErrors: false,
122+
renderingReturnsPromises: false,
123+
};
124+
125+
const renderResult = serverRenderReactComponent(renderParams);
126+
assertIsString(renderResult);
127+
const { html, hasErrors }: RenderResult = JSON.parse(renderResult) as RenderResult;
128+
129+
const result = html && html.indexOf('renderer') > 0 && html.indexOf('Exception in rendering!') > 0;
130+
expect(result).toBeTruthy();
131+
expect(hasErrors).toBeTruthy();
132+
});
133+
134+
it('serverRenderReactComponent renders promises', async () => {
135+
const expectedHtml = '<div>Hello</div>';
136+
const X5: RenderFunction = (_props: unknown, _railsContext?: RailsContext): Promise<string> =>
137+
Promise.resolve(expectedHtml);
138+
139+
ComponentRegistry.register({ X5 });
140+
141+
const renderParams: RenderParams = {
142+
name: 'X5',
143+
domNodeId: 'myDomId',
144+
trace: false,
145+
throwJsErrors: false,
146+
renderingReturnsPromises: true,
147+
};
148+
149+
const renderResult = serverRenderReactComponent(renderParams);
150+
assertIsPromise(renderResult);
151+
const html = await renderResult.then((r) => r.html);
152+
153+
expect(html).toEqual(expectedHtml);
154+
await expect(renderResult.then((r) => r.hasErrors)).resolves.toBeFalsy();
155+
});
156+
157+
it('serverRenderReactComponent renders promise of server side hash result', async () => {
158+
const expectedHtml = '<div>Hello</div>';
159+
const X6 = ((_props: unknown, _railsContext?: RailsContext): Promise<ServerRenderResult> =>
160+
Promise.resolve({ renderedHtml: expectedHtml })) as RenderFunction;
161+
162+
ComponentRegistry.register({ X6 });
163+
164+
const renderParams: RenderParams = {
165+
name: 'X6',
166+
domNodeId: 'myDomId',
167+
trace: false,
168+
throwJsErrors: false,
169+
renderingReturnsPromises: true,
170+
};
171+
172+
const renderResult = serverRenderReactComponent(renderParams);
173+
assertIsPromise(renderResult);
174+
const html = (await renderResult.then((r) => r.html)) as ServerRenderResult;
175+
expectMatchObject(html, { renderedHtml: expectedHtml });
176+
});
177+
});

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
"target": "es5",
1515
"typeRoots": ["./node_modules/@types", "./node_package/types"]
1616
},
17-
"include": ["node_package/src/**/*", "node_package/types/**/*"]
17+
"include": ["node_package/src/**/*", "node_package/types/**/*", "node_package/tests/**/*"]
1818
}

0 commit comments

Comments
 (0)