rxjs-marbles
Advanced tools
Comparing version 3.0.0-rc.4 to 3.0.0
@@ -0,1 +1,22 @@ | ||
<a name="3.0.0"></a> | ||
## [3.0.0](https://github.com/cartant/rxjs-marbles/compare/v2.4.1...v3.0.0) (2018-04-25) | ||
### Features | ||
* Upgrade to RxJS version 6. | ||
<a name="2.4.1"></a> | ||
## [2.4.1](https://github.com/cartant/rxjs-marbles/compare/v2.4.0...v2.4.1) (2018-04-11) | ||
### Bug fixes | ||
* **reframe**: Fix import case. ([651fe31](https://github.com/cartant/rxjs-marbles/commit/651fe31)) | ||
<a name="2.4.0"></a> | ||
## [2.4.0](https://github.com/cartant/rxjs-marbles/compare/v2.3.3...v2.4.0) (2018-04-11) | ||
### Features | ||
* **reframe**: Add `reframe` to the `Context` to allow amount of virtual time per frame/character to be specified. ([15ef0e9](https://github.com/cartant/rxjs-marbles/commit/15ef0e9)) | ||
<a name="2.3.3"></a> | ||
@@ -2,0 +23,0 @@ ## [2.3.3](https://github.com/cartant/rxjs-marbles/compare/v2.3.2...v2.3.3) (2018-03-29) |
@@ -32,5 +32,5 @@ import { Observable, SchedulerLike } from "rxjs"; | ||
}, error?: any): TestObservableLike<T>; | ||
reframe(framesPerCharacter: number, maxFrames?: number): void; | ||
reframe(timePerFrame: number, maxTime?: number): void; | ||
teardown(): void; | ||
time(marbles: string): number; | ||
} |
@@ -95,14 +95,16 @@ "use strict"; | ||
}; | ||
Context.prototype.reframe = function (framesPerCharacter, maxFrames) { | ||
Context.prototype.reframe = function (timePerFrame, maxTime) { | ||
if (!this.reframable_) { | ||
throw new Error("Cannot reframe; scheduler already used."); | ||
} | ||
if (maxFrames === undefined) { | ||
maxFrames = framesPerCharacter * 75; | ||
if (maxTime === undefined) { | ||
maxTime = timePerFrame * 75; | ||
} | ||
this.frameTimeFactor_ = rxjs_1.VirtualTimeScheduler.frameTimeFactor; | ||
rxjs_1.VirtualTimeScheduler.frameTimeFactor = framesPerCharacter; | ||
testing_1.TestScheduler.frameTimeFactor = framesPerCharacter; | ||
this.frameTimeFactor_ = | ||
rxjs_1.VirtualTimeScheduler.frameTimeFactor || | ||
testing_1.TestScheduler.frameTimeFactor; | ||
rxjs_1.VirtualTimeScheduler.frameTimeFactor = timePerFrame; | ||
testing_1.TestScheduler.frameTimeFactor = timePerFrame; | ||
var scheduler = this.scheduler; | ||
scheduler.maxFrames = maxFrames; | ||
scheduler.maxFrames = maxTime; | ||
}; | ||
@@ -109,0 +111,0 @@ Context.prototype.teardown = function () { |
@@ -84,14 +84,16 @@ import { animationFrameScheduler, asapScheduler, asyncScheduler, queueScheduler, VirtualTimeScheduler } from "rxjs"; | ||
} | ||
reframe(framesPerCharacter, maxFrames) { | ||
reframe(timePerFrame, maxTime) { | ||
if (!this.reframable_) { | ||
throw new Error("Cannot reframe; scheduler already used."); | ||
} | ||
if (maxFrames === undefined) { | ||
maxFrames = framesPerCharacter * 75; | ||
if (maxTime === undefined) { | ||
maxTime = timePerFrame * 75; | ||
} | ||
this.frameTimeFactor_ = VirtualTimeScheduler.frameTimeFactor; | ||
VirtualTimeScheduler.frameTimeFactor = framesPerCharacter; | ||
TestScheduler.frameTimeFactor = framesPerCharacter; | ||
this.frameTimeFactor_ = | ||
VirtualTimeScheduler.frameTimeFactor || | ||
TestScheduler.frameTimeFactor; | ||
VirtualTimeScheduler.frameTimeFactor = timePerFrame; | ||
TestScheduler.frameTimeFactor = timePerFrame; | ||
const { scheduler } = this; | ||
scheduler.maxFrames = maxFrames; | ||
scheduler.maxFrames = maxTime; | ||
} | ||
@@ -98,0 +100,0 @@ teardown() { |
@@ -93,14 +93,16 @@ import { animationFrameScheduler, asapScheduler, asyncScheduler, queueScheduler, VirtualTimeScheduler } from "rxjs"; | ||
}; | ||
Context.prototype.reframe = function (framesPerCharacter, maxFrames) { | ||
Context.prototype.reframe = function (timePerFrame, maxTime) { | ||
if (!this.reframable_) { | ||
throw new Error("Cannot reframe; scheduler already used."); | ||
} | ||
if (maxFrames === undefined) { | ||
maxFrames = framesPerCharacter * 75; | ||
if (maxTime === undefined) { | ||
maxTime = timePerFrame * 75; | ||
} | ||
this.frameTimeFactor_ = VirtualTimeScheduler.frameTimeFactor; | ||
VirtualTimeScheduler.frameTimeFactor = framesPerCharacter; | ||
TestScheduler.frameTimeFactor = framesPerCharacter; | ||
this.frameTimeFactor_ = | ||
VirtualTimeScheduler.frameTimeFactor || | ||
TestScheduler.frameTimeFactor; | ||
VirtualTimeScheduler.frameTimeFactor = timePerFrame; | ||
TestScheduler.frameTimeFactor = timePerFrame; | ||
var scheduler = this.scheduler; | ||
scheduler.maxFrames = maxFrames; | ||
scheduler.maxFrames = maxTime; | ||
}; | ||
@@ -107,0 +109,0 @@ Context.prototype.teardown = function () { |
@@ -33,7 +33,7 @@ { | ||
"peerDependencies": { | ||
"rxjs": "^6.0.0-rc.0" | ||
"rxjs": "^6.0.0" | ||
}, | ||
"private": false, | ||
"publishConfig": { | ||
"tag": "rc" | ||
"tag": "latest" | ||
}, | ||
@@ -47,4 +47,4 @@ "repository": { | ||
"unpkg": "./bundles/rxjs-marbles.umd.js", | ||
"version": "3.0.0-rc.4", | ||
"version": "3.0.0", | ||
"ava": {} | ||
} |
176
README.md
@@ -40,20 +40,25 @@ # rxjs-marbles | ||
### With Jasmine and Mocha | ||
`rxjs-marbles` contains framework-specific import locations. If there is a location for the test framework that you are using, you should use the specific import. Doing so will ensure that you receive the best possible integration with your test framework. | ||
For example, importing from `"rxjs-marbles/jest"` will ensure that Jest's matcher is used and the output for test failures will be much prettier. | ||
### With Mocha | ||
Instead of passing your test function directly to `it`, pass it to the library's `marbles` function, like this: | ||
```ts | ||
import { marbles } from "rxjs-marbles"; | ||
import { marbles } from "rxjs-marbles/mocha"; | ||
import { map } from "rxjs/operators"; | ||
describe("rxjs-marbles", () => { | ||
it("should support marble tests", marbles((m) => { | ||
it("should support marble tests", marbles(m => { | ||
const values = { a: 1, b: 2, c: 3, d: 4 }; | ||
const source = m.hot("--^-a-b-c-|", values); | ||
const source = m.hot("--^-a-b-c-|"); | ||
const subs = "^-------!"; | ||
const expected = m.cold("--b-c-d-|", values); | ||
const expected = "--b-c-d-|"; | ||
const destination = source.map((value) => value + 1); | ||
const destination = source.pipe( | ||
map(value => String.fromCharCode(value.charCodeAt(0) + 1)) | ||
); | ||
m.expect(destination).toBeObservable(expected); | ||
@@ -65,90 +70,8 @@ m.expect(source).toHaveSubscriptions(subs); | ||
### With Jest | ||
### With other test frameworks | ||
Instead of passing your test function directly to Jest, pass it to the library's `marbles` function: | ||
To see how `rxjs-marbles` can be used with other test frameworks, see the [examples](./examples) within the repository. | ||
```ts | ||
import { marbles } from "rxjs-marbles"; | ||
With AVA and Tape, the callback passed to the `marbles` function will receive an addional argument - the AVA `TestContext` or the Tape `Test` - which can be used to specify the number of assertions in the test plan. See the framework-specific examples for details. | ||
test("it should support marble tests", marbles((m) => { | ||
const values = { a: 1, b: 2, c: 3, d: 4 }; | ||
const source = m.hot("--^-a-b-c-|", values); | ||
const subs = "^-------!"; | ||
const expected = m.cold("--b-c-d-|", values); | ||
const destination = source.map((value) => value + 1); | ||
m.expect(destination).toBeObservable(expected); | ||
m.expect(source).toHaveSubscriptions(subs); | ||
})); | ||
``` | ||
### With AVA | ||
Instead of passing your test function directly to AVA, pass it to the library's `marbles` function. The `marbles` function will concatenate the additional `TestContext` argument it receives from AVA. | ||
There is an `/ava` directory in the package that includes a wrapper that will correctly type additional argument and will call `configure` - passing AVA's assertion methods to ensure marble assertions will be counted towards AVA's `plan` - so be sure to specify `rxjs-marbles/ava` in the `import` statement or `require` call: | ||
```ts | ||
import { test } from "ava"; | ||
import { marbles } from "rxjs-marbles/ava"; | ||
test("it should support marble tests", marbles((m, t) => { | ||
t.plan(2); | ||
const values = { a: 1, b: 2, c: 3, d: 4 }; | ||
const source = m.hot("--^-a-b-c-|", values); | ||
const subs = "^-------!"; | ||
const expected = m.cold("--b-c-d-|", values); | ||
const destination = source.map((value) => value + 1); | ||
m.expect(destination).toBeObservable(expected); | ||
m.expect(source).toHaveSubscriptions(subs); | ||
})); | ||
``` | ||
### With Tape | ||
Instead of passing your test function directly to Tape, pass it to the library's `marbles` function. The `marbles` function will concatenate the additional `Test` argument it receives from Tape. | ||
There is a `/tape` directory in the package that includes a wrapper that will correctly type additional argument and will call `configure` - passing Tape's assertion methods to ensure marble assertions will be counted towards Tape's `plan` - so be sure to specify `rxjs-marbles/tape` in the `import` statement or `require` call: | ||
```ts | ||
import * as tape from "tape"; | ||
import { marbles } from "rxjs-marbles/tape"; | ||
tape("it should support marble tests", marbles((m, t) => { | ||
t.plan(2); | ||
const values = { a: 1, b: 2, c: 3, d: 4 }; | ||
const source = m.hot("--^-a-b-c-|", values); | ||
const subs = "^-------!"; | ||
const expected = m.cold("--b-c-d-|", values); | ||
const destination = source.map((value) => value + 1); | ||
m.expect(destination).toBeObservable(expected); | ||
m.expect(source).toHaveSubscriptions(subs); | ||
})); | ||
``` | ||
### Alternate assertion methods | ||
If the BDD syntax is something you really don't like, there are some alternative methods on the `Context` that are more terse: | ||
```ts | ||
const source = m.hot("--^-a-b-c-|", values); | ||
const subs = "^-------!"; | ||
const expected = m.cold("--b-c-d-|", values); | ||
const destination = source.map((value) => value + 1); | ||
m.equal(destination, expected); | ||
m.has(source, subs); | ||
``` | ||
### Using cases for test variations | ||
@@ -158,6 +81,7 @@ | ||
The `cases` implementation is framework-specific, so the import should specify the framework. For example, with Jasmine, you would import `cases` and use it instead of the `it` function, like this: | ||
The `cases` implementation is framework-specific, so the import must specify the framework. For example, with Mocha, you would import `cases` and use it instead of the `it` function, like this: | ||
```ts | ||
import { cases } from "rxjs-marbles/jasmine"; | ||
import { cases } from "rxjs-marbles/mocha"; | ||
import { map } from "rxjs/operators"; | ||
@@ -168,7 +92,7 @@ describe("rxjs-marbles", () => { | ||
const values = { a: 1, b: 2, c: 3, d: 4 }; | ||
const source = m.hot(c.s, values); | ||
const expected = m.cold(c.e, values); | ||
const destination = source.map((value) => value + 1); | ||
m.expect(destination).toBeObservable(expected); | ||
const source = m.hot(c.s); | ||
const destination = source.pipe( | ||
map(value => String.fromCharCode(value.charCodeAt(0) + 1)) | ||
); | ||
m.expect(destination).toBeObservable(c.e); | ||
@@ -188,29 +112,2 @@ }, { | ||
With AVA and Tape, the `cases` function also receives the test context. For example, with AVA, you would import `cases` and use it instead of the `test` function, like this: | ||
```ts | ||
import { cases } from "rxjs-marbles/ava"; | ||
cases("should support cases", (m, c, t) => { | ||
t.plan(1); | ||
const values = { a: 1, b: 2, c: 3, d: 4 }; | ||
const source = m.hot(c.s, values); | ||
const expected = m.cold(c.e, values); | ||
const destination = source.map((value) => value + 1); | ||
m.equal(destination, expected); | ||
}, { | ||
"non-empty": { | ||
s: "-a-b-c-|", | ||
e: "-b-c-d-|" | ||
}, | ||
"empty": { | ||
s: "-|", | ||
e: "-|" | ||
} | ||
}); | ||
``` | ||
### Dealing with deeply-nested schedulers | ||
@@ -225,3 +122,3 @@ | ||
```ts | ||
it("should support binding non-test schedulers", marbles((m) => { | ||
it("should support binding non-test schedulers", marbles(m => { | ||
@@ -241,2 +138,24 @@ m.bind(); | ||
### Changing the time per frame | ||
The RxJS `TestScheduler` defaults to 10 virtual milliseconds per frame (each character in the diagram represents a frame) with a maximum of 750 virtual milliseconds for each test. | ||
If the default is not suitable for your test, you can change it by calling the context's `reframe` method, specifying the time per frame and the (optional) maximum time. The `reframe` method must be called before any of the `cold`, `flush`, `hot` or `time` methods are called. | ||
The [examples](./examples) include tests that use `reframe`. | ||
### Alternate assertion methods | ||
If the BDD syntax is something you really don't like, there are some alternative methods on the `Context` that are more terse: | ||
```ts | ||
const source = m.hot("--^-a-b-c-|", values); | ||
const subs = "^-------!"; | ||
const expected = m.cold("--b-c-d-|", values); | ||
const destination = source.map((value) => value + 1); | ||
m.equal(destination, expected); | ||
m.has(source, subs); | ||
``` | ||
## API | ||
@@ -294,2 +213,3 @@ | ||
hot<T = any>(marbles: string, values?: any, error?: any): HotObservable<T>; | ||
reframe(timePerFrame: number, maxTime?: number): void; | ||
readonly scheduler: TestScheduler; | ||
@@ -296,0 +216,0 @@ teardown(): void; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
867806
8726
0
217