Skip to content

Commit 62c1607

Browse files
committed
feat(querying): Add declarative querying (#145)
* 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
1 parent 314c595 commit 62c1607

18 files changed

+1104
-65
lines changed

angularfire2-2.0.0-alpha.16.tgz

24.3 KB
Binary file not shown.

karma.conf.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ module.exports = function(config) {
99
require('karma-jasmine'),
1010
require('karma-chrome-launcher'),
1111
require('karma-firefox-launcher'),
12-
require('karma-systemjs')
12+
require('karma-systemjs'),
13+
require('karma-mocha-reporter')
1314
],
1415

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

9697

9798
// web server port

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"test": "npm run build; karma start",
99
"docs": "typedoc --out docs/api/ --module commonjs --mode modules --name AngularFire2 src",
1010
"build": "rm -rf dist; tsc",
11-
"build_npm": "rm -rf dist && tsc -p tsconfig.publish.es5.json && tsc -p tsconfig.publish.es6.json",
11+
"build_npm": "rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.publish.es5.json && ./node_modules/.bin/tsc -p tsconfig.publish.es6.json",
1212
"postbuild_npm": "cp package.json README.md .npmignore dist/ && npm run rewrite_npm_package",
1313
"rewrite_npm_package": "node --harmony_destructuring tools/rewrite-published-package.js",
1414
"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"
@@ -48,6 +48,7 @@
4848
"karma-chrome-launcher": "^0.2.2",
4949
"karma-firefox-launcher": "^0.1.7",
5050
"karma-jasmine": "^0.3.6",
51+
"karma-mocha-reporter": "^2.0.2",
5152
"karma-systemjs": "^0.10.0",
5253
"parse5": "^1.3.2",
5354
"protractor": "3.0.0",

publish.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
npm run build_npm
2-
npm publish dist
2+
npm pack dist

src/angularfire2.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ describe('angularfire', () => {
5656

5757

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

6262

src/providers/auth.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe('FirebaseAuth', () => {
9393
updateAuthState(authState);
9494
let nextSpy = jasmine.createSpy('nextSpy');
9595
let auth = injector.get(FirebaseAuth);
96-
96+
9797
auth.subscribe(nextSpy);
9898
expect(nextSpy).toHaveBeenCalledWith(AngularFireAuthState);
9999
});

src/utils/firebase_list_factory.spec.ts

+275-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
unwrapMapFn
99
} from './firebase_list_factory';
1010
import {FirebaseListObservable} from './firebase_list_observable';
11+
import {FirebaseObjectFactory} from './firebase_object_factory';
1112
import {
1213
beforeEach,
1314
it,
@@ -16,13 +17,32 @@ import {
1617
describe,
1718
expect
1819
} from 'angular2/testing';
19-
import {Subscription} from 'rxjs';
20+
import {Query} from './query_observable';
21+
import {Subscription, Observable, Subject} from 'rxjs';
2022
import 'rxjs/add/operator/do';
2123
import 'rxjs/add/operator/skip';
2224
import 'rxjs/add/operator/take';
2325

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

28+
function queryTest(observable: Observable<any>, subject: Subject<any>, done: any) {
29+
let nexted = false;
30+
observable
31+
.take(2)
32+
.subscribe(val => {
33+
if (!nexted) {
34+
subject.next('2');
35+
}
36+
if (nexted) {
37+
expect(nexted).toBe(true);
38+
done();
39+
}
40+
nexted = true;
41+
});
42+
43+
subject.next('20');
44+
}
45+
2646
describe('FirebaseListFactory', () => {
2747
var subscription: Subscription;
2848
var questions: FirebaseListObservable<any>;
@@ -34,15 +54,266 @@ describe('FirebaseListFactory', () => {
3454
var val3: any;
3555

3656
describe('constructor', () => {
37-
57+
3858
it('should accept a Firebase db url in the constructor', () => {
3959
const list = FirebaseListFactory(`${rootFirebase}/questions`);
4060
expect(list).toBeAnInstanceOf(FirebaseListObservable);
4161
});
42-
62+
4363
it('should accept a Firebase db ref in the constructor', () => {
4464
const list = FirebaseListFactory(new Firebase(`${rootFirebase}/questions`));
4565
expect(list).toBeAnInstanceOf(FirebaseListObservable);
66+
});
67+
68+
});
69+
70+
describe('query', () => {
71+
72+
describe('orderByChild', () => {
73+
/*
74+
orderByChild combinations
75+
----------------------
76+
orderByChild("").equalTo()
77+
orderByChild("").startAt()
78+
orderByChild("").startAt().endAt();
79+
orderByChild("").endAt();
80+
*/
81+
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {
82+
83+
const subject = new Subject();
84+
const observable = FirebaseListFactory(rootFirebase, {
85+
query: {
86+
orderByChild: 'height',
87+
equalTo: subject
88+
}
89+
});
90+
91+
queryTest(observable, subject, done);
92+
});
93+
94+
it('startAt - should re-run a query when the observable value has emitted', (done: any) => {
95+
96+
const subject = new Subject();
97+
const observable = FirebaseListFactory(rootFirebase, {
98+
query: {
99+
orderByChild: 'height',
100+
startAt: subject
101+
}
102+
});
103+
104+
queryTest(observable, subject, done);
105+
});
106+
107+
it('endAt - should re-run a query when the observable value has emitted', (done: any) => {
108+
109+
const subject = new Subject();
110+
const observable = FirebaseListFactory(rootFirebase, {
111+
query: {
112+
orderByChild: 'height',
113+
endAt: subject
114+
}
115+
});
116+
117+
queryTest(observable, subject, done);
118+
});
119+
120+
it('should throw an error if limitToLast and limitToFirst are chained', () => {
121+
122+
const observable = FirebaseListFactory(rootFirebase, {
123+
query: {
124+
orderByChild: 'height',
125+
limitToFirst: 10,
126+
limitToLast: 100
127+
}
128+
});
129+
expect(observable.subscribe).toThrowError();
130+
});
131+
132+
it('should throw an error if startAt is used with equalTo', () => {
133+
134+
const observable = FirebaseListFactory(rootFirebase, {
135+
query: {
136+
orderByChild: 'height',
137+
equalTo: 10,
138+
startAt: 100
139+
}
140+
});
141+
expect(observable.subscribe).toThrowError();
142+
});
143+
144+
it('should throw an error if endAt is used with equalTo', () => {
145+
146+
const observable = FirebaseListFactory(rootFirebase, {
147+
query: {
148+
orderByChild: 'height',
149+
equalTo: 10,
150+
endAt: 100
151+
}
152+
});
153+
expect(observable.subscribe).toThrowError();
154+
});
155+
156+
it('should throw an error if startAt and endAt is used with equalTo', () => {
157+
158+
const observable = FirebaseListFactory(rootFirebase, {
159+
query: {
160+
orderByChild: 'height',
161+
equalTo: 10,
162+
endAt: 100,
163+
startAt: 103
164+
}
165+
});
166+
expect(observable.subscribe).toThrowError();
167+
});
168+
169+
});
170+
171+
describe('orderByValue', () => {
172+
/*
173+
orderByValue combinations
174+
----------------------
175+
orderByValue("").equalTo()
176+
orderByValue("").startAt()
177+
orderByValue("").startAt().endAt();
178+
orderByValue("").endAt();
179+
*/
180+
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {
181+
182+
const subject = new Subject();
183+
const observable = FirebaseListFactory(rootFirebase, {
184+
query: {
185+
orderByValue: true,
186+
equalTo: subject
187+
}
188+
});
189+
190+
queryTest(observable, subject, done);
191+
});
192+
193+
it('startAt - should re-run a query when the observable value has emitted', (done: any) => {
194+
195+
const subject = new Subject();
196+
const observable = FirebaseListFactory(rootFirebase, {
197+
query: {
198+
orderByValue: true,
199+
startAt: subject
200+
}
201+
});
202+
203+
queryTest(observable, subject, done);
204+
});
205+
206+
it('endAt - should re-run a query when the observable value has emitted', (done: any) => {
207+
208+
const subject = new Subject();
209+
const observable = FirebaseListFactory(rootFirebase, {
210+
query: {
211+
orderByValue: true,
212+
endAt: subject
213+
}
214+
});
215+
216+
queryTest(observable, subject, done);
217+
});
218+
219+
});
220+
221+
describe('orderByKey', () => {
222+
/*
223+
orderByKey combinations
224+
----------------------
225+
orderByKey("").equalTo()
226+
orderByKey("").startAt()
227+
orderByKey("").startAt().endAt();
228+
orderByKey("").endAt();
229+
*/
230+
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {
231+
232+
const subject = new Subject();
233+
const observable = FirebaseListFactory(rootFirebase, {
234+
query: {
235+
orderByKey: true,
236+
equalTo: subject
237+
}
238+
});
239+
240+
queryTest(observable, subject, done);
241+
});
242+
243+
it('startAt - should re-run a query when the observable value has emitted', (done: any) => {
244+
245+
const subject = new Subject();
246+
const observable = FirebaseListFactory(rootFirebase, {
247+
query: {
248+
orderByKey: true,
249+
startAt: subject
250+
}
251+
});
252+
253+
queryTest(observable, subject, done);
254+
});
255+
256+
it('endAt - should re-run a query when the observable value has emitted', (done: any) => {
257+
258+
const subject = new Subject();
259+
const observable = FirebaseListFactory(rootFirebase, {
260+
query: {
261+
orderByKey: true,
262+
endAt: subject
263+
}
264+
});
265+
266+
queryTest(observable, subject, done);
267+
});
268+
});
269+
270+
describe('orderByPriority', () => {
271+
/*
272+
orderByPriority combinations
273+
----------------------
274+
orderByPriority("").equalTo()
275+
orderByPriority("").startAt()
276+
orderByPriority("").startAt().endAt();
277+
orderByPriority("").endAt();
278+
*/
279+
it('equalTo - should re-run a query when the observable value has emitted', (done: any) => {
280+
281+
const subject = new Subject();
282+
const observable = FirebaseListFactory(rootFirebase, {
283+
query: {
284+
orderByKey: true,
285+
equalTo: subject
286+
}
287+
});
288+
289+
queryTest(observable, subject, done);
290+
});
291+
292+
it('startAt - should re-run a query when the observable value has emitted', (done: any) => {
293+
294+
const subject = new Subject();
295+
const observable = FirebaseListFactory(rootFirebase, {
296+
query: {
297+
orderByKey: true,
298+
startAt: subject
299+
}
300+
});
301+
302+
queryTest(observable, subject, done);
303+
});
304+
305+
it('endAt - should re-run a query when the observable value has emitted', (done: any) => {
306+
307+
const subject = new Subject();
308+
const observable = FirebaseListFactory(rootFirebase, {
309+
query: {
310+
orderByKey: true,
311+
endAt: subject
312+
}
313+
});
314+
315+
queryTest(observable, subject, done);
316+
});
46317
});
47318

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

70341

71342
it('should emit only when the initial data set has been loaded', (done: any) => {
72-
// TODO: Fix Firebase server event order. srsly
73-
// Use set to populate and erase previous values
74-
// Populate with mutliple values to see the initial data load
343+
75344
(<any>questions)._ref.set([{ initial1: true }, { initial2: true }, { initial3: true }, { initial4: true }])
76345
.then(() => questions.take(1).toPromise())
77346
.then((val: any[]) => {

0 commit comments

Comments
 (0)