Skip to content

Commit 4e82c74

Browse files
committed
Release v0.8.0
1 parent 4d5a4d0 commit 4e82c74

3 files changed

Lines changed: 244 additions & 14 deletions

File tree

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mockfirebase",
3-
"version": "0.7.0",
3+
"version": "0.8.0",
44
"homepage": "https://github.com/katowulf/mockfirebase",
55
"authors": [
66
"Kato"

browser/mockfirebase.js

Lines changed: 242 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
/** mockfirebase - v0.7.0
1+
/** mockfirebase - v0.8.0
22
https://github.com/katowulf/mockfirebase
33
* Copyright (c) 2014 Kato
44
* License: MIT */
55
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.mockfirebase=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
66
'use strict';
77

88
exports.MockFirebase = require('./firebase');
9+
/** @deprecated */
910
exports.MockFirebaseSimpleLogin = require('./login');
1011

1112
},{"./firebase":15,"./login":16}],2:[function(require,module,exports){
@@ -1507,7 +1508,7 @@ Buffer.prototype.copy = function (target, target_start, start, end) {
15071508

15081509
var len = end - start
15091510

1510-
if (len < 100 || !Buffer.TYPED_ARRAY_SUPPORT) {
1511+
if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
15111512
for (var i = 0; i < len; i++) {
15121513
target[i + target_start] = this[i + start]
15131514
}
@@ -1576,6 +1577,7 @@ var BP = Buffer.prototype
15761577
* Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
15771578
*/
15781579
Buffer._augment = function (arr) {
1580+
arr.constructor = Buffer
15791581
arr._isBuffer = true
15801582

15811583
// save reference to original Uint8Array get/set methods before overwriting
@@ -9557,6 +9559,12 @@ function MockFirebase(currentPath, data, parent, name) {
95579559

95589560
// stores the last auto id generated by push() for tests
95599561
this._lastAutoId = null;
9562+
9563+
this._authUserData = null;
9564+
this._authListeners = [];
9565+
this._authCompletionListeners = [];
9566+
this._users = {};
9567+
this._uidCounter = 1;
95609568
}
95619569

95629570
MockFirebase.prototype = {
@@ -9701,7 +9709,7 @@ MockFirebase.prototype = {
97019709
*
97029710
* @param {string} event
97039711
* @param {string} key
9704-
* @param data
9712+
* @param [data]
97059713
* @param {string} [prevChild]
97069714
* @param [pri]
97079715
* @returns {MockFirebase}
@@ -9727,6 +9735,29 @@ MockFirebase.prototype = {
97279735
return this;
97289736
},
97299737

9738+
/**
9739+
* Modifies authentication state and changes the current user credentials. This will trigger
9740+
* any onAuth() listeners in the next flush() operation.
9741+
*
9742+
* @param {Object|null} userData if an object, it should contain all field specified here: https://www.firebase.com/docs/web/api/firebase/onauth.html
9743+
*/
9744+
changeAuthState: function (userData) {
9745+
var self = this;
9746+
this._defer(function() {
9747+
if (!_.isEqual(self._authUserData, userData)) {
9748+
self._authUserData = _.isObject(userData) ? userData : null;
9749+
self._triggerAuthEvent();
9750+
}
9751+
});
9752+
},
9753+
9754+
/**
9755+
* Retrieve an email user that was added with createUser()
9756+
*/
9757+
getEmailUser: function(email) {
9758+
return this._users.hasOwnProperty(email) ? _.extend({}, this._users[email]) : null;
9759+
},
9760+
97309761
/*****************************************************
97319762
* Firebase API methods
97329763
*****************************************************/
@@ -9943,26 +9974,150 @@ MockFirebase.prototype = {
99439974
return [valueFn, finishedFn, applyLocally];
99449975
},
99459976

9977+
/**********************************************************
9978+
* AUTHENTICATION METHODS
9979+
**********************************************************/
9980+
99469981
/**
99479982
* If token is valid and parses, returns the contents of token as exected. If not, the error is returned.
99489983
* Does not change behavior in any way (since we don't really auth anywhere)
99499984
*
99509985
* @param {String} token
99519986
* @param {Function} [callback]
9987+
* @deprecated
99529988
*/
99539989
auth: function(token, callback) {
9954-
//todo invoke callback with the parsed token contents
9955-
var err = this._nextErr('auth');
9956-
if (callback) {
9990+
console.warn('FIREBASE WARNING: FirebaseRef.auth() being deprecated. Please use FirebaseRef.authWithCustomToken() instead.');
9991+
this._authEvent('auth', callback);
9992+
},
9993+
9994+
/**
9995+
* If token is valid and parses, returns the contents of token as exected. If not, the error is returned.
9996+
* Does not change behavior in any way (since we don't really auth anywhere)
9997+
*
9998+
* @param {String} token
9999+
* @param {Function} [onComplete]
10000+
*/
10001+
authWithCustomToken: function(token, onComplete) {
10002+
this._authEvent('authWithCustomToken', onComplete);
10003+
},
10004+
10005+
authAnonymously: function(onComplete) {
10006+
this._authEvent('authAnonymously', onComplete);
10007+
},
10008+
10009+
authWithPassword: function(credentials, onComplete) {
10010+
this._authEvent('authWithPassword', onComplete);
10011+
},
10012+
10013+
authWithOAuthPopup: function(provider, onComplete) {
10014+
this._authEvent('authWithOAuthPopup', onComplete);
10015+
},
10016+
10017+
authWithOAuthRedirect: function(provider, onComplete) {
10018+
this._authEvent('authWithOAuthRedirect', onComplete);
10019+
},
10020+
10021+
authWithOAuthToken: function(provider, credentials, onComplete) {
10022+
this._authEvent('authWithOAuthToken', onComplete);
10023+
},
10024+
10025+
_authEvent: function(method, callback) {
10026+
var err = this._nextErr(method);
10027+
if (!callback) return;
10028+
if (err) {
10029+
// if an error occurs, we defer the error report until the next flush()
10030+
// event is triggered
995710031
this._defer(function() {
9958-
var auth = { auth: { id: 'test', _token: token }, expires: (new Date()).to_i / 1000 };
9959-
if( err === null ) {
9960-
callback(null, auth);
9961-
} else {
9962-
callback(err);
9963-
}
10032+
callback(err, null);
996410033
});
996510034
}
10035+
else {
10036+
// if there is no error, then we just add our callback to the listener
10037+
// stack and wait for the next changeAuthState() call.
10038+
this._authCompletionListeners.push({fn: callback});
10039+
}
10040+
},
10041+
10042+
getAuth: function() {
10043+
return this._authUserData;
10044+
},
10045+
10046+
onAuth: function(onComplete, context) {
10047+
this._authListeners.push({fn: onComplete, ctx: context});
10048+
},
10049+
10050+
offAuth: function(onComplete, context) {
10051+
var index = _.findIndex(this._authListeners, function(v) {
10052+
return v.fn === onComplete && v.ctx === context;
10053+
});
10054+
if (index > -1) {
10055+
this._authListeners.splice(index, 1);
10056+
}
10057+
},
10058+
10059+
unauth: function() {
10060+
if (this._authUserData !== null) {
10061+
this._authUserData = null;
10062+
this._triggerAuthEvent();
10063+
}
10064+
},
10065+
10066+
createUser: function(credentials, onComplete) {
10067+
var err = this._nextErr('createUser');
10068+
var users = this._users;
10069+
this._defer(_.bind(function() {
10070+
var user = null;
10071+
err = err ||
10072+
this._validateCreds('createUser', credentials, ['email', 'password']) ||
10073+
this._validateNewEmail(credentials);
10074+
if( !err ) {
10075+
var key = credentials.email;
10076+
users[key] = {uid: this._nextUid(), email: key, password: credentials.password};
10077+
user = {uid: users[key].uid};
10078+
}
10079+
onComplete(err, user);
10080+
}, this));
10081+
},
10082+
10083+
changePassword: function(credentials, onComplete) {
10084+
var err = this._nextErr('changePassword');
10085+
this._defer(_.bind(function() {
10086+
err = err ||
10087+
this._validateCreds('changePassword', credentials, ['email', 'oldPassword', 'newPassword']) ||
10088+
this._validateExistingEmail(credentials) ||
10089+
this._validPass(credentials, 'oldPassword');
10090+
if( !err ) {
10091+
var key = credentials.email;
10092+
var user = this._users[key];
10093+
user.password = credentials.newPassword;
10094+
}
10095+
onComplete(err);
10096+
}, this));
10097+
},
10098+
10099+
removeUser: function(credentials, onComplete) {
10100+
var err = this._nextErr('removeUser');
10101+
this._defer(_.bind(function() {
10102+
err = err ||
10103+
this._validateCreds('removeUser', credentials, ['email', 'password']) ||
10104+
this._validateExistingEmail(credentials) ||
10105+
this._validPass(credentials, 'password');
10106+
if( !err ) {
10107+
delete this._users[credentials.email];
10108+
}
10109+
onComplete(err);
10110+
}, this));
10111+
},
10112+
10113+
resetPassword: function(credentials, onComplete) {
10114+
var err = this._nextErr('resetPassword');
10115+
this._defer(_.bind(function() {
10116+
err = err ||
10117+
this._validateCreds('resetPassword', credentials, ['email']) ||
10118+
this._validateExistingEmail(credentials);
10119+
onComplete(err);
10120+
}, this));
996610121
},
996710122

996810123
/**
@@ -9985,6 +10140,65 @@ MockFirebase.prototype = {
998510140
* Private/internal methods
998610141
*****************************************************/
998710142

10143+
_nextUid: function() {
10144+
return 'simplelogin:'+(this._uidCounter++);
10145+
},
10146+
10147+
_validateNewEmail: function(creds) {
10148+
creds = _.assign({}, creds);
10149+
if( this._users.hasOwnProperty(creds.email) ) {
10150+
var err = new Error('The specified email address is already in use.');
10151+
err.code = 'EMAIL_TAKEN';
10152+
return err;
10153+
}
10154+
return null;
10155+
},
10156+
10157+
_validateExistingEmail: function(creds) {
10158+
creds = _.assign({}, creds);
10159+
if( !this._users.hasOwnProperty(creds.email) ) {
10160+
var err = new Error('The specified user does not exist.');
10161+
err.code = 'INVALID_USER';
10162+
return err;
10163+
}
10164+
return null;
10165+
},
10166+
10167+
_validateCreds: function(method, creds, fields) {
10168+
var err = this._validObj(creds, method, 'First');
10169+
var i = 0;
10170+
while (err === null && i < fields.length) {
10171+
err = this._validArg(method, creds, 'First', fields[i], 'string');
10172+
i++;
10173+
}
10174+
return err;
10175+
},
10176+
10177+
_validPass: function(obj, name) {
10178+
var err = null;
10179+
var key = obj.email;
10180+
if( obj[name] !== this._users[key].password ) {
10181+
err = new Error('The specified password is incorrect.');
10182+
err.code = 'INVALID_PASSWORD';
10183+
}
10184+
return err;
10185+
},
10186+
10187+
_validObj: function(obj, method, position) {
10188+
if( !_.isObject(obj) ) {
10189+
return new Error('Firebase.' + method + ' failed: ' + position + ' argument must be a valid object.');
10190+
}
10191+
return null;
10192+
},
10193+
10194+
_validArg: function(method, obj, position, name, type) {
10195+
if( !obj.hasOwnProperty(name) || typeof(obj[name]) !== type ) {
10196+
return new Error('Firebase.' + method + ' failed: ' + position +
10197+
' argument must contain the key "' + name + '" with type "' + type + '"');
10198+
}
10199+
return null;
10200+
},
10201+
998810202
_childChanged: function(ref) {
998910203
var events = [];
999010204
var childKey = ref.key();
@@ -10107,6 +10321,21 @@ MockFirebase.prototype = {
1010710321
}
1010810322
},
1010910323

10324+
_triggerAuthEvent: function() {
10325+
var list = this._authCompletionListeners;
10326+
// clear the completion list before triggering callbacks
10327+
this._authCompletionListeners = [];
10328+
var user = this._authUserData;
10329+
// trigger completion listeners first
10330+
_.forEach(list, function(parts) {
10331+
parts.fn.call(parts.ctx, null, _.cloneDeep(user));
10332+
});
10333+
// then trigger onAuth listeners
10334+
_.forEach(this._authListeners, function(parts) {
10335+
parts.fn.call(parts.ctx, _.cloneDeep(user));
10336+
});
10337+
},
10338+
1011010339
_updateOrAdd: function(key, data, events) {
1011110340
var exists = _.isObject(this.data) && this.data.hasOwnProperty(key);
1011210341
if( !exists ) {
@@ -10217,6 +10446,7 @@ var md5 = require('MD5');
1021710446

1021810447
/*******************************************************************************
1021910448
* SIMPLE LOGIN
10449+
* @deprecated
1022010450
******************************************************************************/
1022110451
function MockFirebaseSimpleLogin (ref, callback, userData) {
1022210452
// allows test units to monitor the callback function to make sure

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mockfirebase",
3-
"version": "0.7.0",
3+
"version": "0.8.0",
44
"description": "An experimental Firebase stub/spy library for writing unit tests (not supported by Firebase)",
55
"main": "./src",
66
"scripts": {

0 commit comments

Comments
 (0)