Skip to content

Commit bf75f8e

Browse files
authored
refactor: encapsulate Metro startup orchestration (#86)
1 parent ab5a226 commit bf75f8e

File tree

20 files changed

+1430
-462
lines changed

20 files changed

+1430
-462
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import fs from 'node:fs';
2+
import os from 'node:os';
3+
import path from 'node:path';
4+
import { afterEach, describe, expect, it, vi } from 'vitest';
5+
import type { Config as HarnessConfig } from '@react-native-harness/config';
6+
import type { Reporter, ReportableEvent } from '../reporter.js';
7+
import { getBundleRequestObserverMiddleware } from '../middlewares/bundle-request-middleware.js';
8+
import { HARNESS_REQUEST_KIND_HEADER } from '../request-kind.js';
9+
10+
const createReporter = () => {
11+
const events: ReportableEvent[] = [];
12+
13+
const reporter: Reporter = {
14+
addListener: vi.fn(),
15+
removeListener: vi.fn(),
16+
clearAllListeners: vi.fn(),
17+
emit: (event) => {
18+
events.push(event);
19+
},
20+
};
21+
22+
return { events, reporter };
23+
};
24+
25+
const createProjectRoot = () => {
26+
const projectRoot = fs.mkdtempSync(
27+
path.join(os.tmpdir(), 'rn-harness-bundle-request-')
28+
);
29+
tempDirs.push(projectRoot);
30+
fs.writeFileSync(path.join(projectRoot, 'index.js'), 'module.exports = {};');
31+
return projectRoot;
32+
};
33+
34+
const tempDirs: string[] = [];
35+
36+
afterEach(() => {
37+
for (const tempDir of tempDirs.splice(0)) {
38+
fs.rmSync(tempDir, { recursive: true, force: true });
39+
}
40+
});
41+
42+
const createHarnessConfig = (): HarnessConfig =>
43+
({
44+
entryPoint: './index.js',
45+
}) as HarnessConfig;
46+
47+
describe('bundle request observer middleware', () => {
48+
it('emits app-originated entry bundle requests', () => {
49+
const { events, reporter } = createReporter();
50+
const middleware = getBundleRequestObserverMiddleware(
51+
createProjectRoot(),
52+
createHarnessConfig(),
53+
reporter
54+
);
55+
const next = vi.fn();
56+
57+
middleware(
58+
{
59+
headers: {},
60+
url: '/index.bundle?platform=ios&dev=true',
61+
} as never,
62+
{} as never,
63+
next
64+
);
65+
66+
expect(events).toEqual([
67+
expect.objectContaining({
68+
type: 'bundle_request_observed',
69+
platform: 'ios',
70+
requestKind: 'app',
71+
url: '/index.bundle?platform=ios&dev=true',
72+
}),
73+
]);
74+
expect(next).toHaveBeenCalledTimes(1);
75+
});
76+
77+
it('tags prewarm requests using the Harness header', () => {
78+
const { events, reporter } = createReporter();
79+
const middleware = getBundleRequestObserverMiddleware(
80+
createProjectRoot(),
81+
createHarnessConfig(),
82+
reporter
83+
);
84+
85+
middleware(
86+
{
87+
headers: {
88+
[HARNESS_REQUEST_KIND_HEADER]: 'prewarm',
89+
},
90+
url: '/index.bundle?platform=android',
91+
} as never,
92+
{} as never,
93+
vi.fn()
94+
);
95+
96+
expect(events).toEqual([
97+
expect.objectContaining({
98+
platform: 'android',
99+
requestKind: 'prewarm',
100+
}),
101+
]);
102+
});
103+
104+
it('ignores non-entry bundle requests', () => {
105+
const { events, reporter } = createReporter();
106+
const middleware = getBundleRequestObserverMiddleware(
107+
createProjectRoot(),
108+
createHarnessConfig(),
109+
reporter
110+
);
111+
112+
middleware(
113+
{
114+
headers: {},
115+
url: '/other.bundle?platform=ios',
116+
} as never,
117+
{} as never,
118+
vi.fn()
119+
);
120+
121+
expect(events).toEqual([]);
122+
});
123+
});

0 commit comments

Comments
 (0)