Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 93 additions & 25 deletions src/database/query_observable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ function scalarQueryTest(query: Query, done: any) {
}

function observableQueryTest(query: Query, nextProp: any, done: any) {
const nextSpy = jasmine.createSpy('next');
const queryObservable = observeQuery(query);
const toMerge: any = {};
queryObservable.subscribe(nextSpy);
queryObservable.subscribe(result => {
const merged = Object.assign(query, toMerge);
expect(result).toEqual(merged);
done();
});
Object.keys(nextProp).forEach(prop => {
query[prop].next(nextProp[prop]);
toMerge[prop] = nextProp[prop];
})
const merged = Object.assign(query, toMerge);
expect(nextSpy).toHaveBeenCalledWith(merged);
done();
});
}

describe('observeQuery', () => {
Expand All @@ -37,7 +37,7 @@ describe('observeQuery', () => {
var nextSpy = jasmine.createSpy('next');
var completeSpy = jasmine.createSpy('complete');
var query = { orderByChild: 'height', equalTo: 10 };
var obs = observeQuery(query);
var obs = observeQuery(query, false);
obs.subscribe(nextSpy, null, completeSpy);
expect(nextSpy).toHaveBeenCalledWith({
orderByChild: 'height',
Expand All @@ -50,7 +50,7 @@ describe('observeQuery', () => {
var nextSpy = jasmine.createSpy('next');
var completeSpy = jasmine.createSpy('complete');
var query:any = null;
var obs = observeQuery(query);
var obs = observeQuery(query, false);
obs.subscribe(nextSpy, null, completeSpy);
expect(nextSpy).toHaveBeenCalledWith(null);
expect(completeSpy).toHaveBeenCalled();
Expand All @@ -63,7 +63,7 @@ describe('observeQuery', () => {
var query = {
orderByKey: new Subject<boolean>()
};
var obs = observeQuery(query);
var obs = observeQuery(query, false);
var noOrderyQuery = { orderByKey: false };
obs.subscribe(nextSpy, null, completeSpy);
query.orderByKey.next(true);
Expand All @@ -81,7 +81,7 @@ describe('observeQuery', () => {
var query = {
orderByKey: new Subject<boolean>()
};
var obs = observeQuery(query);
var obs = observeQuery(query, false);
obs.subscribe(nextSpy, null, completeSpy);
query.orderByKey.next(true);
expect(nextSpy).toHaveBeenCalledWith({ orderByKey: true });
Expand All @@ -92,40 +92,47 @@ describe('observeQuery', () => {


it('should omit only the orderBy type of the last emitted orderBy observable', () => {
// TODO: Should we allow re-emitting of the orderBy method?
var nextSpy = jasmine.createSpy('next');
var query = {
orderByKey: new Subject<boolean>(),
orderByPriority: new Subject<boolean>(),
orderByValue: new Subject<boolean>(),
orderByChild: new Subject<string>()
};
var obs = observeQuery(query);
var obs = observeQuery(query, false);
obs.subscribe(nextSpy);
query.orderByChild.next('height');
expect(nextSpy).toHaveBeenCalledWith({
orderByChild: 'height'
});
nextSpy.calls.reset();
query.orderByKey.next(true);
expect(nextSpy).not.toHaveBeenCalled();
// nextSpy.calls.reset();
// query.orderByValue.next(true);
// expect(nextSpy).toHaveBeenCalledWith({orderByValue: true});
// nextSpy.calls.reset();
expect(nextSpy).toHaveBeenCalledWith({
orderByKey: true
});
nextSpy.calls.reset();
query.orderByValue.next(true);
expect(nextSpy).toHaveBeenCalledWith({
orderByValue: true
});
nextSpy.calls.reset();
query.orderByChild.next('foo');
expect(nextSpy).toHaveBeenCalledWith({orderByChild: 'foo'});
expect(nextSpy).toHaveBeenCalledWith({
orderByChild: 'foo'
});
});
});


// describe('getOrderObservables', () => {
// it('should be subscribable event if no observables found for orderby', () => {
// expect(() => {
// getOrderObservables((<Query>{})).subscribe();
// }).not.toThrow();
// });
// });
describe('getOrderObservables', () => {
it('should be subscribable event if no observables found for orderby', () => {
var nextSpy = jasmine.createSpy('next');
var obs = getOrderObservables({});
obs.subscribe(nextSpy);
expect(nextSpy).toHaveBeenCalledWith(null);
});
});


describe('query combinations', () => {

Expand Down Expand Up @@ -422,3 +429,64 @@ describe('query combinations', () => {
});

});


describe('audited queries', () => {

it('should immediately emit if not audited', () => {
var nextSpy = jasmine.createSpy('next');
var query = { orderByChild: 'height', startAt: new Subject(), endAt: new Subject() };
var obs = observeQuery(query, false);
obs.subscribe(nextSpy);
query.startAt.next(5);
expect(nextSpy).not.toHaveBeenCalled();
query.endAt.next(10);
expect(nextSpy).toHaveBeenCalledWith({
orderByChild: 'height',
startAt: 5,
endAt: 10
});
query.startAt.next(10);
expect(nextSpy).toHaveBeenCalledWith({
orderByChild: 'height',
startAt: 10,
endAt: 10
});
query.endAt.next(15);
expect(nextSpy).toHaveBeenCalledWith({
orderByChild: 'height',
startAt: 10,
endAt: 15
});
});

it('should emit the last query (in the event loop) if audited', (done: any) => {
let emits = 0;
var query = { orderByChild: 'height', startAt: new Subject(), endAt: new Subject() };
var obs = observeQuery(query, true);
obs.subscribe(result => {
switch (++emits) {
case 1:
expect(result).toEqual({
orderByChild: 'height',
startAt: 5,
endAt: 10
});
query.startAt.next(10);
query.endAt.next(15);
break;
case 2:
expect(result).toEqual({
orderByChild: 'height',
startAt: 10,
endAt: 15
});
done();
break;
}
});
query.startAt.next(5);
query.endAt.next(10);
});

});
29 changes: 17 additions & 12 deletions src/database/query_observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Observer } from 'rxjs/Observer';
import { combineLatest } from 'rxjs/operator/combineLatest';
import { merge } from 'rxjs/operator/merge';
import { map } from 'rxjs/operator/map';
import { auditTime } from 'rxjs/operator/auditTime';
import {
Query,
ScalarQuery,
Expand All @@ -16,20 +17,24 @@ import {
} from '../interfaces';
import { isNil } from '../utils';

export function observeQuery(query: Query): Observable<ScalarQuery> {
export function observeQuery(query: Query, audit: boolean = true): Observable<ScalarQuery> {
if (isNil(query)) {
return observableOf(null);
}

return Observable.create((observer: Observer<ScalarQuery>) => {

let obs = getOrderObservables(query) as Observable<OrderBySelection>;
combineLatest.call(obs,
getStartAtObservable(query),
getEndAtObservable(query),
getEqualToObservable(query),
getLimitToObservables(query)
)
let combined = combineLatest.call(
getOrderObservables(query),
getStartAtObservable(query),
getEndAtObservable(query),
getEqualToObservable(query),
getLimitToObservables(query)
);
if (audit) {
combined = auditTime.call(combined, 0);
}
combined
.subscribe(([orderBy, startAt, endAt, equalTo, limitTo]
: [OrderBySelection, Primitive, Primitive, Primitive, LimitToSelection]) => {

Expand Down Expand Up @@ -80,7 +85,7 @@ export function observeQuery(query: Query): Observable<ScalarQuery> {
});
}

export function getOrderObservables(query: Query): Observable<OrderBySelection> | Observable<OrderBySelection | Observable<OrderBySelection>> {
export function getOrderObservables(query: Query): Observable<OrderBySelection> {
var observables = ['orderByChild', 'orderByKey', 'orderByValue', 'orderByPriority']
.map((key: string, option: OrderByOptions) => {
return ({ key, option })
Expand All @@ -93,15 +98,15 @@ export function getOrderObservables(query: Query): Observable<OrderBySelection>
if (observables.length === 1) {
return observables[0];
} else if (observables.length > 1) {
return merge.call(observables[0], observables.slice(1));
return merge.apply(observables[0], observables.slice(1));
} else {
return new Observable<OrderBySelection>(subscriber => {
subscriber.next(null);
});
}
}

export function getLimitToObservables(query: Query): Observable<LimitToSelection> | Observable<LimitToSelection | Observable<LimitToSelection>> {
export function getLimitToObservables(query: Query): Observable<LimitToSelection> {
var observables = ['limitToFirst', 'limitToLast']
.map((key: string, option: LimitToOptions) => ({ key, option }))
.filter(({key, option}: { key: string, option: LimitToOptions }) => !isNil(query[key]))
Expand All @@ -110,7 +115,7 @@ export function getLimitToObservables(query: Query): Observable<LimitToSelection
if (observables.length === 1) {
return observables[0];
} else if (observables.length > 1) {
const mergedObs = merge.call(observables[0], observables.slice(1));
const mergedObs = merge.apply(observables[0], observables.slice(1));
return mergedObs;
} else {
return new Observable<LimitToSelection>(subscriber => {
Expand Down
16 changes: 8 additions & 8 deletions src/test-root.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export * from './angularfire2.spec';
export * from './database/firebase_list_factory.spec';
export * from './database/firebase_object_factory.spec';
export * from './database/firebase_list_observable.spec';
export * from './database/firebase_object_observable.spec';
export * from './database/query_observable.spec';
export * from './auth/auth.spec';
export * from './auth/auth_backend.spec';
import './angularfire2.spec';
import './database/firebase_list_factory.spec';
import './database/firebase_object_factory.spec';
import './database/firebase_list_observable.spec';
import './database/firebase_object_observable.spec';
import './database/query_observable.spec';
import './auth/auth.spec';
import './auth/auth_backend.spec';