Home Manual Reference Source Test Repository

spec-js/operators/find-spec.js

"use strict";
var chai_1 = require('chai');
var Rx = require('../../dist/package/Rx');
var Observable = Rx.Observable;
/** @test {find} */
describe('Observable.prototype.find', function () {
    function truePredicate(x) {
        return true;
    }
    asDiagram('find(x => x % 5 === 0)')('should return matching element from source emits single element', function () {
        var values = { a: 3, b: 9, c: 15, d: 20 };
        var source = hot('---a--b--c--d---|', values);
        var subs = '^        !       ';
        var expected = '---------(c|)    ';
        var predicate = function (x) { return x % 5 === 0; };
        expectObservable(source.find(predicate)).toBe(expected, values);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should throw if not provided a function', function () {
        chai_1.expect(function () {
            Observable.of('yut', 'yee', 'sam').find('yee');
        }).to.throw(TypeError, 'predicate is not a function');
    });
    it('should not emit if source does not emit', function () {
        var source = hot('-');
        var subs = '^';
        var expected = '-';
        expectObservable(source.find(truePredicate)).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should return undefined if source is empty to match predicate', function () {
        var source = cold('|');
        var subs = '(^!)';
        var expected = '(x|)';
        var result = source.find(truePredicate);
        expectObservable(result).toBe(expected, { x: undefined });
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should return matching element from source emits single element', function () {
        var source = hot('--a--|');
        var subs = '^ !';
        var expected = '--(a|)';
        var predicate = function (value) {
            return value === 'a';
        };
        expectObservable(source.find(predicate)).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should return matching element from source emits multiple elements', function () {
        var source = hot('--a--b---c-|');
        var subs = '^    !';
        var expected = '-----(b|)';
        var predicate = function (value) {
            return value === 'b';
        };
        expectObservable(source.find(predicate)).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should work with a custom thisArg', function () {
        var source = hot('--a--b---c-|');
        var subs = '^    !';
        var expected = '-----(b|)';
        var finder = {
            target: 'b'
        };
        var predicate = function (value) {
            return value === this.target;
        };
        expectObservable(source.find(predicate, finder)).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should return undefined if element does not match with predicate', function () {
        var source = hot('--a--b--c--|');
        var subs = '^          !';
        var expected = '-----------(x|)';
        var predicate = function (value) {
            return value === 'z';
        };
        expectObservable(source.find(predicate)).toBe(expected, { x: undefined });
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should allow unsubscribing early and explicitly', function () {
        var source = hot('--a--b--c--|');
        var subs = '^     !     ';
        var expected = '-------     ';
        var unsub = '      !     ';
        var result = source.find(function (value) { return value === 'z'; });
        expectObservable(result, unsub).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should not break unsubscription chains when result is unsubscribed explicitly', function () {
        var source = hot('--a--b--c--|');
        var subs = '^     !     ';
        var expected = '-------     ';
        var unsub = '      !     ';
        var result = source
            .mergeMap(function (x) { return Observable.of(x); })
            .find(function (value) { return value === 'z'; })
            .mergeMap(function (x) { return Observable.of(x); });
        expectObservable(result, unsub).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should raise if source raise error while element does not match with predicate', function () {
        var source = hot('--a--b--#');
        var subs = '^       !';
        var expected = '--------#';
        var predicate = function (value) {
            return value === 'z';
        };
        expectObservable(source.find(predicate)).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should raise error if predicate throws error', function () {
        var source = hot('--a--b--c--|');
        var subs = '^ !';
        var expected = '--#';
        var predicate = function (value) {
            throw 'error';
        };
        expectObservable(source.find(predicate)).toBe(expected);
        expectSubscriptions(source.subscriptions).toBe(subs);
    });
    it('should support type guards without breaking previous behavior', function () {
        // tslint:disable no-unused-variable
        // type guards with interfaces and classes
        {
            var Foo = (function () {
                function Foo(bar, baz) {
                    if (bar === void 0) { bar = 'name'; }
                    if (baz === void 0) { baz = 42; }
                    this.bar = bar;
                    this.baz = baz;
                }
                return Foo;
            }());
            var isBar = function (x) { return x && x.bar !== undefined; };
            var isBaz = function (x) { return x && x.baz !== undefined; };
            var foo = new Foo();
            Observable.of(foo).find(function (foo) { return foo.baz === 42; })
                .subscribe(function (x) { return x.baz; }); // x is still Foo
            Observable.of(foo).find(isBar)
                .subscribe(function (x) { return x.bar; }); // x is Bar!
            var foobar = new Foo(); // type is interface, not the class
            Observable.of(foobar).find(function (foobar) { return foobar.bar === 'name'; })
                .subscribe(function (x) { return x.bar; }); // <-- x is still Bar
            Observable.of(foobar).find(isBar)
                .subscribe(function (x) { return x.bar; }); // <--- x is Bar!
            var barish = { bar: 'quack', baz: 42 }; // type can quack like a Bar
            Observable.of(barish).find(function (x) { return x.bar === 'quack'; })
                .subscribe(function (x) { return x.bar; }); // x is still { bar: string; baz: number; }
            Observable.of(barish).find(isBar)
                .subscribe(function (bar) { return bar.bar; }); // x is Bar!
        }
        // type guards with primitive types
        {
            var xs = Observable.from([1, 'aaa', 3, 'bb']);
            // This type guard will narrow a `string | number` to a string in the examples below
            var isString = function (x) { return typeof x === 'string'; };
            xs.find(isString)
                .subscribe(function (s) { return s.length; }); // s is string
            // In contrast, this type of regular boolean predicate still maintains the original type
            xs.find(function (x) { return typeof x === 'number'; })
                .subscribe(function (x) { return x; }); // x is still string | number
            xs.find(function (x, i) { return typeof x === 'number' && x > i; })
                .subscribe(function (x) { return x; }); // x is still string | number
        }
        // tslint:disable enable
    });
});
//# sourceMappingURL=find-spec.js.map