diff --git a/src/reactfire.js b/src/reactfire.js index 8076551..474878c 100644 --- a/src/reactfire.js +++ b/src/reactfire.js @@ -35,16 +35,20 @@ var ReactFireMixin = { _bind: function(firebaseRef, bindVar, bindAsArray) { this._validateBindVar(bindVar); - var error; + var errorMessage, errorCode; if (Object.prototype.toString.call(firebaseRef) !== "[object Object]") { - error = "firebaseRef must be an instance of Firebase"; + errorMessage = "firebaseRef must be an instance of Firebase"; + errorCode = "INVALID_FIREBASE_REF"; } else if (typeof bindAsArray !== "boolean") { - error = "bindAsArray must be a boolean. Got: " + bindAsArray; + errorMessage = "bindAsArray must be a boolean. Got: " + bindAsArray; + errorCode = "INVALID_BIND_AS_ARRAY"; } - if (typeof error !== "undefined") { - throw new Error("ReactFire: " + error); + if (typeof errorMessage !== "undefined") { + var error = new Error("ReactFire: " + errorMessage); + error.code = errorCode; + throw error; } this.firebaseRefs[bindVar] = firebaseRef.ref(); @@ -65,7 +69,9 @@ var ReactFireMixin = { this._validateBindVar(bindVar); if (typeof this.firebaseRefs[bindVar] === "undefined") { - throw new Error("unexpected value for bindVar. \"" + bindVar + "\" was either never bound or has already been unbound"); + var error = new Error("ReactFire: unexpected value for bindVar. \"" + bindVar + "\" was either never bound or has already been unbound"); + error.code = "UNBOUND_BIND_VARIABLE"; + throw error; } this.firebaseRefs[bindVar].off("value", this.firebaseListeners[bindVar]); @@ -79,25 +85,27 @@ var ReactFireMixin = { /*************/ /* Validates the name of the variable which is being bound */ _validateBindVar: function(bindVar) { - var error; + var errorMessage; if (typeof bindVar !== "string") { - error = "bindVar must be a string. Got: " + bindVar; + errorMessage = "bindVar must be a string. Got: " + bindVar; } else if (bindVar.length === 0) { - error = "bindVar must be a non-empty string. Got: \"\""; + errorMessage = "bindVar must be a non-empty string. Got: \"\""; } else if (bindVar.length > 768) { // Firebase can only stored child paths up to 768 characters - error = "bindVar is too long to be stored in Firebase. Got: " + bindVar; + errorMessage = "bindVar is too long to be stored in Firebase. Got: " + bindVar; } else if (/[\[\].#$\/\u0000-\u001F\u007F]/.test(bindVar)) { // Firebase does not allow node keys to contain the following characters - error = "bindVar cannot contain any of the following characters: . # $ ] [ /. Got: " + bindVar; + errorMessage = "bindVar cannot contain any of the following characters: . # $ ] [ /. Got: " + bindVar; } - if (typeof error !== "undefined") { - throw new Error("ReactFire: " + error); + if (typeof errorMessage !== "undefined") { + var error = new Error("ReactFire: " + errorMessage); + error.code = "INVALID_BIND_VARIABLE"; + throw error; } }, diff --git a/tests/specs/reactfire.spec.js b/tests/specs/reactfire.spec.js index dbd0983..d769db5 100644 --- a/tests/specs/reactfire.spec.js +++ b/tests/specs/reactfire.spec.js @@ -9,8 +9,6 @@ describe("ReactFireMixin Tests:", function() { describe("bindAsArray():", function() { it("bindAsArray() throws errors given invalid Firebase refs", function() { - var expectedError = new Error("ReactFire: firebaseRef must be an instance of Firebase"); - var TestComponent = React.createClass({ mixins: [ReactFireMixin], @@ -18,7 +16,12 @@ describe("ReactFireMixin Tests:", function() { var _this = this; invalidFirebaseRefs.forEach(function(invalidFirebaseRef) { - expect(function() { _this.bindAsArray(invalidFirebaseRef, "items"); }).toThrow(expectedError); + try { + _this.bindAsArray(invalidFirebaseRef, "items"); + expect("Function should throw error given parameter: " + invalidFirebaseRef).toBeFalsy(); + } catch (error) { + expect(error.code).toEqual("INVALID_FIREBASE_REF"); + } }); }, @@ -38,7 +41,12 @@ describe("ReactFireMixin Tests:", function() { var _this = this; invalidBindVars.forEach(function(invalidBindVar) { - expect(function() { _this.bindAsArray(firebaseRef, invalidBindVar); }).toThrow(); + try { + _this.bindAsArray(firebaseRef, invalidBindVar); + expect("Function should throw error given parameter: " + invalidBindVar).toBeFalsy(); + } catch (error) { + expect(error.code).toEqual("INVALID_BIND_VARIABLE"); + } }); }, @@ -141,8 +149,6 @@ describe("ReactFireMixin Tests:", function() { describe("bindAsObject():", function() { it("bindAsObject() throws errors given invalid Firebase refs", function() { - var expectedError = new Error("ReactFire: firebaseRef must be an instance of Firebase"); - var TestComponent = React.createClass({ mixins: [ReactFireMixin], @@ -150,7 +156,12 @@ describe("ReactFireMixin Tests:", function() { var _this = this; invalidFirebaseRefs.forEach(function(invalidFirebaseRef) { - expect(function() { _this.bindAsObject(invalidFirebaseRef, "items"); }).toThrow(expectedError); + try { + _this.bindAsObject(invalidFirebaseRef, "items"); + expect("Function should throw error given parameter: " + invalidFirebaseRef).toBeFalsy(); + } catch (error) { + expect(error.code).toEqual("INVALID_FIREBASE_REF"); + } }); }, @@ -170,7 +181,12 @@ describe("ReactFireMixin Tests:", function() { var _this = this; invalidBindVars.forEach(function(invalidBindVar) { - expect(function() { _this.bindAsObject(firebaseRef, invalidBindVar); }).toThrow(); + try { + _this.bindAsObject(firebaseRef, invalidBindVar); + expect("Function should throw error given parameter: " + invalidBindVar).toBeFalsy(); + } catch (error) { + expect(error.code).toEqual("INVALID_BIND_VARIABLE"); + } }); }, @@ -280,7 +296,12 @@ describe("ReactFireMixin Tests:", function() { var _this = this; invalidBindVars.forEach(function(invalidBindVar) { - expect(function() { _this.unbind(invalidBindVar); }).toThrow(); + try { + _this.unbind(invalidBindVar); + expect("Function should throw error given parameter: " + invalidBindVar).toBeFalsy(); + } catch (error) { + expect(error.code).toEqual("INVALID_BIND_VARIABLE"); + } }); }, @@ -300,7 +321,12 @@ describe("ReactFireMixin Tests:", function() { var _this = this; validBindVars.forEach(function(validBindVar) { - expect(function() { _this.unbind(validBindVar); }).toThrow(); + try { + _this.unbind(validBindVar); + expect("Function should throw error given parameter: " + validBindVar).toBeFalsy(); + } catch (error) { + expect(error.code).toEqual("UNBOUND_BIND_VARIABLE"); + } }); }, @@ -420,8 +446,12 @@ describe("ReactFireMixin Tests:", function() { var _this = this; nonBooleanParams.forEach(function(nonBooleanParam) { - var expectedError = new Error("ReactFire: bindAsArray must be a boolean. Got: " + nonBooleanParam); - expect(function() { _this._bind(firebaseRef, "items", nonBooleanParam); }).toThrow(expectedError); + try { + _this._bind(firebaseRef, "items", nonBooleanParam); + expect("Function should throw error given parameter: " + nonBooleanParam).toBeFalsy(); + } catch (error) { + expect(error.code).toEqual("INVALID_BIND_AS_ARRAY"); + } }); },