or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-scheduling.mdindex.mdpriority-management.mdprofiling.mdtesting-utilities.mdtiming-yielding.md

testing-utilities.mddocs/

0

# Testing Utilities

1

2

Mock scheduler functions specifically designed for testing environments, providing deterministic time control and task execution for reliable unit tests.

3

4

These utilities are available from the `scheduler/unstable_mock` entry point and provide a controllable scheduler implementation.

5

6

## Capabilities

7

8

### Flush All

9

10

Flushes all scheduled work immediately, completing all pending tasks.

11

12

```javascript { .api }

13

/**

14

* Flush all scheduled work immediately

15

* Throws error if any tasks yield values during execution

16

*/

17

function unstable_flushAll(): void;

18

```

19

20

**Usage Examples:**

21

22

```javascript

23

import {

24

unstable_scheduleCallback,

25

unstable_NormalPriority

26

} from "scheduler/unstable_mock";

27

import { unstable_flushAll } from "scheduler/unstable_mock";

28

29

// Schedule multiple tasks

30

unstable_scheduleCallback(unstable_NormalPriority, () => {

31

console.log("Task 1");

32

});

33

34

unstable_scheduleCallback(unstable_NormalPriority, () => {

35

console.log("Task 2");

36

});

37

38

// Execute all tasks immediately

39

unstable_flushAll();

40

// Output: "Task 1", "Task 2"

41

```

42

43

### Flush Expired

44

45

Executes only tasks that have exceeded their timeout, leaving non-expired tasks in the queue.

46

47

```javascript { .api }

48

/**

49

* Flush only expired tasks based on current mock time

50

*/

51

function unstable_flushExpired(): void;

52

```

53

54

**Usage Examples:**

55

56

```javascript

57

import {

58

unstable_scheduleCallback,

59

unstable_UserBlockingPriority,

60

unstable_LowPriority,

61

unstable_advanceTime,

62

unstable_flushExpired,

63

reset

64

} from "scheduler/unstable_mock";

65

66

reset(); // Start with clean state

67

68

// Schedule tasks with different priorities

69

unstable_scheduleCallback(unstable_UserBlockingPriority, () => {

70

console.log("High priority task");

71

});

72

73

unstable_scheduleCallback(unstable_LowPriority, () => {

74

console.log("Low priority task");

75

});

76

77

// Advance time past UserBlocking timeout (250ms) but not Low timeout (10000ms)

78

unstable_advanceTime(300);

79

80

// Only the expired high-priority task will execute

81

unstable_flushExpired();

82

// Output: "High priority task"

83

84

// Low priority task is still pending

85

unstable_flushAll();

86

// Output: "Low priority task"

87

```

88

89

### Advance Time

90

91

Advances the mock time and triggers any timers that should fire.

92

93

```javascript { .api }

94

/**

95

* Advance mock time by specified milliseconds

96

* @param ms - Milliseconds to advance the mock time

97

*/

98

function unstable_advanceTime(ms: number): void;

99

```

100

101

**Usage Examples:**

102

103

```javascript

104

import {

105

unstable_scheduleCallback,

106

unstable_NormalPriority,

107

unstable_advanceTime,

108

unstable_flushExpired,

109

unstable_now,

110

reset

111

} from "scheduler/unstable_mock";

112

113

reset();

114

115

console.log("Start time:", unstable_now()); // 0

116

117

// Schedule delayed task

118

unstable_scheduleCallback(

119

unstable_NormalPriority,

120

() => console.log("Delayed task executed"),

121

{ delay: 1000 }

122

);

123

124

// Advance time but not enough to trigger task

125

unstable_advanceTime(500);

126

console.log("Time after 500ms:", unstable_now()); // 500

127

unstable_flushExpired(); // No output - task not ready

128

129

// Advance time to trigger the delayed task

130

unstable_advanceTime(500);

131

console.log("Time after 1000ms:", unstable_now()); // 1000

132

unstable_flushExpired();

133

// Output: "Delayed task executed"

134

```

135

136

### Reset

137

138

Resets the mock scheduler to its initial state, clearing all tasks and resetting time.

139

140

```javascript { .api }

141

/**

142

* Reset scheduler to initial state

143

* Clears all scheduled tasks and resets mock time to 0

144

*/

145

function reset(): void;

146

```

147

148

**Usage Examples:**

149

150

```javascript

151

import {

152

unstable_scheduleCallback,

153

unstable_NormalPriority,

154

unstable_advanceTime,

155

unstable_now,

156

unstable_hasPendingWork,

157

reset

158

} from "scheduler/unstable_mock";

159

160

// Schedule some work and advance time

161

unstable_scheduleCallback(unstable_NormalPriority, () => {

162

console.log("This task will be cleared");

163

});

164

165

unstable_advanceTime(5000);

166

console.log("Time before reset:", unstable_now()); // 5000

167

console.log("Has pending work:", unstable_hasPendingWork()); // true

168

169

// Reset everything

170

reset();

171

172

console.log("Time after reset:", unstable_now()); // 0

173

console.log("Has pending work:", unstable_hasPendingWork()); // false

174

175

// Test isolation

176

function testCase1() {

177

reset(); // Ensure clean state

178

// Test implementation

179

}

180

181

function testCase2() {

182

reset(); // Ensure clean state

183

// Test implementation

184

}

185

```

186

187

### Flush Number of Yields

188

189

Flushes work until a specific number of yields have occurred, useful for testing time-sliced operations.

190

191

```javascript { .api }

192

/**

193

* Flush work until specified number of yields

194

* @param count - Number of yields to allow before stopping

195

*/

196

function unstable_flushNumberOfYields(count: number): void;

197

```

198

199

**Usage Examples:**

200

201

```javascript

202

import {

203

unstable_scheduleCallback,

204

unstable_NormalPriority,

205

unstable_flushNumberOfYields,

206

log,

207

unstable_clearLog,

208

reset

209

} from "scheduler/unstable_mock";

210

211

reset();

212

213

// Schedule work that yields values

214

unstable_scheduleCallback(unstable_NormalPriority, () => {

215

log("Step 1");

216

return () => {

217

log("Step 2");

218

return () => {

219

log("Step 3");

220

};

221

};

222

});

223

224

// Flush only first yield

225

unstable_flushNumberOfYields(1);

226

console.log(unstable_clearLog()); // ["Step 1"]

227

228

// Flush next yield

229

unstable_flushNumberOfYields(1);

230

console.log(unstable_clearLog()); // ["Step 2"]

231

232

// Flush final yield

233

unstable_flushNumberOfYields(1);

234

console.log(unstable_clearLog()); // ["Step 3"]

235

```

236

237

### Additional Testing Utilities

238

239

#### Has Pending Work

240

241

```javascript { .api }

242

/**

243

* Check if there are pending scheduled tasks

244

* @returns true if tasks are pending, false otherwise

245

*/

246

function unstable_hasPendingWork(): boolean;

247

```

248

249

#### Clear Log

250

251

```javascript { .api }

252

/**

253

* Clear and return the current yield log

254

* @returns Array of values that were logged during task execution

255

*/

256

function unstable_clearLog(): Array<mixed>;

257

```

258

259

#### Log

260

261

```javascript { .api }

262

/**

263

* Log a value during task execution for testing purposes

264

* @param value - Value to log for later retrieval

265

*/

266

function log(value: mixed): void;

267

```

268

269

#### Flush Until Next Paint

270

271

```javascript { .api }

272

/**

273

* Flush work until a paint is requested

274

* @returns false when completed

275

*/

276

function unstable_flushUntilNextPaint(): false;

277

```

278

279

#### Flush All Without Asserting

280

281

```javascript { .api }

282

/**

283

* Flush all work without assertion checks

284

* @returns true if work was flushed, false if no work was pending

285

*/

286

function unstable_flushAllWithoutAsserting(): boolean;

287

```

288

289

#### Set Disable Yield Value

290

291

```javascript { .api }

292

/**

293

* Control whether yield values are logged

294

* @param newValue - true to disable logging, false to enable

295

*/

296

function unstable_setDisableYieldValue(newValue: boolean): void;

297

```

298

299

## Testing Patterns

300

301

### Basic Test Setup

302

303

```javascript

304

import {

305

unstable_scheduleCallback,

306

unstable_NormalPriority,

307

unstable_flushAll,

308

reset

309

} from "scheduler/unstable_mock";

310

311

describe("Scheduler tests", () => {

312

beforeEach(() => {

313

reset(); // Clean slate for each test

314

});

315

316

test("basic task execution", () => {

317

let executed = false;

318

319

unstable_scheduleCallback(unstable_NormalPriority, () => {

320

executed = true;

321

});

322

323

expect(executed).toBe(false);

324

unstable_flushAll();

325

expect(executed).toBe(true);

326

});

327

});

328

```

329

330

### Testing Time-Based Behavior

331

332

```javascript

333

import {

334

unstable_scheduleCallback,

335

unstable_UserBlockingPriority,

336

unstable_advanceTime,

337

unstable_flushExpired,

338

unstable_now,

339

reset

340

} from "scheduler/unstable_mock";

341

342

test("priority timeout behavior", () => {

343

reset();

344

345

let didTimeout = null;

346

347

unstable_scheduleCallback(unstable_UserBlockingPriority, (timeout) => {

348

didTimeout = timeout;

349

});

350

351

// Don't advance time - task shouldn't timeout

352

unstable_flushExpired();

353

expect(didTimeout).toBe(false);

354

355

reset();

356

357

unstable_scheduleCallback(unstable_UserBlockingPriority, (timeout) => {

358

didTimeout = timeout;

359

});

360

361

// Advance past UserBlocking timeout (250ms)

362

unstable_advanceTime(300);

363

unstable_flushExpired();

364

expect(didTimeout).toBe(true);

365

});

366

```

367

368

### Testing Yielding Behavior

369

370

```javascript

371

import {

372

unstable_scheduleCallback,

373

unstable_NormalPriority,

374

unstable_flushNumberOfYields,

375

log,

376

unstable_clearLog,

377

reset

378

} from "scheduler/unstable_mock";

379

380

test("task yielding", () => {

381

reset();

382

383

unstable_scheduleCallback(unstable_NormalPriority, () => {

384

log("A");

385

return () => {

386

log("B");

387

return () => {

388

log("C");

389

};

390

};

391

});

392

393

// Execute one yield at a time

394

unstable_flushNumberOfYields(1);

395

expect(unstable_clearLog()).toEqual(["A"]);

396

397

unstable_flushNumberOfYields(1);

398

expect(unstable_clearLog()).toEqual(["B"]);

399

400

unstable_flushNumberOfYields(1);

401

expect(unstable_clearLog()).toEqual(["C"]);

402

});

403

```