or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-operations.mddisposables.mdindex.mdobservable-aggregation.mdobservable-combination.mdobservable-creation.mdobservable-filtering.mdobservable-transformation.mdschedulers.mdsubjects.mdtesting.mdtime-operations.md

testing.mddocs/

0

# Testing Support

1

2

Testing utilities for unit testing reactive code with virtual time and marble testing.

3

4

## Capabilities

5

6

### Test Scheduler

7

8

Virtual time scheduler for deterministic testing of time-based operations.

9

10

```javascript { .api }

11

/**

12

* Creates a virtual time scheduler for testing

13

* @constructor

14

* @returns {TestScheduler} New test scheduler instance

15

*/

16

function TestScheduler();

17

18

/**

19

* Creates a hot observable for testing

20

* @param {...Object} records - Array of recorded events

21

* @returns {Observable} Hot observable with specified events

22

*/

23

testScheduler.createHotObservable = function(...records);

24

25

/**

26

* Creates a cold observable for testing

27

* @param {...Object} records - Array of recorded events

28

* @returns {Observable} Cold observable with specified events

29

*/

30

testScheduler.createColdObservable = function(...records);

31

32

/**

33

* Creates a test observer

34

* @returns {Observer} Test observer that records events

35

*/

36

testScheduler.createObserver = function();

37

38

/**

39

* Starts a test with specified timing

40

* @param {function} create - Function that creates the observable to test

41

* @param {number} [created] - Time when observable is created (default: 100)

42

* @param {number} [subscribed] - Time when subscription occurs (default: 200)

43

* @param {number} [disposed] - Time when subscription is disposed (default: 1000)

44

* @returns {Object} Test result with messages and subscriptions

45

*/

46

testScheduler.start = function(create, created, subscribed, disposed);

47

```

48

49

### Reactive Test Utilities

50

51

Static utilities for creating test records and timing.

52

53

```javascript { .api }

54

/**

55

* Default timing constants for tests

56

*/

57

Rx.ReactiveTest.created = 100;

58

Rx.ReactiveTest.subscribed = 200;

59

Rx.ReactiveTest.disposed = 1000;

60

61

/**

62

* Creates an OnNext test record

63

* @param {number} ticks - Time when value is emitted

64

* @param {*} value - Value to emit

65

* @returns {Object} OnNext test record

66

*/

67

Rx.ReactiveTest.onNext = function(ticks, value);

68

69

/**

70

* Creates an OnError test record

71

* @param {number} ticks - Time when error occurs

72

* @param {*} error - Error to emit

73

* @returns {Object} OnError test record

74

*/

75

Rx.ReactiveTest.onError = function(ticks, error);

76

77

/**

78

* Creates an OnCompleted test record

79

* @param {number} ticks - Time when completion occurs

80

* @returns {Object} OnCompleted test record

81

*/

82

Rx.ReactiveTest.onCompleted = function(ticks);

83

84

/**

85

* Creates a subscription record

86

* @param {number} subscribe - Time when subscription starts

87

* @param {number} [unsubscribe] - Time when subscription ends

88

* @returns {Object} Subscription test record

89

*/

90

Rx.ReactiveTest.subscribe = function(subscribe, unsubscribe);

91

```

92

93

### Basic Testing Example

94

95

```javascript

96

// Example test using TestScheduler

97

var scheduler = new Rx.TestScheduler();

98

99

// Create test data

100

var hotObservable = scheduler.createHotObservable(

101

Rx.ReactiveTest.onNext(150, 1), // Before subscription

102

Rx.ReactiveTest.onNext(210, 2), // After subscription

103

Rx.ReactiveTest.onNext(220, 3),

104

Rx.ReactiveTest.onCompleted(230)

105

);

106

107

var coldObservable = scheduler.createColdObservable(

108

Rx.ReactiveTest.onNext(10, 'a'),

109

Rx.ReactiveTest.onNext(20, 'b'),

110

Rx.ReactiveTest.onCompleted(30)

111

);

112

113

// Test the observable

114

var result = scheduler.start(function() {

115

return hotObservable.map(function(x) { return x * 2; });

116

});

117

118

// Assert results

119

assert.deepEqual(result.messages, [

120

Rx.ReactiveTest.onNext(210, 4), // 2 * 2

121

Rx.ReactiveTest.onNext(220, 6), // 3 * 2

122

Rx.ReactiveTest.onCompleted(230)

123

]);

124

```

125

126

### Advanced Testing Patterns

127

128

Testing time-based operations:

129

130

```javascript

131

var scheduler = new Rx.TestScheduler();

132

133

var result = scheduler.start(function() {

134

return Rx.Observable.interval(100, scheduler)

135

.take(3)

136

.map(function(x) { return x + 1; });

137

});

138

139

assert.deepEqual(result.messages, [

140

Rx.ReactiveTest.onNext(300, 1), // 200 + 100 interval

141

Rx.ReactiveTest.onNext(400, 2), // 200 + 200 interval

142

Rx.ReactiveTest.onNext(500, 3), // 200 + 300 interval

143

Rx.ReactiveTest.onCompleted(500)

144

]);

145

```

146

147

### Test Observer

148

149

Observers that record all events for assertion:

150

151

```javascript { .api }

152

/**

153

* Test observer that records all events

154

* @constructor

155

* @returns {TestObserver} Test observer instance

156

*/

157

function TestObserver();

158

159

// Properties available on test observer

160

testObserver.messages; // Array of recorded events

161

testObserver.subscriptions; // Array of subscription records

162

```

163

164

**Usage Example:**

165

166

```javascript

167

var scheduler = new Rx.TestScheduler();

168

var observer = scheduler.createObserver();

169

170

var source = scheduler.createHotObservable(

171

Rx.ReactiveTest.onNext(210, 1),

172

Rx.ReactiveTest.onNext(220, 2),

173

Rx.ReactiveTest.onCompleted(230)

174

);

175

176

source.subscribe(observer);

177

scheduler.start();

178

179

// Check recorded messages

180

console.log(observer.messages);

181

// Output: [onNext(210, 1), onNext(220, 2), onCompleted(230)]

182

```

183

184

### Marble Testing Concepts

185

186

While RxJS 4 doesn't have built-in marble testing, the patterns can be simulated:

187

188

```javascript

189

// Simulate marble testing with helper functions

190

function parseMarbles(marbles, values, scheduler) {

191

var result = [];

192

var time = 0;

193

194

for (var i = 0; i < marbles.length; i++) {

195

var char = marbles[i];

196

if (char === '-') {

197

time += 10; // Frame advance

198

} else if (char === '|') {

199

result.push(Rx.ReactiveTest.onCompleted(time));

200

} else if (char === 'x') {

201

result.push(Rx.ReactiveTest.onError(time, new Error('test error')));

202

} else if (values[char]) {

203

result.push(Rx.ReactiveTest.onNext(time, values[char]));

204

time += 10;

205

}

206

}

207

208

return scheduler.createColdObservable.apply(scheduler, result);

209

}

210

211

// Usage

212

var scheduler = new Rx.TestScheduler();

213

var source = parseMarbles('a-b-c|', {a: 1, b: 2, c: 3}, scheduler);

214

```

215

216

### Error Testing

217

218

Testing error scenarios:

219

220

```javascript

221

var scheduler = new Rx.TestScheduler();

222

223

var result = scheduler.start(function() {

224

return Rx.Observable.throw(new Error('test error'), scheduler);

225

});

226

227

assert.deepEqual(result.messages, [

228

Rx.ReactiveTest.onError(200, Error('test error'))

229

]);

230

```

231

232

### Subscription Testing

233

234

Testing subscription timing:

235

236

```javascript

237

var scheduler = new Rx.TestScheduler();

238

var source = scheduler.createHotObservable(/* events */);

239

240

var subscription = source.subscribe(observer);

241

scheduler.schedule(null, 250, function() {

242

subscription.dispose();

243

});

244

245

scheduler.start();

246

247

// Check subscription was disposed at correct time

248

assert.equal(observer.subscriptions[0].unsubscribe, 250);

249

```

250

251

### Recorded and Subscription Classes

252

253

Data structures for test records and subscription timing.

254

255

```javascript { .api }

256

/**

257

* Represents a recorded notification with timing

258

* @param {number} time - Time when notification occurred

259

* @param {Object} value - Notification object (OnNext, OnError, or OnCompleted)

260

* @returns {Recorded} Recorded notification

261

*/

262

function Recorded(time, value);

263

264

/**

265

* Represents a subscription lifetime

266

* @param {number} subscribe - Time when subscription started

267

* @param {number} [unsubscribe] - Time when subscription ended

268

* @returns {Subscription} Subscription record

269

*/

270

function Subscription(subscribe, unsubscribe);

271

```

272

273

### TestScheduler Advanced Methods

274

275

Additional methods for complex testing scenarios.

276

277

```javascript { .api }

278

/**

279

* Schedules an action to run at absolute time

280

* @param {*} state - State to pass to action

281

* @param {number} dueTime - Absolute time to run action

282

* @param {function} action - Action to execute

283

* @returns {Disposable} Disposable for canceling the action

284

*/

285

testScheduler.scheduleAbsolute = function(state, dueTime, action);

286

287

/**

288

* Schedules an action to run after relative time

289

* @param {*} state - State to pass to action

290

* @param {number} dueTime - Relative time to run action

291

* @param {function} action - Action to execute

292

* @returns {Disposable} Disposable for canceling the action

293

*/

294

testScheduler.scheduleRelative = function(state, dueTime, action);

295

296

/**

297

* Schedules a recursive action

298

* @param {*} state - State to pass to action

299

* @param {number} dueTime - Time to run action

300

* @param {function} action - Recursive action to execute

301

* @returns {Disposable} Disposable for canceling the action

302

*/

303

testScheduler.scheduleRecursiveAbsolute = function(state, dueTime, action);

304

305

/**

306

* Advances the scheduler clock to specified time

307

* @param {number} time - Time to advance to

308

*/

309

testScheduler.advanceTo = function(time);

310

311

/**

312

* Advances the scheduler clock by specified amount

313

* @param {number} time - Amount of time to advance

314

*/

315

testScheduler.advanceBy = function(time);

316

317

/**

318

* Starts the scheduler and runs all scheduled actions

319

*/

320

testScheduler.start = function();

321

322

/**

323

* Stops the scheduler

324

*/

325

testScheduler.stop = function();

326

327

/**

328

* Gets the current virtual time

329

* @returns {number} Current virtual time

330

*/

331

testScheduler.clock = number;

332

```

333

334

### Mock Observer

335

336

Observer implementation for testing that records all events.

337

338

```javascript { .api }

339

/**

340

* Creates a mock observer that records events

341

* @param {TestScheduler} scheduler - Test scheduler to use for timing

342

* @returns {MockObserver} Mock observer instance

343

*/

344

function MockObserver(scheduler);

345

346

// Mock observer properties

347

mockObserver.messages; // Array of recorded Recorded objects

348

mockObserver.isDisposed; // Whether observer is disposed

349

350

// Observer interface methods

351

mockObserver.onNext = function(value);

352

mockObserver.onError = function(error);

353

mockObserver.onCompleted = function();

354

```

355

356

### Virtual Time Scheduler

357

358

Base class for test scheduler with virtual time support.

359

360

```javascript { .api }

361

/**

362

* Base virtual time scheduler

363

* @param {number} [initialClock] - Initial virtual time

364

* @returns {VirtualTimeScheduler} Virtual time scheduler

365

*/

366

function VirtualTimeScheduler(initialClock);

367

368

// Virtual time scheduler methods

369

virtualScheduler.now = function(); // Current virtual time

370

virtualScheduler.scheduleAbsolute = function(state, dueTime, action);

371

virtualScheduler.scheduleRelative = function(state, dueTime, action);

372

virtualScheduler.start = function();

373

virtualScheduler.stop = function();

374

virtualScheduler.advanceTo = function(time);

375

virtualScheduler.advanceBy = function(time);

376

```

377

378

### Historical Scheduler

379

380

Scheduler for testing with historical time data.

381

382

```javascript { .api }

383

/**

384

* Creates a historical scheduler that compares against historical data

385

* @param {number} initialClock - Initial historical time

386

* @param {function} comparer - Function to compare historical data

387

* @returns {HistoricalScheduler} Historical scheduler

388

*/

389

function HistoricalScheduler(initialClock, comparer);

390

```

391

392

### Testing Best Practices

393

394

Key patterns for effective testing:

395

396

```javascript

397

// 1. Use consistent timing constants

398

var T = Rx.ReactiveTest;

399

var scheduler = new Rx.TestScheduler();

400

401

// 2. Test both hot and cold observables

402

var hot = scheduler.createHotObservable(

403

T.onNext(150, 1), // Before subscription

404

T.onNext(210, 2), // After subscription

405

T.onCompleted(250)

406

);

407

408

var cold = scheduler.createColdObservable(

409

T.onNext(10, 'a'), // Relative to subscription

410

T.onNext(20, 'b'),

411

T.onCompleted(30)

412

);

413

414

// 3. Test error scenarios

415

var errorSource = scheduler.createColdObservable(

416

T.onNext(10, 1),

417

T.onError(20, new Error('test'))

418

);

419

420

// 4. Test subscription lifecycle

421

var result = scheduler.start(

422

function() { return source.take(2); },

423

100, // Created

424

200, // Subscribed

425

300 // Disposed

426

);

427

428

// 5. Assert both values and timing

429

assert.deepEqual(result.messages, expectedMessages);

430

assert.deepEqual(source.subscriptions, expectedSubscriptions);

431

```