Skip to content

Commit

Permalink
feat(querying): Add declarative querying (#145)
Browse files Browse the repository at this point in the history
* feat(list): Add methods to FirebaseListObservable

* feat(list): .remove() should remove the whole list if no param is provided

* chore(utils): Add utils for runtime type checking

* feat(list): Accept url or ref

* chore(utils): function for checking for url or firebase ref

* feat(object): Accept a ref for .object()

* fix(auth): login() with Password provides credentials

* fix(auth): Add expires to FirebaseAuthState

* fix(auth): Add PasswordCredentials interface

* feat(auth): Add createUser method on auth

* fix(auth): Add expires in original declaration

* feat(querying) Add Querying API

* feat(querying)

* lots of fixes to query

* feat(querying): Awesome dynamic querying

* feat(querying): Tests for querying

* chore(querying): Remove commented out code

* feat(build): Change build for local typescript

* fix(database): Trigger observer error from .on() cancel callback

* fix(query): Feedback from jeffbcross
  • Loading branch information
davideast committed May 5, 2016
1 parent 314c595 commit 62c1607
Show file tree
Hide file tree
Showing 18 changed files with 1,104 additions and 65 deletions.
Binary file added angularfire2-2.0.0-alpha.16.tgz
Binary file not shown.
5 changes: 3 additions & 2 deletions karma.conf.js
Expand Up @@ -9,7 +9,8 @@ module.exports = function(config) {
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-firefox-launcher'),
require('karma-systemjs')
require('karma-systemjs'),
require('karma-mocha-reporter')
],

systemjs: {
Expand Down Expand Up @@ -91,7 +92,7 @@ module.exports = function(config) {
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['dots'],
reporters: ['mocha'],


// web server port
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -8,7 +8,7 @@
"test": "npm run build; karma start",
"docs": "typedoc --out docs/api/ --module commonjs --mode modules --name AngularFire2 src",
"build": "rm -rf dist; tsc",
"build_npm": "rm -rf dist && tsc -p tsconfig.publish.es5.json && tsc -p tsconfig.publish.es6.json",
"build_npm": "rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.publish.es5.json && ./node_modules/.bin/tsc -p tsconfig.publish.es6.json",
"postbuild_npm": "cp package.json README.md .npmignore dist/ && npm run rewrite_npm_package",
"rewrite_npm_package": "node --harmony_destructuring tools/rewrite-published-package.js",
"build_bundle": "cp -r src angularfire2 && tsc typings/main.d.ts angularfire2.ts --rootDir . --module system -t es5 --outFile dist/bundles/angularfire2.js --moduleResolution node --emitDecoratorMetadata --experimentalDecorators"
Expand Down Expand Up @@ -48,6 +48,7 @@
"karma-chrome-launcher": "^0.2.2",
"karma-firefox-launcher": "^0.1.7",
"karma-jasmine": "^0.3.6",
"karma-mocha-reporter": "^2.0.2",
"karma-systemjs": "^0.10.0",
"parse5": "^1.3.2",
"protractor": "3.0.0",
Expand Down
2 changes: 1 addition & 1 deletion publish.sh
@@ -1,2 +1,2 @@
npm run build_npm
npm publish dist
npm pack dist
2 changes: 1 addition & 1 deletion src/angularfire2.spec.ts
Expand Up @@ -56,7 +56,7 @@ describe('angularfire', () => {


it('should accept an absolute url', () => {
expect((<any>af.list(localServerUrl))._ref.toString()).toBe(localServerUrl);
expect(af.list(localServerUrl)._ref.toString()).toEqual(localServerUrl);
});


Expand Down
2 changes: 1 addition & 1 deletion src/providers/auth.spec.ts
Expand Up @@ -93,7 +93,7 @@ describe('FirebaseAuth', () => {
updateAuthState(authState);
let nextSpy = jasmine.createSpy('nextSpy');
let auth = injector.get(FirebaseAuth);

auth.subscribe(nextSpy);
expect(nextSpy).toHaveBeenCalledWith(AngularFireAuthState);
});
Expand Down
281 changes: 275 additions & 6 deletions src/utils/firebase_list_factory.spec.ts
Expand Up @@ -8,6 +8,7 @@ import {
unwrapMapFn
} from './firebase_list_factory';
import {FirebaseListObservable} from './firebase_list_observable';
import {FirebaseObjectFactory} from './firebase_object_factory';
import {
beforeEach,
it,
Expand All @@ -16,13 +17,32 @@ import {
describe,
expect
} from 'angular2/testing';
import {Subscription} from 'rxjs';
import {Query} from './query_observable';
import {Subscription, Observable, Subject} from 'rxjs';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/skip';
import 'rxjs/add/operator/take';

const rootFirebase = 'https://angularfire2-list-factory.firebaseio-demo.com/';

function queryTest(observable: Observable<any>, subject: Subject<any>, done: any) {
let nexted = false;
observable
.take(2)
.subscribe(val => {
if (!nexted) {
subject.next('2');
}
if (nexted) {
expect(nexted).toBe(true);
done();
}
nexted = true;
});

subject.next('20');
}

describe('FirebaseListFactory', () => {
var subscription: Subscription;
var questions: FirebaseListObservable<any>;
Expand All @@ -34,15 +54,266 @@ describe('FirebaseListFactory', () => {
var val3: any;

describe('constructor', () => {

it('should accept a Firebase db url in the constructor', () => {
const list = FirebaseListFactory(`${rootFirebase}/questions`);
expect(list).toBeAnInstanceOf(FirebaseListObservable);
});

it('should accept a Firebase db ref in the constructor', () => {
const list = FirebaseListFactory(new Firebase(`${rootFirebase}/questions`));
expect(list).toBeAnInstanceOf(FirebaseListObservable);
});

});

describe('query', () => {

describe('orderByChild', () => {
/*
orderByChild combinations
----------------------
orderByChild("").equalTo()
orderByChild("").startAt()
orderByChild("").startAt().endAt();
orderByChild("").endAt();
*/
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByChild: 'height',
equalTo: subject
}
});

queryTest(observable, subject, done);
});

it('startAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByChild: 'height',
startAt: subject
}
});

queryTest(observable, subject, done);
});

it('endAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByChild: 'height',
endAt: subject
}
});

queryTest(observable, subject, done);
});

it('should throw an error if limitToLast and limitToFirst are chained', () => {

const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByChild: 'height',
limitToFirst: 10,
limitToLast: 100
}
});
expect(observable.subscribe).toThrowError();
});

it('should throw an error if startAt is used with equalTo', () => {

const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByChild: 'height',
equalTo: 10,
startAt: 100
}
});
expect(observable.subscribe).toThrowError();
});

it('should throw an error if endAt is used with equalTo', () => {

const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByChild: 'height',
equalTo: 10,
endAt: 100
}
});
expect(observable.subscribe).toThrowError();
});

it('should throw an error if startAt and endAt is used with equalTo', () => {

const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByChild: 'height',
equalTo: 10,
endAt: 100,
startAt: 103
}
});
expect(observable.subscribe).toThrowError();
});

});

describe('orderByValue', () => {
/*
orderByValue combinations
----------------------
orderByValue("").equalTo()
orderByValue("").startAt()
orderByValue("").startAt().endAt();
orderByValue("").endAt();
*/
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByValue: true,
equalTo: subject
}
});

queryTest(observable, subject, done);
});

it('startAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByValue: true,
startAt: subject
}
});

queryTest(observable, subject, done);
});

it('endAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByValue: true,
endAt: subject
}
});

queryTest(observable, subject, done);
});

});

describe('orderByKey', () => {
/*
orderByKey combinations
----------------------
orderByKey("").equalTo()
orderByKey("").startAt()
orderByKey("").startAt().endAt();
orderByKey("").endAt();
*/
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByKey: true,
equalTo: subject
}
});

queryTest(observable, subject, done);
});

it('startAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByKey: true,
startAt: subject
}
});

queryTest(observable, subject, done);
});

it('endAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByKey: true,
endAt: subject
}
});

queryTest(observable, subject, done);
});
});

describe('orderByPriority', () => {
/*
orderByPriority combinations
----------------------
orderByPriority("").equalTo()
orderByPriority("").startAt()
orderByPriority("").startAt().endAt();
orderByPriority("").endAt();
*/
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByKey: true,
equalTo: subject
}
});

queryTest(observable, subject, done);
});

it('startAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByKey: true,
startAt: subject
}
});

queryTest(observable, subject, done);
});

it('endAt - should re-run a query when the observable value has emitted', (done: any) => {

const subject = new Subject();
const observable = FirebaseListFactory(rootFirebase, {
query: {
orderByKey: true,
endAt: subject
}
});

queryTest(observable, subject, done);
});
});

});
Expand All @@ -69,9 +340,7 @@ describe('FirebaseListFactory', () => {


it('should emit only when the initial data set has been loaded', (done: any) => {
// TODO: Fix Firebase server event order. srsly
// Use set to populate and erase previous values
// Populate with mutliple values to see the initial data load

(<any>questions)._ref.set([{ initial1: true }, { initial2: true }, { initial3: true }, { initial4: true }])
.then(() => questions.take(1).toPromise())
.then((val: any[]) => {
Expand Down

0 comments on commit 62c1607

Please sign in to comment.