Last night I started adding a new feature to my project was-tested. Instead of accumulating code coverage blindly, I wanted to start collecting this information when the user (typically a QA tester) started going through a test script. Then when the script is finished, the QA can click "stop" and we save the code coverage for a particular feature. This information can be the basis for a lot of interesting projects.
So I wanted a simple way to store some basic information: the name of the feature test, test steps, and maybe code coverage JSON object. I needed to store this data somewhere and as a prototype I have decided to use Firebase backend data service. The main three features that attracted me to Firebase were:
- simple JSON data store and retrieval
- Node and AngularJS clients
- Rich user authentication options
So I have created a project on Firebase and started with a simple Node client to server as a test bed tool. For example I wanted to create a new test, add a second test and fetch all created tests from Node before writing any browser code. Here is my experience with Firebase API.
Using Firebase
Setting up a project is very simple. Once a project ID is issued, I can use the firebase Node package and push first item of data
1 | var Firebase = require('Firebase'); |
Notice that the in order to check if the set()
method failed, we need to pass a callback that receives
an error or nothing. If everything goes fine, can I update the newly created item? No, I do not get the
reference to the new value, only the fact that it was created, because the callback fired and there was no error.
I love promises, so I converted the ref.set
to promise-based approach
1 | var Q = require('q'); |
So this worked for a single object. I my case I had a list of test suites to save / update. Thus I needed
to keep adding a new test to the list and use ref.push()
method. This method is different from the ref.set()
- it takes callback, but also returns a value that references
the newly created item!
1 | var newItem = ref.push(info, function (err) { |
This is extremely weird, using return value AND callback at the same time. But I could convert to a promise-returning
method when using ref.set()
and I could do so now too
1 | var testPush = Q.nbind(ref.push, ref); |
Finally, I needed a way to retrieve all items from a reference. There is a method called ref.once('value') that fetches all data. Here is its signature
1 | ref.once('value', function (dataObject) { |
There is no return value, but the callback does not follow Node convention - it has data at the first position,
not the error. In fact, I do not know if there is a way to handle errors when calling ref.once
.
Of course I could write my own adaptor for ref.once
method to return a promise.
But I cannot say why do some Firebase methods:
- take Node-style callback argument, while others
- return a value,
- yet other methods take a callback with just a data argument?
This is an awful API format for such a small number of methods (Firebase has very few methods). I am going back to the MongoDB data services.