Skip to content

Commit f6912b4

Browse files
committed
WIP: work on adding more tests
1 parent 2a84d8e commit f6912b4

File tree

16 files changed

+3213
-265
lines changed

16 files changed

+3213
-265
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ npm-debug.log
66
/.nyc_output
77
/tests/integration/config
88
/temp
9-
/.vscode
9+
/.vscode
10+
/tests/config

gulp/tasks/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function runBrowserUnitTests(dev = false) {
6060
'./tests/**/binary/**/*.test.ts',
6161
],
6262

63-
browsers: dev ? [ 'ChromeHeadless' ] : globalKarmaConf.browsers
63+
browsers: dev ? [ 'Chrome' ] : globalKarmaConf.browsers
6464
});
6565
new karma.Server(karmaConfig, exitCode => {
6666
if (dev) return done();

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
"karma-spec-reporter": "^0.0.30",
7373
"karma-typescript": "^3.0.1",
7474
"karma-webpack": "^2.0.3",
75+
"lodash": "^4.17.4",
7576
"merge2": "^1.0.3",
7677
"mkdirp": "^0.5.1",
7778
"require-dir": "^0.3.1",

src/database/api/Query.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
import { errorPrefix, validateArgCount, validateCallback, validateContextObject } from "../../utils/validation";
1414
import { ValueEventRegistration, ChildEventRegistration } from "../core/view/EventRegistration";
1515
import { Deferred, attachDummyErrorHandler } from "../../utils/promise";
16+
import { Reference } from "./Reference";
17+
import { Repo } from "../core/Repo";
1618

1719
/**
1820
* A Query represents a filter to be applied to a firebase location. This object purely represents the
@@ -21,7 +23,7 @@ import { Deferred, attachDummyErrorHandler } from "../../utils/promise";
2123
* Since every Firebase reference is a query, Firebase inherits from this object.
2224
*/
2325
export class Query {
24-
repo;
26+
repo: Repo;
2527
path;
2628
queryParams_;
2729
orderByCalled_;
@@ -124,6 +126,17 @@ export class Query {
124126
return this.queryParams_;
125127
}
126128

129+
/**
130+
* @return {!Firebase}
131+
*/
132+
getRef() {
133+
validateArgCount('Query.ref', 0, 0, arguments.length);
134+
// This is a slight hack. We cannot goog.require('fb.api.Firebase'), since Firebase requires fb.api.Query.
135+
// However, we will always export 'Firebase' to the global namespace, so it's guaranteed to exist by the time this
136+
// method gets called.
137+
return new Reference(this.repo, this.path);
138+
}
139+
127140
/**
128141
* @param {!string} eventType
129142
* @param {!function(DataSnapshot, string=)} callback
@@ -201,12 +214,12 @@ export class Query {
201214
* @param {!function(!DataSnapshot, string=)} userCallback
202215
* @return {!firebase.Promise}
203216
*/
204-
once(eventType, userCallback) {
217+
once(eventType, userCallback?, cancelOrContext?, context?) {
205218
validateArgCount('Query.once', 1, 4, arguments.length);
206219
validateEventType('Query.once', 1, eventType, false);
207220
validateCallback('Query.once', 2, userCallback, true);
208221

209-
var ret = this.getCancelAndContextArgs_('Query.once', arguments[2], arguments[3]);
222+
var ret = this.getCancelAndContextArgs_('Query.once', cancelOrContext, context);
210223

211224
// TODO: Implement this more efficiently (in particular, use 'get' wire protocol for 'value' event)
212225
// TODO: consider actually wiring the callbacks into the promise. We cannot do this without a breaking change
@@ -245,7 +258,7 @@ export class Query {
245258
* @param {!number} limit
246259
* @return {!Query}
247260
*/
248-
limitToFirst(limit) {
261+
limitToFirst(limit): Query {
249262
validateArgCount('Query.limitToFirst', 1, 1, arguments.length);
250263
if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) {
251264
throw new Error('Query.limitToFirst: First argument must be a positive integer.');
@@ -263,7 +276,7 @@ export class Query {
263276
* @param {!number} limit
264277
* @return {!Query}
265278
*/
266-
limitToLast(limit) {
279+
limitToLast(limit?): Query {
267280
validateArgCount('Query.limitToLast', 1, 1, arguments.length);
268281
if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) {
269282
throw new Error('Query.limitToLast: First argument must be a positive integer.');
@@ -345,12 +358,12 @@ export class Query {
345358
* @param {?string=} opt_name
346359
* @return {!Query}
347360
*/
348-
startAt(value, opt_name) {
361+
startAt(value = null, name?) {
349362
validateArgCount('Query.startAt', 0, 2, arguments.length);
350363
validateFirebaseDataArg('Query.startAt', 1, value, this.path, true);
351-
validateKey('Query.startAt', 2, opt_name, true);
364+
validateKey('Query.startAt', 2, name, true);
352365

353-
var newParams = this.queryParams_.startAt(value, opt_name);
366+
var newParams = this.queryParams_.startAt(value, name);
354367
this.validateLimit_(newParams);
355368
this.validateQueryEndpoints_(newParams);
356369
if (this.queryParams_.hasStart()) {
@@ -361,7 +374,7 @@ export class Query {
361374
// Calling with no params tells us to start at the beginning.
362375
if (value == null) {
363376
value = null;
364-
opt_name = null;
377+
name = null;
365378
}
366379
return new Query(this.repo, this.path, newParams, this.orderByCalled_);
367380
}
@@ -371,12 +384,12 @@ export class Query {
371384
* @param {?string=} opt_name
372385
* @return {!Query}
373386
*/
374-
endAt(value, opt_name) {
387+
endAt(value = null, name?) {
375388
validateArgCount('Query.endAt', 0, 2, arguments.length);
376389
validateFirebaseDataArg('Query.endAt', 1, value, this.path, true);
377-
validateKey('Query.endAt', 2, opt_name, true);
390+
validateKey('Query.endAt', 2, name, true);
378391

379-
var newParams = this.queryParams_.endAt(value, opt_name);
392+
var newParams = this.queryParams_.endAt(value, name);
380393
this.validateLimit_(newParams);
381394
this.validateQueryEndpoints_(newParams);
382395
if (this.queryParams_.hasEnd()) {
@@ -394,10 +407,10 @@ export class Query {
394407
* @param {string=} opt_name
395408
* @return {!Query}
396409
*/
397-
equalTo(value, opt_name) {
410+
equalTo(value, name?) {
398411
validateArgCount('Query.equalTo', 1, 2, arguments.length);
399412
validateFirebaseDataArg('Query.equalTo', 1, value, this.path, false);
400-
validateKey('Query.equalTo', 2, opt_name, true);
413+
validateKey('Query.equalTo', 2, name, true);
401414
if (this.queryParams_.hasStart()) {
402415
throw new Error('Query.equalTo: Starting point was already set (by another call to startAt or ' +
403416
'equalTo).');
@@ -406,7 +419,7 @@ export class Query {
406419
throw new Error('Query.equalTo: Ending point was already set (by another call to endAt or ' +
407420
'equalTo).');
408421
}
409-
return this.startAt(value, opt_name).endAt(value, opt_name);
422+
return this.startAt(value, name).endAt(value, name);
410423
}
411424

412425
/**
@@ -448,7 +461,7 @@ export class Query {
448461
* @param {Query} other
449462
* @return {boolean}
450463
*/
451-
isEqual(other) {
464+
isEqual(other?) {
452465
validateArgCount('Query.isEqual', 1, 1, arguments.length);
453466
if (!(other instanceof Query)) {
454467
var error = 'Query.isEqual failed: First argument must be an instance of firebase.database.Query.';
@@ -490,4 +503,8 @@ export class Query {
490503
}
491504
return ret;
492505
}
506+
507+
get ref() {
508+
return this.getRef();
509+
}
493510
}; // end Query

src/database/api/Reference.ts

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export class Reference extends Query {
126126
* @param {function(?Error)=} opt_onComplete
127127
* @return {!firebase.Promise}
128128
*/
129-
update(objectToMerge, opt_onComplete) {
129+
update(objectToMerge, onComplete?) {
130130
validateArgCount('Firebase.update', 1, 2, arguments.length);
131131
validateWritablePath('Firebase.update', this.path);
132132

@@ -143,9 +143,9 @@ export class Reference extends Query {
143143
);
144144
}
145145
validateFirebaseMergeDataArg('Firebase.update', 1, objectToMerge, this.path, false);
146-
validateCallback('Firebase.update', 2, opt_onComplete, true);
146+
validateCallback('Firebase.update', 2, onComplete, true);
147147
var deferred = new Deferred();
148-
this.repo.update(this.path, objectToMerge, deferred.wrapCallback(opt_onComplete));
148+
this.repo.update(this.path, objectToMerge, deferred.wrapCallback(onComplete));
149149
return deferred.promise;
150150
}
151151

@@ -155,31 +155,31 @@ export class Reference extends Query {
155155
* @param {function(?Error)=} opt_onComplete
156156
* @return {!firebase.Promise}
157157
*/
158-
setWithPriority(newVal, newPriority, opt_onComplete) {
158+
setWithPriority(newVal, newPriority, onComplete?) {
159159
validateArgCount('Firebase.setWithPriority', 2, 3, arguments.length);
160160
validateWritablePath('Firebase.setWithPriority', this.path);
161161
validateFirebaseDataArg('Firebase.setWithPriority', 1, newVal, this.path, false);
162162
validatePriority('Firebase.setWithPriority', 2, newPriority, false);
163-
validateCallback('Firebase.setWithPriority', 3, opt_onComplete, true);
163+
validateCallback('Firebase.setWithPriority', 3, onComplete, true);
164164

165165
if (this.getKey() === '.length' || this.getKey() === '.keys')
166166
throw 'Firebase.setWithPriority failed: ' + this.getKey() + ' is a read-only object.';
167167

168168
var deferred = new Deferred();
169-
this.repo.setWithPriority(this.path, newVal, newPriority, deferred.wrapCallback(opt_onComplete));
169+
this.repo.setWithPriority(this.path, newVal, newPriority, deferred.wrapCallback(onComplete));
170170
return deferred.promise;
171171
}
172172

173173
/**
174174
* @param {function(?Error)=} opt_onComplete
175175
* @return {!firebase.Promise}
176176
*/
177-
remove(opt_onComplete) {
177+
remove(onComplete?) {
178178
validateArgCount('Firebase.remove', 0, 1, arguments.length);
179179
validateWritablePath('Firebase.remove', this.path);
180-
validateCallback('Firebase.remove', 1, opt_onComplete, true);
180+
validateCallback('Firebase.remove', 1, onComplete, true);
181181

182-
return this.set(null, opt_onComplete);
182+
return this.set(null, onComplete);
183183
}
184184

185185
/**
@@ -228,14 +228,14 @@ export class Reference extends Query {
228228
* @param {function(?Error)=} opt_onComplete
229229
* @return {!firebase.Promise}
230230
*/
231-
setPriority(priority, opt_onComplete) {
231+
setPriority(priority, onComplete?) {
232232
validateArgCount('Firebase.setPriority', 1, 2, arguments.length);
233233
validateWritablePath('Firebase.setPriority', this.path);
234234
validatePriority('Firebase.setPriority', 1, priority, false);
235-
validateCallback('Firebase.setPriority', 2, opt_onComplete, true);
235+
validateCallback('Firebase.setPriority', 2, onComplete, true);
236236

237237
var deferred = new Deferred();
238-
this.repo.setWithPriority(this.path.child('.priority'), priority, null, deferred.wrapCallback(opt_onComplete));
238+
this.repo.setWithPriority(this.path.child('.priority'), priority, null, deferred.wrapCallback(onComplete));
239239
return deferred.promise;
240240
}
241241

@@ -244,11 +244,11 @@ export class Reference extends Query {
244244
* @param {function(?Error)=} opt_onComplete
245245
* @return {!Firebase}
246246
*/
247-
push(opt_value, opt_onComplete) {
247+
push(value?, onComplete?) {
248248
validateArgCount('Firebase.push', 0, 2, arguments.length);
249249
validateWritablePath('Firebase.push', this.path);
250-
validateFirebaseDataArg('Firebase.push', 1, opt_value, this.path, true);
251-
validateCallback('Firebase.push', 2, opt_onComplete, true);
250+
validateFirebaseDataArg('Firebase.push', 1, value, this.path, true);
251+
validateCallback('Firebase.push', 2, onComplete, true);
252252

253253
var now = this.repo.serverTime();
254254
var name = nextPushId(now);
@@ -262,16 +262,16 @@ export class Reference extends Query {
262262
var pushRef = this.child(name);
263263

264264
var promise;
265-
if (opt_value != null) {
266-
promise = thennablePushRef.set(opt_value, opt_onComplete).then(function () { return pushRef; });
265+
if (value != null) {
266+
promise = thennablePushRef.set(value, onComplete).then(function () { return pushRef; });
267267
} else {
268268
promise = PromiseImpl.resolve(pushRef);
269269
}
270270

271271
thennablePushRef.then = promise.then.bind(promise);
272272
/** @type {letMeUseMapAccessors} */ (thennablePushRef)["catch"] = promise.then.bind(promise, undefined);
273273

274-
if (typeof opt_onComplete === 'function') {
274+
if (typeof onComplete === 'function') {
275275
attachDummyErrorHandler(promise);
276276
}
277277

@@ -285,6 +285,22 @@ export class Reference extends Query {
285285
validateWritablePath('Firebase.onDisconnect', this.path);
286286
return new OnDisconnect(this.repo, this.path);
287287
}
288+
289+
get database() {
290+
return this.databaseProp();
291+
}
292+
293+
get key() {
294+
return this.getKey();
295+
}
296+
297+
get parent() {
298+
return this.getParent();
299+
}
300+
301+
get root() {
302+
return this.getRoot();
303+
}
288304
}
289305

290306
Object.defineProperty(Query.prototype, 'getRef', {
@@ -295,12 +311,4 @@ Object.defineProperty(Query.prototype, 'getRef', {
295311
// method gets called.
296312
return new Reference(this.repo, this.path);
297313
}
298-
})
299-
300-
// Internal code should NOT use these exported properties - because when they are
301-
// minified, they will refernce the minified name. We could fix this by including
302-
// our our externs file for all our exposed symbols.
303-
exportPropGetter(Reference.prototype, 'database', Reference.prototype.databaseProp);
304-
exportPropGetter(Reference.prototype, 'key', Reference.prototype.getKey);
305-
exportPropGetter(Reference.prototype, 'parent', Reference.prototype.getParent);
306-
exportPropGetter(Reference.prototype, 'root', Reference.prototype.getRoot);
314+
});

src/database/core/Repo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class Repo {
3232
statsListener_;
3333
eventQueue_;
3434
nextWriteId_;
35-
persistentConnection_;
35+
persistentConnection_ : PersistentConnection | null;
3636
server_;
3737
statsReporter_;
3838
transactions_init_;

src/database/core/Repo_transaction.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ export const TransactionStatus = {
8888
this.transactionQueueTree_ = new Tree();
8989
};
9090

91+
declare module './Repo' {
92+
interface Repo {
93+
startTransaction(path: Path, transactionUpdate, onComplete, applyLocally): void
94+
}
95+
}
96+
9197
/**
9298
* Creates a new transaction, adds it to the transactions we're tracking, and sends it to the server if possible.
9399
*

src/database/core/SyncPoint.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class SyncPoint {
5555
} else {
5656
var events = [];
5757

58-
forEach(this.views_, function(view) {
58+
forEach(this.views_, function(key, view) {
5959
events = events.concat(view.applyOperation(operation, writesCache, optCompleteServerCache));
6060
});
6161

@@ -122,7 +122,7 @@ export class SyncPoint {
122122
if (queryId === 'default') {
123123
// When you do ref.off(...), we search all views for the registration to remove.
124124
var self = this;
125-
forEach(this.views_, function(view, viewQueryId) {
125+
forEach(this.views_, function(viewQueryId, view) {
126126
cancelEvents = cancelEvents.concat(view.removeEventRegistration(eventRegistration, cancelError));
127127
if (view.isEmpty()) {
128128
delete self.views_[viewQueryId];
@@ -175,7 +175,7 @@ export class SyncPoint {
175175
*/
176176
getCompleteServerCache(path) {
177177
var serverCache = null;
178-
forEach(this.views_, function(view) {
178+
forEach(this.views_, (key, view) => {
179179
serverCache = serverCache || view.getCompleteServerCache(path);
180180
});
181181
return serverCache;

0 commit comments

Comments
 (0)