mirror of
https://github.com/hanzoai/firebase-js-sdk.git
synced 2026-09-24 16:59:10 +00:00
252 lines
5.9 KiB
TypeScript
252 lines
5.9 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2017 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import { assert } from 'chai';
|
|
import * as sinon from 'sinon';
|
|
import { async, createSubscribe, Observer, Subscribe } from '../src/subscribe';
|
|
|
|
describe('createSubscribe', () => {
|
|
let spy: any;
|
|
beforeEach(() => {
|
|
// Listen to console.error calls.
|
|
spy = sinon.spy(console, 'error');
|
|
});
|
|
|
|
afterEach(() => {
|
|
spy.restore();
|
|
});
|
|
|
|
it('Creation', done => {
|
|
const subscribe = createSubscribe<number>((observer: Observer<number>) => {
|
|
observer.next(123);
|
|
});
|
|
|
|
const unsub = subscribe((value: number) => {
|
|
unsub();
|
|
assert.equal(value, 123);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('Logging observer error to console', done => {
|
|
const uncatchableError = new Error('uncatchable');
|
|
const subscribe = createSubscribe<number>((observer: Observer<number>) => {
|
|
observer.next(123);
|
|
observer.complete();
|
|
});
|
|
|
|
subscribe({
|
|
next(value) {
|
|
assert.equal(value, 123);
|
|
// Simulate an error is thrown in the next callback.
|
|
// This should log to the console as an error.
|
|
throw uncatchableError;
|
|
},
|
|
complete() {
|
|
// By this point, the error should have been logged.
|
|
assert.ok(spy.calledWith(uncatchableError));
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
|
|
it('Well-defined subscription order', done => {
|
|
const subscribe = createSubscribe<number>(observer => {
|
|
observer.next(123);
|
|
// Subscription after value emitted should NOT be received.
|
|
subscribe({
|
|
next(_value) {
|
|
assert.ok(false);
|
|
}
|
|
});
|
|
});
|
|
// Subscription before value emitted should be received.
|
|
subscribe({
|
|
next(_value) {
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
|
|
it('Subscribing to already complete Subscribe', done => {
|
|
let seq = 0;
|
|
const subscribe = createSubscribe<number>(observer => {
|
|
observer.next(456);
|
|
observer.complete();
|
|
});
|
|
subscribe({
|
|
next(value: number) {
|
|
assert.equal(seq++, 0);
|
|
assert.equal(value, 456);
|
|
},
|
|
complete() {
|
|
subscribe({
|
|
complete() {
|
|
assert.equal(seq++, 1);
|
|
done();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
it('Subscribing to errored Subscribe', done => {
|
|
let seq = 0;
|
|
const subscribe = createSubscribe<number>(observer => {
|
|
observer.next(246);
|
|
observer.error(new Error('failure'));
|
|
});
|
|
subscribe({
|
|
next(value: number) {
|
|
assert.equal(seq++, 0);
|
|
assert.equal(value, 246);
|
|
},
|
|
error(e) {
|
|
assert.equal(seq++, 1);
|
|
subscribe({
|
|
error(_e2) {
|
|
assert.equal(seq++, 2);
|
|
assert.equal(e.message, 'failure');
|
|
done();
|
|
}
|
|
});
|
|
},
|
|
complete() {
|
|
assert.ok(false);
|
|
}
|
|
});
|
|
});
|
|
|
|
it('Delayed value', done => {
|
|
const subscribe = createSubscribe<number>((observer: Observer<number>) => {
|
|
setTimeout(() => observer.next(123), 10);
|
|
});
|
|
|
|
subscribe((value: number) => {
|
|
assert.equal(value, 123);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('Executor throws => Error', () => {
|
|
// It's an application error to throw an exception in the executor -
|
|
// but since it is called asynchronously, our only option is
|
|
// to emit that Error and terminate the Subscribe.
|
|
const subscribe = createSubscribe<number>((_observer: Observer<number>) => {
|
|
throw new Error('Executor throws');
|
|
});
|
|
subscribe({
|
|
error(e) {
|
|
assert.equal(e.message, 'Executor throws');
|
|
}
|
|
});
|
|
});
|
|
|
|
it('Sequence', done => {
|
|
const subscribe = makeCounter(10);
|
|
|
|
let j = 1;
|
|
subscribe({
|
|
next(value: number) {
|
|
assert.equal(value, j++);
|
|
},
|
|
complete() {
|
|
assert.equal(j, 11);
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
|
|
it('unlisten', done => {
|
|
const subscribe = makeCounter(10);
|
|
|
|
subscribe({
|
|
complete: () => {
|
|
async(done)();
|
|
}
|
|
});
|
|
|
|
let j = 1;
|
|
const unsub = subscribe({
|
|
next: (value: number) => {
|
|
assert.ok(value <= 5);
|
|
assert.equal(value, j++);
|
|
if (value === 5) {
|
|
unsub();
|
|
}
|
|
},
|
|
complete: () => {
|
|
assert.ok(false, 'Does not call completed if unsubscribed');
|
|
}
|
|
});
|
|
});
|
|
|
|
it('onNoObservers', done => {
|
|
const subscribe = makeCounter(10);
|
|
|
|
let j = 1;
|
|
const unsub = subscribe({
|
|
next: (value: number) => {
|
|
assert.ok(value <= 5);
|
|
assert.equal(value, j++);
|
|
if (value === 5) {
|
|
unsub();
|
|
async(done)();
|
|
}
|
|
},
|
|
complete: () => {
|
|
assert.ok(false, 'Does not call completed if unsubscribed');
|
|
}
|
|
});
|
|
});
|
|
|
|
// TODO(koss): Add test for partial Observer (missing methods).
|
|
it('Partial Observer', done => {
|
|
const subscribe = makeCounter(10);
|
|
|
|
const _unsub = subscribe({
|
|
complete: () => {
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
function makeCounter(maxCount: number, ms = 10): Subscribe<number> {
|
|
let id: any;
|
|
|
|
return createSubscribe<number>(
|
|
(observer: Observer<number>) => {
|
|
let i = 1;
|
|
id = setInterval(() => {
|
|
observer.next(i++);
|
|
if (i > maxCount) {
|
|
if (id) {
|
|
clearInterval(id);
|
|
id = undefined;
|
|
}
|
|
observer.complete();
|
|
}
|
|
}, ms);
|
|
},
|
|
(_observer: Observer<number>) => {
|
|
clearInterval(id);
|
|
id = undefined;
|
|
}
|
|
);
|
|
}
|