Home Manual Reference Source Test Repository

spec-js/Subject-spec.js

"use strict";
var _this = this;
var chai_1 = require('chai');
var Rx = require('../dist/package/Rx');
var Subject = Rx.Subject;
var Observable = Rx.Observable;
/** @test {Subject} */
describe('Subject', function () {
    it('should pump values right on through itself', function (done) {
        var subject = new Subject();
        var expected = ['foo', 'bar'];
        subject.subscribe(function (x) {
            chai_1.expect(x).to.equal(expected.shift());
        }, null, done);
        subject.next('foo');
        subject.next('bar');
        subject.complete();
    });
    it('should pump values to multiple subscribers', function (done) {
        var subject = new Subject();
        var expected = ['foo', 'bar'];
        var i = 0;
        var j = 0;
        subject.subscribe(function (x) {
            chai_1.expect(x).to.equal(expected[i++]);
        });
        subject.subscribe(function (x) {
            chai_1.expect(x).to.equal(expected[j++]);
        }, null, done);
        chai_1.expect(subject.observers.length).to.equal(2);
        subject.next('foo');
        subject.next('bar');
        subject.complete();
    });
    it('should handle subscribers that arrive and leave at different times, ' +
        'subject does not complete', function () {
        var subject = new Subject();
        var results1 = [];
        var results2 = [];
        var results3 = [];
        subject.next(1);
        subject.next(2);
        subject.next(3);
        subject.next(4);
        var subscription1 = subject.subscribe(function (x) { results1.push(x); }, function (e) { results1.push('E'); }, function () { results1.push('C'); });
        subject.next(5);
        var subscription2 = subject.subscribe(function (x) { results2.push(x); }, function (e) { results2.push('E'); }, function () { results2.push('C'); });
        subject.next(6);
        subject.next(7);
        subscription1.unsubscribe();
        subject.next(8);
        subscription2.unsubscribe();
        subject.next(9);
        subject.next(10);
        var subscription3 = subject.subscribe(function (x) { results3.push(x); }, function (e) { results3.push('E'); }, function () { results3.push('C'); });
        subject.next(11);
        subscription3.unsubscribe();
        chai_1.expect(results1).to.deep.equal([5, 6, 7]);
        chai_1.expect(results2).to.deep.equal([6, 7, 8]);
        chai_1.expect(results3).to.deep.equal([11]);
    });
    it('should handle subscribers that arrive and leave at different times, ' +
        'subject completes', function () {
        var subject = new Subject();
        var results1 = [];
        var results2 = [];
        var results3 = [];
        subject.next(1);
        subject.next(2);
        subject.next(3);
        subject.next(4);
        var subscription1 = subject.subscribe(function (x) { results1.push(x); }, function (e) { results1.push('E'); }, function () { results1.push('C'); });
        subject.next(5);
        var subscription2 = subject.subscribe(function (x) { results2.push(x); }, function (e) { results2.push('E'); }, function () { results2.push('C'); });
        subject.next(6);
        subject.next(7);
        subscription1.unsubscribe();
        subject.complete();
        subscription2.unsubscribe();
        var subscription3 = subject.subscribe(function (x) { results3.push(x); }, function (e) { results3.push('E'); }, function () { results3.push('C'); });
        subscription3.unsubscribe();
        chai_1.expect(results1).to.deep.equal([5, 6, 7]);
        chai_1.expect(results2).to.deep.equal([6, 7, 'C']);
        chai_1.expect(results3).to.deep.equal(['C']);
    });
    it('should handle subscribers that arrive and leave at different times, ' +
        'subject terminates with an error', function () {
        var subject = new Subject();
        var results1 = [];
        var results2 = [];
        var results3 = [];
        subject.next(1);
        subject.next(2);
        subject.next(3);
        subject.next(4);
        var subscription1 = subject.subscribe(function (x) { results1.push(x); }, function (e) { results1.push('E'); }, function () { results1.push('C'); });
        subject.next(5);
        var subscription2 = subject.subscribe(function (x) { results2.push(x); }, function (e) { results2.push('E'); }, function () { results2.push('C'); });
        subject.next(6);
        subject.next(7);
        subscription1.unsubscribe();
        subject.error(new Error('err'));
        subscription2.unsubscribe();
        var subscription3 = subject.subscribe(function (x) { results3.push(x); }, function (e) { results3.push('E'); }, function () { results3.push('C'); });
        subscription3.unsubscribe();
        chai_1.expect(results1).to.deep.equal([5, 6, 7]);
        chai_1.expect(results2).to.deep.equal([6, 7, 'E']);
        chai_1.expect(results3).to.deep.equal(['E']);
    });
    it('should handle subscribers that arrive and leave at different times, ' +
        'subject completes before nexting any value', function () {
        var subject = new Subject();
        var results1 = [];
        var results2 = [];
        var results3 = [];
        var subscription1 = subject.subscribe(function (x) { results1.push(x); }, function (e) { results1.push('E'); }, function () { results1.push('C'); });
        var subscription2 = subject.subscribe(function (x) { results2.push(x); }, function (e) { results2.push('E'); }, function () { results2.push('C'); });
        subscription1.unsubscribe();
        subject.complete();
        subscription2.unsubscribe();
        var subscription3 = subject.subscribe(function (x) { results3.push(x); }, function (e) { results3.push('E'); }, function () { results3.push('C'); });
        subscription3.unsubscribe();
        chai_1.expect(results1).to.deep.equal([]);
        chai_1.expect(results2).to.deep.equal(['C']);
        chai_1.expect(results3).to.deep.equal(['C']);
    });
    it('should disallow new subscriber once subject has been disposed', function () {
        var subject = new Subject();
        var results1 = [];
        var results2 = [];
        var results3 = [];
        var subscription1 = subject.subscribe(function (x) { results1.push(x); }, function (e) { results1.push('E'); }, function () { results1.push('C'); });
        subject.next(1);
        subject.next(2);
        var subscription2 = subject.subscribe(function (x) { results2.push(x); }, function (e) { results2.push('E'); }, function () { results2.push('C'); });
        subject.next(3);
        subject.next(4);
        subject.next(5);
        subscription1.unsubscribe();
        subscription2.unsubscribe();
        subject.unsubscribe();
        chai_1.expect(function () {
            subject.subscribe(function (x) { results3.push(x); }, function (err) {
                chai_1.expect(false).to.equal('should not throw error: ' + err.toString());
            });
        }).to.throw(Rx.ObjectUnsubscribedError);
        chai_1.expect(results1).to.deep.equal([1, 2, 3, 4, 5]);
        chai_1.expect(results2).to.deep.equal([3, 4, 5]);
        chai_1.expect(results3).to.deep.equal([]);
    });
    it('should not allow values to be nexted after it is unsubscribed', function (done) {
        var subject = new Subject();
        var expected = ['foo'];
        subject.subscribe(function (x) {
            chai_1.expect(x).to.equal(expected.shift());
        });
        subject.next('foo');
        subject.unsubscribe();
        chai_1.expect(function () { return subject.next('bar'); }).to.throw(Rx.ObjectUnsubscribedError);
        done();
    });
    it('should clean out unsubscribed subscribers', function (done) {
        var subject = new Subject();
        var sub1 = subject.subscribe(function (x) {
            //noop
        });
        var sub2 = subject.subscribe(function (x) {
            //noop
        });
        chai_1.expect(subject.observers.length).to.equal(2);
        sub1.unsubscribe();
        chai_1.expect(subject.observers.length).to.equal(1);
        sub2.unsubscribe();
        chai_1.expect(subject.observers.length).to.equal(0);
        done();
    });
    it('should have a static create function that works', function () {
        chai_1.expect(Subject.create).to.be.a('function');
        var source = Observable.of(1, 2, 3, 4, 5);
        var nexts = [];
        var output = [];
        var error;
        var complete = false;
        var outputComplete = false;
        var destination = {
            closed: false,
            next: function (x) {
                nexts.push(x);
            },
            error: function (err) {
                error = err;
                this.closed = true;
            },
            complete: function () {
                complete = true;
                _this.closed = true;
            }
        };
        var sub = Subject.create(destination, source);
        sub.subscribe(function (x) {
            output.push(x);
        }, null, function () {
            outputComplete = true;
        });
        sub.next('a');
        sub.next('b');
        sub.next('c');
        sub.complete();
        chai_1.expect(nexts).to.deep.equal(['a', 'b', 'c']);
        chai_1.expect(complete).to.be.true;
        chai_1.expect(error).to.be.a('undefined');
        chai_1.expect(output).to.deep.equal([1, 2, 3, 4, 5]);
        chai_1.expect(outputComplete).to.be.true;
    });
    it('should have a static create function that works also to raise errors', function () {
        chai_1.expect(Subject.create).to.be.a('function');
        var source = Observable.of(1, 2, 3, 4, 5);
        var nexts = [];
        var output = [];
        var error;
        var complete = false;
        var outputComplete = false;
        var destination = {
            closed: false,
            next: function (x) {
                nexts.push(x);
            },
            error: function (err) {
                error = err;
                this.closed = true;
            },
            complete: function () {
                complete = true;
                _this.closed = true;
            }
        };
        var sub = Subject.create(destination, source);
        sub.subscribe(function (x) {
            output.push(x);
        }, null, function () {
            outputComplete = true;
        });
        sub.next('a');
        sub.next('b');
        sub.next('c');
        sub.error('boom');
        chai_1.expect(nexts).to.deep.equal(['a', 'b', 'c']);
        chai_1.expect(complete).to.be.false;
        chai_1.expect(error).to.equal('boom');
        chai_1.expect(output).to.deep.equal([1, 2, 3, 4, 5]);
        chai_1.expect(outputComplete).to.be.true;
    });
    it('should be an Observer which can be given to Observable.subscribe', function (done) {
        var source = Observable.of(1, 2, 3, 4, 5);
        var subject = new Subject();
        var expected = [1, 2, 3, 4, 5];
        subject.subscribe(function (x) {
            chai_1.expect(x).to.equal(expected.shift());
        }, function (x) {
            done(new Error('should not be called'));
        }, function () {
            done();
        });
        source.subscribe(subject);
    });
    it('should be usable as an Observer of a finite delayed Observable', function (done) {
        var source = Rx.Observable.of(1, 2, 3).delay(50);
        var subject = new Rx.Subject();
        var expected = [1, 2, 3];
        subject.subscribe(function (x) {
            chai_1.expect(x).to.equal(expected.shift());
        }, function (x) {
            done(new Error('should not be called'));
        }, function () {
            done();
        });
        source.subscribe(subject);
    });
    it('should throw ObjectUnsubscribedError when emit after unsubscribed', function () {
        var subject = new Rx.Subject();
        subject.unsubscribe();
        chai_1.expect(function () {
            subject.next('a');
        }).to.throw(Rx.ObjectUnsubscribedError);
        chai_1.expect(function () {
            subject.error('a');
        }).to.throw(Rx.ObjectUnsubscribedError);
        chai_1.expect(function () {
            subject.complete();
        }).to.throw(Rx.ObjectUnsubscribedError);
    });
    it('should not next after completed', function () {
        var subject = new Rx.Subject();
        var results = [];
        subject.subscribe(function (x) { return results.push(x); }, null, function () { return results.push('C'); });
        subject.next('a');
        subject.complete();
        subject.next('b');
        chai_1.expect(results).to.deep.equal(['a', 'C']);
    });
    it('should not next after error', function () {
        var error = new Error('wut?');
        var subject = new Rx.Subject();
        var results = [];
        subject.subscribe(function (x) { return results.push(x); }, function (err) { return results.push(err); });
        subject.next('a');
        subject.error(error);
        subject.next('b');
        chai_1.expect(results).to.deep.equal(['a', error]);
    });
    describe('asObservable', function () {
        it('should hide subject', function () {
            var subject = new Rx.Subject();
            var observable = subject.asObservable();
            chai_1.expect(subject).not.to.equal(observable);
            chai_1.expect(observable instanceof Observable).to.be.true;
            chai_1.expect(observable instanceof Subject).to.be.false;
        });
        it('should handle subject never emits', function () {
            var observable = hot('-').asObservable();
            expectObservable(observable).toBe([]);
        });
        it('should handle subject completes without emits', function () {
            var observable = hot('--^--|').asObservable();
            var expected = '---|';
            expectObservable(observable).toBe(expected);
        });
        it('should handle subject throws', function () {
            var observable = hot('--^--#').asObservable();
            var expected = '---#';
            expectObservable(observable).toBe(expected);
        });
        it('should handle subject emits', function () {
            var observable = hot('--^--x--|').asObservable();
            var expected = '---x--|';
            expectObservable(observable).toBe(expected);
        });
        it('should work with inherited subject', function () {
            var results = [];
            var subject = new Rx.AsyncSubject();
            subject.next(42);
            subject.complete();
            var observable = subject.asObservable();
            observable.subscribe(function (x) { return results.push(x); }, null, function () { return results.push('done'); });
            chai_1.expect(results).to.deep.equal([42, 'done']);
        });
    });
});
describe('AnonymousSubject', function () {
    it('should be exposed', function () {
        chai_1.expect(Rx.AnonymousSubject).to.be.a('function');
    });
    it('should not eager', function () {
        var subscribed = false;
        var subject = Rx.Subject.create(null, new Rx.Observable(function (observer) {
            subscribed = true;
            var subscription = Rx.Observable.of('x').subscribe(observer);
            return function () {
                subscription.unsubscribe();
            };
        }));
        var observable = subject.asObservable();
        chai_1.expect(subscribed).to.be.false;
        observable.subscribe();
        chai_1.expect(subscribed).to.be.true;
    });
});
//# sourceMappingURL=Subject-spec.js.map