or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdindex.mdpresets.mdrsc.mdtesting-utilities.md
tile.json

rsc.mddocs/

0

# React Server Components (RSC)

1

2

Jest Expo provides comprehensive testing support for React Server Components, including specialized presets, utilities for rendering RSC to flight data, and custom Jest matchers for validating RSC output.

3

4

## Capabilities

5

6

### RSC Presets

7

8

Specialized Jest preset configurations for testing React Server Components across different platforms.

9

10

#### RSC Universal Preset

11

12

```javascript { .api }

13

// In package.json or jest.config.js

14

{

15

"jest": {

16

"preset": "jest-expo/rsc"

17

}

18

}

19

```

20

21

**Features:**

22

- Multi-platform RSC testing for iOS, Android, and web

23

- React Server Component testing mode enabled

24

- Prettier snapshot formatting for RSC flight data

25

- Specialized setup for Node.js web APIs (Blob, File, ReadableStream)

26

27

#### Platform-Specific RSC Presets

28

29

```javascript { .api }

30

// Available RSC platform presets

31

"jest-expo/rsc/ios" // RSC iOS testing preset

32

"jest-expo/rsc/android" // RSC Android testing preset

33

"jest-expo/rsc/web" // RSC web testing preset

34

```

35

36

**RSC iOS Preset:**

37

- React Native test environment with RSC enabled

38

- iOS-specific snapshot resolver (`.rsc.ios.snap` files)

39

- Platform set to `ios` with React Server Component mode

40

- Uses `getIOSPreset({ isReactServer: true })`

41

42

**RSC Android Preset:**

43

- React Native test environment with RSC enabled

44

- Android-specific snapshot resolver (`.rsc.android.snap` files)

45

- Platform set to `android` with React Server Component mode

46

- Uses `getAndroidPreset({ isReactServer: true })`

47

48

**RSC Web Preset:**

49

- jsdom test environment with RSC enabled

50

- Web-specific snapshot resolver (`.rsc.web.snap` files)

51

- Platform set to `web` with React Server Component mode

52

- Uses `getWebPreset({ isReactServer: true })`

53

54

**Common RSC Features:**

55

- All presets run in Node.js test environment for RSC compatibility

56

- Test path filters to only run `__rsc_tests__` directories

57

- RSC-specific Babel transforms and bundler configurations

58

- Custom expect matchers for RSC flight data validation

59

60

### RSC Utilities

61

62

Core utilities for rendering React Server Components to flight data format for testing.

63

64

#### Stream to String

65

66

```javascript { .api }

67

/**

68

* Convert ReadableStream to string for testing

69

* @param stream - ReadableStream to convert

70

* @returns Promise that resolves to string content

71

*/

72

function streamToString(stream: ReadableStream): Promise<string>;

73

```

74

75

**Usage Example:**

76

77

```javascript

78

import { streamToString } from "jest-expo/src/rsc-utils";

79

80

test("stream conversion", async () => {

81

const stream = new ReadableStream({

82

start(controller) {

83

controller.enqueue("Hello");

84

controller.enqueue(" World");

85

controller.close();

86

}

87

});

88

89

const result = await streamToString(stream);

90

expect(result).toBe("Hello World");

91

});

92

```

93

94

#### Render JSX to Flight String

95

96

```javascript { .api }

97

/**

98

* Render JSX to RSC payload string

99

* @param jsx - React element to render

100

* @param throwOnError - Whether to throw errors during rendering

101

* @returns Promise that resolves to RSC flight string

102

*/

103

function renderJsxToFlightStringAsync(

104

jsx: React.ReactNode,

105

throwOnError?: boolean

106

): Promise<string>;

107

```

108

109

**Usage Example:**

110

111

```javascript

112

import { renderJsxToFlightStringAsync } from "jest-expo/src/rsc-utils";

113

114

test("RSC rendering", async () => {

115

const element = <div>Hello RSC</div>;

116

const flightString = await renderJsxToFlightStringAsync(element);

117

118

expect(flightString).toContain('"type":"div"');

119

expect(flightString).toContain('Hello RSC');

120

});

121

```

122

123

#### Render JSX to ReadableStream

124

125

```javascript { .api }

126

/**

127

* Render JSX to RSC ReadableStream

128

* @param jsx - React element to render

129

* @param options - Rendering options

130

* @returns Object containing ReadableStream and client boundaries

131

*/

132

function renderJsxToReadableStream(

133

jsx: React.ReactNode,

134

options?: RSCRenderOptions

135

): RSCRenderResult;

136

137

interface RSCRenderOptions {

138

onError?: (error: Error) => void;

139

}

140

141

interface RSCRenderResult {

142

stream: ReadableStream;

143

clientBoundaries: string[];

144

}

145

```

146

147

**Usage Example:**

148

149

```javascript

150

import { renderJsxToReadableStream, streamToString } from "jest-expo/src/rsc-utils";

151

152

test("RSC stream rendering", async () => {

153

const element = <div>Streaming RSC</div>;

154

const { stream, clientBoundaries } = renderJsxToReadableStream(element);

155

const result = await streamToString(stream);

156

157

expect(result).toContain("Streaming RSC");

158

expect(clientBoundaries).toEqual([]);

159

});

160

```

161

162

### RSC Jest Matchers

163

164

Custom Jest matchers specifically designed for testing React Server Components flight data.

165

166

#### toMatchFlight

167

168

```javascript { .api }

169

/**

170

* Compare RSC flight data to expected string

171

* @param expectedFlight - Expected RSC flight string

172

*/

173

expect(data: React.ReactNode | ReadableStream).toMatchFlight(expectedFlight: string);

174

```

175

176

**Features:**

177

- Accepts JSX elements, flight strings, or ReadableStreams

178

- Automatically renders JSX to flight format for comparison

179

- Provides detailed diff output for flight data mismatches

180

- Handles async stream processing

181

182

**Usage Example:**

183

184

```javascript

185

describe("RSC flight matching", () => {

186

test("JSX to flight comparison", () => {

187

const element = <div className="test">Content</div>;

188

const expectedFlight = '{"type":"div","props":{"className":"test"},"children":["Content"]}';

189

190

expect(element).toMatchFlight(expectedFlight);

191

});

192

193

test("stream to flight comparison", async () => {

194

const element = <span>Stream test</span>;

195

const stream = renderJsxToReadableStream(element);

196

const expectedFlight = '{"type":"span","props":{},"children":["Stream test"]}';

197

198

expect(stream).toMatchFlight(expectedFlight);

199

});

200

});

201

```

202

203

#### toMatchFlightSnapshot

204

205

```javascript { .api }

206

/**

207

* Compare RSC flight data to snapshot file

208

*/

209

expect(data: React.ReactNode | ReadableStream).toMatchFlightSnapshot();

210

```

211

212

**Features:**

213

- Creates RSC-specific snapshot files with platform extensions

214

- Automatically handles JSX rendering to flight format

215

- Supports RSC snapshot updates with `--updateSnapshot`

216

- Platform-specific snapshot naming (`.rsc.ios.snap`, etc.)

217

218

**Usage Example:**

219

220

```javascript

221

describe("RSC snapshot testing", () => {

222

test("component flight snapshot", () => {

223

const element = (

224

<div>

225

<h1>Title</h1>

226

<p>Description</p>

227

</div>

228

);

229

230

expect(element).toMatchFlightSnapshot();

231

});

232

233

test("async component snapshot", async () => {

234

const AsyncComponent = async () => {

235

const data = await fetchData();

236

return <div>{data.title}</div>;

237

};

238

239

const element = <AsyncComponent />;

240

expect(element).toMatchFlightSnapshot();

241

});

242

});

243

```

244

245

### RSC Setup and Configuration

246

247

#### Environment Setup

248

249

RSC presets automatically configure the test environment with necessary globals:

250

251

```javascript { .api }

252

// Automatically configured in RSC presets

253

global.__DEV__ = true;

254

global.Blob = Blob;

255

global.File = File;

256

global.ReadableStream = ReadableStream;

257

global.WritableStream = WritableStream;

258

global.TransformStream = TransformStream;

259

global.TextDecoder = TextDecoder;

260

global.TextEncoder = TextEncoder;

261

```

262

263

#### Custom RSC Test Setup

264

265

```javascript

266

// Custom RSC test setup

267

import { expect } from "@jest/globals";

268

269

// Extend Jest matchers with RSC matchers

270

declare global {

271

namespace jest {

272

interface Matchers<R> {

273

toMatchFlight(expectedFlight: string): R;

274

toMatchFlightSnapshot(): R;

275

}

276

}

277

}

278

```

279

280

### Advanced RSC Testing Patterns

281

282

#### Server Component Testing

283

284

```javascript

285

describe("Server Components", () => {

286

test("async server component", async () => {

287

const ServerComponent = async ({ userId }) => {

288

const user = await fetchUser(userId);

289

return <div>Hello {user.name}</div>;

290

};

291

292

const element = <ServerComponent userId="123" />;

293

expect(element).toMatchFlightSnapshot();

294

});

295

});

296

```

297

298

#### Client Component Boundary Testing

299

300

```javascript

301

describe("Client/Server boundaries", () => {

302

test("server component with client children", () => {

303

const ServerWrapper = ({ children }) => (

304

<div className="server-wrapper">{children}</div>

305

);

306

307

const ClientComponent = () => <button>Click me</button>;

308

309

const element = (

310

<ServerWrapper>

311

<ClientComponent />

312

</ServerWrapper>

313

);

314

315

expect(element).toMatchFlightSnapshot();

316

});

317

});

318

```

319

320

## Types

321

322

```typescript { .api }

323

// RSC utility types

324

interface RSCRenderOptions {

325

onError?: (error: Error) => void;

326

identifierPrefix?: string;

327

}

328

329

// Jest matcher interfaces

330

interface JestExpoMatchers<R> extends Record<string, any> {

331

/**

332

* Compare RSC flight data to expected string

333

*/

334

toMatchFlight(expectedFlight: string): R;

335

336

/**

337

* Compare RSC flight data to snapshot file

338

*/

339

toMatchFlightSnapshot(): R;

340

}

341

342

// RSC utility function types

343

declare function streamToString(stream: ReadableStream): Promise<string>;

344

345

declare function renderJsxToFlightStringAsync(

346

jsx: React.ReactNode,

347

throwOnError?: boolean

348

): Promise<string>;

349

350

declare function renderJsxToReadableStream(

351

jsx: React.ReactNode,

352

options?: RSCRenderOptions

353

): RSCRenderResult;

354

355

// RSC utility interfaces

356

interface RSCRenderOptions {

357

onError?: (error: Error) => void;

358

}

359

360

interface RSCRenderResult {

361

stream: ReadableStream;

362

clientBoundaries: string[];

363

}

364

365

// Global extensions for RSC testing

366

declare global {

367

namespace jest {

368

interface Matchers<R> extends JestExpoMatchers<R> {}

369

interface Expect extends JestExpoMatchers<any> {}

370

interface InverseAsymmetricMatchers extends Expect {}

371

}

372

}

373

374

// React Server Component types

375

type ServerComponent<P = {}> = (props: P) => Promise<React.ReactElement>;

376

type ClientComponent<P = {}> = React.ComponentType<P>;

377

378

interface RSCFlightData {

379

type: string;

380

props: Record<string, any>;

381

children?: React.ReactNode[];

382

}

383

```