Skip to content

Commit ec23294

Browse files
fix tests caused by mock-fs and linting
1 parent 8e857ac commit ec23294

File tree

6 files changed

+115
-114
lines changed

6 files changed

+115
-114
lines changed

packages/react-on-rails-pro/tests/AsyncQueue.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import * as EventEmitter from 'node:events';
22

33
class AsyncQueue<T> {
4-
private eventEmitter = new EventEmitter<{ data: any, end: any }>();
4+
private eventEmitter = new EventEmitter();
5+
56
private buffer: T[] = [];
7+
68
private isEnded = false;
79

810
enqueue(value: T) {
911
if (this.isEnded) {
10-
throw new Error("Queue Ended");
12+
throw new Error('Queue Ended');
1113
}
1214

1315
if (this.eventEmitter.listenerCount('data') > 0) {
@@ -28,31 +30,27 @@ class AsyncQueue<T> {
2830
if (bufferValueIfExist) {
2931
resolve(bufferValueIfExist);
3032
} else if (this.isEnded) {
31-
reject(new Error("Queue Ended"));
33+
reject(new Error('Queue Ended'));
3234
} else {
33-
let teardown = () => {}
35+
let teardown = () => {};
3436
const onData = (value: T) => {
3537
resolve(value);
3638
teardown();
37-
}
38-
39+
};
40+
3941
const onEnd = () => {
40-
reject(new Error("Queue Ended"));
42+
reject(new Error('Queue Ended'));
4143
teardown();
42-
}
44+
};
4345

4446
this.eventEmitter.on('data', onData);
4547
this.eventEmitter.on('end', onEnd);
4648
teardown = () => {
4749
this.eventEmitter.off('data', onData);
4850
this.eventEmitter.off('end', onEnd);
49-
}
51+
};
5052
}
51-
})
52-
}
53-
54-
toString() {
55-
return ""
53+
});
5654
}
5755
}
5856

packages/react-on-rails-pro/tests/StreamReader.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PassThrough, Readable } from 'node:stream';
2-
import AsyncQueue from './AsyncQueue';
2+
import AsyncQueue from './AsyncQueue.ts';
33

44
class StreamReader {
55
private asyncQueue: AsyncQueue<string>;
@@ -11,7 +11,7 @@ class StreamReader {
1111
const readableStream = new PassThrough();
1212
pipeableStream.pipe(readableStream);
1313

14-
readableStream.on('data', (chunk) => {
14+
readableStream.on('data', (chunk: Buffer) => {
1515
const decodedChunk = decoder.decode(chunk);
1616
this.asyncQueue.enqueue(decodedChunk);
1717
});

packages/react-on-rails-pro/tests/concurrentRSCPayloadGeneration.rsc.test.tsx

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,43 @@
44
/// <reference types="react/experimental" />
55

66
import * as React from 'react';
7-
import { PassThrough, Readable, Transform } from 'node:stream';
8-
import { text } from 'node:stream/consumers';
97
import { Suspense, PropsWithChildren } from 'react';
108

119
import * as path from 'path';
1210
import * as mock from 'mock-fs';
1311

14-
import ReactOnRails, { RailsContextWithServerStreamingCapabilities } from '../src/ReactOnRailsRSC';
15-
import AsyncQueue from './AsyncQueue';
16-
import StreamReader from './StreamReader';
17-
import removeRSCChunkStack from './utils/removeRSCChunkStack';
12+
import ReactOnRails, { RailsContextWithServerStreamingCapabilities } from '../src/ReactOnRailsRSC.ts';
13+
import AsyncQueue from './AsyncQueue.ts';
14+
import StreamReader from './StreamReader.ts';
15+
import removeRSCChunkStack from './utils/removeRSCChunkStack.ts';
1816

19-
const manifestFileDirectory = path.resolve(__dirname, '../src')
17+
const manifestFileDirectory = path.resolve(__dirname, '../src');
2018
const clientManifestPath = path.join(manifestFileDirectory, 'react-client-manifest.json');
2119

22-
mock({
23-
[clientManifestPath]: JSON.stringify({
24-
filePathToModuleMetadata: {},
25-
moduleLoading: { prefix: '', crossOrigin: null },
26-
}),
20+
beforeEach(() => {
21+
mock({
22+
[clientManifestPath]: JSON.stringify({
23+
filePathToModuleMetadata: {},
24+
moduleLoading: { prefix: '', crossOrigin: null },
25+
}),
26+
});
2727
});
2828

29-
afterAll(() => mock.restore());
29+
afterEach(() => mock.restore());
3030

31-
const AsyncQueueItem = async ({ asyncQueue, children }: PropsWithChildren<{asyncQueue: AsyncQueue<string>}>) => {
31+
const AsyncQueueItem = async ({
32+
asyncQueue,
33+
children,
34+
}: PropsWithChildren<{ asyncQueue: AsyncQueue<string> }>) => {
3235
const value = await asyncQueue.dequeue();
3336

3437
return (
3538
<>
3639
<p>Data: {value}</p>
3740
{children}
3841
</>
39-
)
40-
}
42+
);
43+
};
4144

4245
const AsyncQueueContainer = ({ asyncQueue }: { asyncQueue: AsyncQueue<string> }) => {
4346
return (
@@ -55,8 +58,8 @@ const AsyncQueueContainer = ({ asyncQueue }: { asyncQueue: AsyncQueue<string> })
5558
</AsyncQueueItem>
5659
</Suspense>
5760
</div>
58-
)
59-
}
61+
);
62+
};
6063

6164
ReactOnRails.register({ AsyncQueueContainer });
6265

@@ -72,30 +75,30 @@ const renderComponent = (props: Record<string, unknown>) => {
7275
domNodeId: 'dom-id',
7376
props,
7477
});
75-
}
78+
};
7679

7780
const createParallelRenders = (size: number) => {
7881
const asyncQueues = new Array(size).fill(null).map(() => new AsyncQueue<string>());
7982
const streams = asyncQueues.map((asyncQueue) => {
8083
return renderComponent({ asyncQueue });
8184
});
82-
const readers = streams.map(stream => new StreamReader(stream));
85+
const readers = streams.map((stream) => new StreamReader(stream));
8386

84-
const enqueue = (value: string) => asyncQueues.forEach(asyncQueues => asyncQueues.enqueue(value));
87+
const enqueue = (value: string) => asyncQueues.forEach((asyncQueue) => asyncQueue.enqueue(value));
8588

86-
const expectNextChunk = (nextChunk: string) => Promise.all(
87-
readers.map(async (reader) => {
88-
const chunk = await reader.nextChunk();
89-
expect(removeRSCChunkStack(chunk)).toEqual(removeRSCChunkStack(nextChunk));
90-
})
91-
);
92-
93-
const expectEndOfStream = () => Promise.all(
94-
readers.map(reader => expect(reader.nextChunk()).rejects.toThrow(/Queue Ended/))
95-
);
89+
const expectNextChunk = (nextChunk: string) =>
90+
Promise.all(
91+
readers.map(async (reader) => {
92+
const chunk = await reader.nextChunk();
93+
expect(removeRSCChunkStack(chunk)).toEqual(removeRSCChunkStack(nextChunk));
94+
}),
95+
);
96+
97+
const expectEndOfStream = () =>
98+
Promise.all(readers.map((reader) => expect(reader.nextChunk()).rejects.toThrow(/Queue Ended/)));
9699

97100
return { enqueue, expectNextChunk, expectEndOfStream };
98-
}
101+
};
99102

100103
test('Renders concurrent rsc streams as single rsc stream', async () => {
101104
expect.assertions(258);
@@ -104,38 +107,38 @@ test('Renders concurrent rsc streams as single rsc stream', async () => {
104107
const reader = new StreamReader(stream);
105108

106109
const chunks: string[] = [];
107-
let chunk = await reader.nextChunk()
110+
let chunk = await reader.nextChunk();
108111
chunks.push(chunk);
109-
expect(chunk).toContain("Async Queue");
110-
expect(chunk).toContain("Loading Item2");
111-
expect(chunk).not.toContain("Random Value");
112+
expect(chunk).toContain('Async Queue');
113+
expect(chunk).toContain('Loading Item2');
114+
expect(chunk).not.toContain('Random Value');
112115

113-
asyncQueue.enqueue("Random Value1");
116+
asyncQueue.enqueue('Random Value1');
114117
chunk = await reader.nextChunk();
115118
chunks.push(chunk);
116-
expect(chunk).toContain("Random Value1");
119+
expect(chunk).toContain('Random Value1');
117120

118-
asyncQueue.enqueue("Random Value2");
121+
asyncQueue.enqueue('Random Value2');
119122
chunk = await reader.nextChunk();
120123
chunks.push(chunk);
121-
expect(chunk).toContain("Random Value2");
124+
expect(chunk).toContain('Random Value2');
122125

123-
asyncQueue.enqueue("Random Value3");
126+
asyncQueue.enqueue('Random Value3');
124127
chunk = await reader.nextChunk();
125128
chunks.push(chunk);
126-
expect(chunk).toContain("Random Value3");
129+
expect(chunk).toContain('Random Value3');
127130

128131
await expect(reader.nextChunk()).rejects.toThrow(/Queue Ended/);
129132

130133
const { enqueue, expectNextChunk, expectEndOfStream } = createParallelRenders(50);
131134

132135
expect(chunks).toHaveLength(4);
133-
await expectNextChunk(chunks[0]!);
134-
enqueue("Random Value1");
135-
await expectNextChunk(chunks[1]!);
136-
enqueue("Random Value2");
137-
await expectNextChunk(chunks[2]!);
138-
enqueue("Random Value3");
139-
await expectNextChunk(chunks[3]!);
136+
await expectNextChunk(chunks[0]);
137+
enqueue('Random Value1');
138+
await expectNextChunk(chunks[1]);
139+
enqueue('Random Value2');
140+
await expectNextChunk(chunks[2]);
141+
enqueue('Random Value3');
142+
await expectNextChunk(chunks[3]);
140143
await expectEndOfStream();
141144
});

packages/react-on-rails-pro/tests/serverRenderRSCReactComponent.rsc.test.tsx

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,22 @@
11
/**
22
* @jest-environment node
33
*/
4+
/// <reference types="react/experimental" />
45

56
import * as React from 'react';
67
import { Suspense } from 'react';
78
import * as mock from 'mock-fs';
8-
import * as fs from 'fs';
99
import * as path from 'path';
10-
import { pipeline, finished } from 'stream/promises';
10+
import { finished } from 'stream/promises';
1111
import { text } from 'stream/consumers';
12-
import { buildServerRenderer } from 'react-on-rails-rsc/server.node';
13-
import createReactOutput from 'react-on-rails/createReactOutput';
1412
import ReactOnRails, { RailsContextWithServerStreamingCapabilities } from '../src/ReactOnRailsRSC.ts';
15-
import removeRSCStackFromAllChunks from './utils/removeRSCStackFromAllChunks.ts'
1613

17-
const PromiseWrapper = async ({ promise, name }: { promise: Promise<string>, name: string }) => {
14+
const PromiseWrapper = async ({ promise, name }: { promise: Promise<string>; name: string }) => {
1815
console.log(`[${name}] Before awaitng`);
1916
const value = await promise;
2017
console.log(`[${name}] After awaitng`);
21-
return (
22-
<p>Value: {value}</p>
23-
);
24-
}
18+
return <p>Value: {value}</p>;
19+
};
2520

2621
const PromiseContainer = ({ name }: { name: string }) => {
2722
const promise = new Promise<string>((resolve) => {
@@ -44,21 +39,23 @@ const PromiseContainer = ({ name }: { name: string }) => {
4439
</Suspense>
4540
</div>
4641
);
47-
}
42+
};
4843

4944
ReactOnRails.register({ PromiseContainer });
5045

51-
const manifestFileDirectory = path.resolve(__dirname, '../src')
46+
const manifestFileDirectory = path.resolve(__dirname, '../src');
5247
const clientManifestPath = path.join(manifestFileDirectory, 'react-client-manifest.json');
5348

54-
mock({
55-
[clientManifestPath]: JSON.stringify({
56-
filePathToModuleMetadata: {},
57-
moduleLoading: { prefix: '', crossOrigin: null },
58-
}),
49+
beforeEach(() => {
50+
mock({
51+
[clientManifestPath]: JSON.stringify({
52+
filePathToModuleMetadata: {},
53+
moduleLoading: { prefix: '', crossOrigin: null },
54+
}),
55+
});
5956
});
6057

61-
afterAll(() => {
58+
afterEach(() => {
6259
mock.restore();
6360
});
6461

@@ -72,7 +69,7 @@ test('no logs leakage between concurrent rendering components', async () => {
7269
renderingReturnsPromises: true,
7370
throwJsErrors: true,
7471
domNodeId: 'dom-id',
75-
props: { name: "First Unique Name" }
72+
props: { name: 'First Unique Name' },
7673
});
7774
const readable2 = ReactOnRails.serverRenderRSCReactComponent({
7875
railsContext: {
@@ -83,15 +80,15 @@ test('no logs leakage between concurrent rendering components', async () => {
8380
renderingReturnsPromises: true,
8481
throwJsErrors: true,
8582
domNodeId: 'dom-id',
86-
props: { name: "Second Unique Name" }
83+
props: { name: 'Second Unique Name' },
8784
});
8885

8986
const [content1, content2] = await Promise.all([text(readable1), text(readable2)]);
9087

91-
expect(content1).toContain("First Unique Name");
92-
expect(content2).toContain("Second Unique Name");
93-
expect(content1).not.toContain("Second Unique Name");
94-
expect(content2).not.toContain("First Unique Name");
88+
expect(content1).toContain('First Unique Name');
89+
expect(content2).toContain('Second Unique Name');
90+
expect(content1).not.toContain('Second Unique Name');
91+
expect(content2).not.toContain('First Unique Name');
9592
});
9693

9794
test('no logs lekage from outside the component', async () => {
@@ -104,7 +101,7 @@ test('no logs lekage from outside the component', async () => {
104101
renderingReturnsPromises: true,
105102
throwJsErrors: true,
106103
domNodeId: 'dom-id',
107-
props: { name: "First Unique Name" }
104+
props: { name: 'First Unique Name' },
108105
});
109106

110107
const promise = new Promise<void>((resolve) => {
@@ -121,8 +118,8 @@ test('no logs lekage from outside the component', async () => {
121118

122119
const [content1] = await Promise.all([text(readable1), promise]);
123120

124-
expect(content1).toContain("First Unique Name");
125-
expect(content1).not.toContain("Outside The Component");
121+
expect(content1).toContain('First Unique Name');
122+
expect(content1).not.toContain('Outside The Component');
126123
});
127124

128125
test('[bug] catches logs outside the component during reading the stream', async () => {
@@ -135,29 +132,29 @@ test('[bug] catches logs outside the component during reading the stream', async
135132
renderingReturnsPromises: true,
136133
throwJsErrors: true,
137134
domNodeId: 'dom-id',
138-
props: { name: "First Unique Name" }
135+
props: { name: 'First Unique Name' },
139136
});
140-
141-
let content1 = "";
137+
138+
let content1 = '';
142139
let i = 0;
143-
readable1.on('data', (chunk) => {
140+
readable1.on('data', (chunk: Buffer) => {
144141
i += 1;
145142
// To avoid infinite loop
146143
if (i < 5) {
147-
console.log("Outside The Component");
144+
console.log('Outside The Component');
148145
}
149146
content1 += chunk.toString();
150147
});
151148

152149
// However, any logs from outside the stream 'data' event callback is not catched
153150
const intervalId = setInterval(() => {
154-
console.log("From Interval")
151+
console.log('From Interval');
155152
}, 2);
156153
await finished(readable1);
157154
clearInterval(intervalId);
158155

159-
expect(content1).toContain("First Unique Name");
160-
expect(content1).not.toContain("From Interval");
156+
expect(content1).toContain('First Unique Name');
157+
expect(content1).not.toContain('From Interval');
161158
// Here's the bug
162-
expect(content1).toContain("Outside The Component");
159+
expect(content1).toContain('Outside The Component');
163160
});

0 commit comments

Comments
 (0)