Multiplayer space battle adventure game. We created it for Node Knockout 2016 competition last weekend together with @phil_rukin. The game is inspired by arcade classics but instead of fighting with asteroids user will have to fight with another user spaceships in realtime. 🎮
Play - https://kosmetikas-nodeknockout2016.herokuapp.com
That's how creative Sundays pass! Just made myself a Sublime Text theme optimized specially for 6to5's ECMAScript6 syntax definitions with React's JSX extensions. Check more screenshots and source code on GitHub.
Nowadays Flux (together with React.js) is one of the hottest topics in the tech world.
When people talk about Flux they mean more of a pattern than a framework. But Javascript community has already made a solid input into it and developed different approaches for working with Flux in order to bring some structure and “frameworky” feel. The first thing which comes to mind after some exploration - there are too much Flux libraries right now. In spite of that let’s try to compare some of them.
As for me I prefer staying on the shoulders of giants and Facebook’s open-source Dispatcher did pretty well for me so far both in commercial and pet projects. However curiousity forced me to implement a small “proof of concept” app with different Flux libraries on board to have ability to compare and see them in action.
Unidirectional data flow
"Flux" is just a word that describes itself as an architecture with "one way" data flow. What does it really mean? There are tons of different diagrams trying to visualize the unidirectional flow of data but the one that really makes sense for me is very simple:
Actions -> Data Stores -> Components (Views)
Every data mutation inside application occurs with calling the Actions - these could be user interaction inside component or server response. Data stores listen to the actions and mutate the data within themselves. It’s important to remember that stores are not models but they contain models. On the other hand Views listen to the stores in order to get the data to display and have no manipulations with it on their own. Every component re-renders itself completely when the data change is fired. Thanks to React and Virtual DOM every render is very cheap in performance costs. React will update the real DOM with only the difference. When another user interaction is happening we call actions and the flow is repeated.
Another good self-descriptive diagram about relations of different Flux parts could look as follows:
In the draft version of this article I wanted to focus only on the trio of the most popular Flux solutions so far - authentic Flux Dispatcher by Facebook, pluggable isomorphic container known as Fluxible by Yahoo and even more functional approach and rethink of original ideas by Mikael Brassman with his Reflux implementation. However attention that I received to my comparison repository on GitHub and several pull-requests with another solutions changed my mind a bit.
So I assume that readers of this blog post are aware of basic Flux architecture principles. Facebook’s Flux is the place where to start if you don’t feel confident with them. It’s important to get original Flux ideas in your head before proceeding with some specific implementations. I hope that comparison demo will help you to choose the right library to simplify your Flux way and it will definetly expand with more useful solutions.
I strongly encourage you to fork the Flux Comparison Demo and make pull requests with some Flux implementations that could be miserebly ommited by me.
Demo
The idea behind example client-side application is quite simple, it’s a parody on numerous online shops and consists of 2 components - the list of available products and cart where to checkout them.
Choose some products from our "Flux Online Shop" and add them to cart. Open browser console and click Checkout button, you’ll see payload with products that you just “bought”.
Dispatcher and Constants
Almost all libraries use Facebook’s Dispatcher under the hood. Except Fluxible which has it’s own Dispatchr as separate module and Reflux that decided to move the dispatcher into the actions themselves and remove the singleton implementation.
// McFly is an almost classy dispatcher itself var mcFly = new McFly(); return mcFly.dispatcher;
Also we can differentiate libraries on those who use Constants like in classic Facebook Flux (e.g. McFly, Marty) and big switch statements in stores (I’m looking at you McFly!).
Other ones prefer to not use such concepts. That’s good ‘cause when there is no giant switch statements in your store and the burden of constants is removed from the developer, custom dispatcher logic becomes unnecessary.
However you shouldn’t be under delusion. For example in Alt there is still a single dispatcher through which actions flow to the stores. That means that you still get the benefit of being able to hook into the dispatcher to listen to all global events. This is very useful for debugging.
// Alt.js provides access to the dispatcher var Alt = require('alt'); var alt = new Alt(); alt.dispatcher.register(console.log);
Facebook’s dispatcher is just a part of the library that saves you from writing custom boilerplate code.
Actions
Creating and using actions in almost all libraries feel the same. Especially in those that are good in incapsulating boilerplate code.
I believe that the only right place to initiate fetching data in Flux is Action Creators. It has a lot of benefits and works as easy as firing actions when request starts and when it finishes. One of the reasons to mention why you should follow this pattern is that stores pulling in data will screw you as soon as more than one store needs to know about a data request. Hopefully all libraries in the comparison are fine with using actions as the place to make web API calls.
// ES6 flavored Alt.js's actions class ActionsCreators { constructor() { // boilerplate actions this.generateActions( 'receiveProducts', 'addToCart', 'finishCheckout' ); } cartCheckout(products) { this.dispatch(products); // make request to third-party API WebAPIUtils.checkoutProducts(products); } } alt.createActions(ActionsCreators, exports);
// Web API utils call actions on success getAllProducts() { shop.getProducts( (products) => ActionCreators.receiveProducts(products); ); }, checkoutProducts() { shop.buyProducts( (products) => ActionCreators.finishCheckout(products); ); }
Very interesting discussion on where to fetch data and async requests was on the recent ReactConf 2015. Here is video that I highly recommend to watch. There are couple of useful advices as well.
Nevertheless there might be some difference in syntax. And the most wide-spread notice by the community is that calling actions in Fluxible are kind of verbose.
// Fluxible way of creating... module.exports = function (context, payload, done) { context.dispatch('ADD_TO_CART', {product: payload.product}); done(); };
In my opionion stores should be as simple as possible, prefferebly immutable, with no data fetching and async functions. Just a thin layer which describes the current state of the app. It’s better to have standalone stores that do not have dependencies on other ones. However practically sometimes (in simple cases) it’s handy to have waitFor method:
// fragment from Marty.js' CartStore onAddToCart: function (product) { // waiting to product store finish data manipulations this.waitFor(ProductStore); var id = product.id; product.quantity = id in this.state ? this.state[id].quantity + 1 : 1; this.state[id] = assign({}, product[id], product); this.hasChanged(); }
Reflux is a bit different in the terms of waiting. You can aggregate stores by listening to another data store’s change event. For me possibility of stores to listen to each other sounds a bit dangerous as your application can quickly become crumbled and hard to maintain.
// CartStore initialization in Reflux var CartStore = Reflux.createStore({ init: function () { this._products = {}; // listen to actions this.listenTo(ActionCreators.cartCheckout, this.onCartCheckout); this.listenTo(ActionCreators.finishCheckout, this.onSuccessCheckout); // subscribe to listen for whole ProductStore as there is no `waitFor` this.listenTo(ProductStore, noop); this.listenTo(ActionCreators.addToCart, this.onAddToCart); }, ...
Isomorphism
I really haven’t seen a big problem with singleton instances of stores and actions if we are dealing with pure client-side app so far. This could even work on the server in some cases too. However approach that is declared by Flummox makes me think in a bit different way, especially if we’re talking about isomophic apps. Flummox does not rely on on singleton objects, spread out across multiple modules and each of the different classes can be instantiated independently from the others. This makes it very easy to test. And even more! That’s why you get isomorphism for free - just create a new Flux() instance on each request. Flummox lacks some API docs for a moment but this should be improved very soon.
One of the coolest Alt.js features is Snapshots. The concept which borrows some from Fluxible’s dehydration/rehydration. At any point in time you can takeSnapshot() of your application and have entire state serialized for persistence, transfering, logging, or debugging. It’s easy to bootstrap serialized data and get your application in the particular state.
Components vs. Containers
What I really like in Flux is that our components are not aware of any code changes in the flow. That’s the total separation of concerns. To achieve this we introduce container components as additional layer which deals with data and pass it as props to standalone widgets. That’s why the real components with markup in all examples are completely the same. The next code fragment is CartContainer.jsx from classic FB Flux:
// Facebook Flux's CartContainer function _getStateFromStores () { return { products: CartStore.getAddedProducts(), total: CartStore.getTotal() }; } var CartContainer = React.createClass({ getInitialState: function () { return _getStateFromStores(); }, componentDidMount: function () { // subscribe to store changes CartStore.addChangeListener(this._onChange); }, componentWillUnmount: function () { // unsubscribe from stores CartStore.removeChangeListener(this._onChange); }, onCheckoutClicked: function () { if (!this.state.products.length) { return; } // fire action on user interaction ActionCreators.cartCheckout(this.state.products); }, render: function () { return ( <Cart products={this.state.products} total={this.state.total} onCheckoutClicked={this.onCheckoutClicked} /> ); }, _onChange: function () { this.setState(_getStateFromStores()); } });
All libraries share Flux’s principle which states that stores are the only source of data for components. As you see the thing that change from one solution to another is the difference in subscribe/unsubscribe boilerplate code. Find the differences in the next code fragment from the previous one (except that this one is written in ES6):
// Flummox's CartContainer let CartContainer = React.createClass({ getInitialState() { // access actions and stores through Flux instance this.actions = this.props.flux.getActions('app'); this.cartStore = this.props.flux.getStore('cart'); return this.getStateFromStores(); }, getStateFromStores() { return { products: this.cartStore.getProducts(), total: this.cartStore.getTotal(), }; }, componentDidMount() { // subscribe to store changes this.cartStore.addListener('change', this.onStoreChange); }, componentWillUnmount() { // unsubscribe from stores this.cartStore.removeListener('change', this.onStoreChange); }, onStoreChange() { this.setState(this.getStateFromStores()); }, onCheckoutClicked() { if (!this.state.products.length) { return; } // fire action on user interaction this.actions.cartCheckout(this.state.products); }, render() { return ( <Cart products={this.state.products} total={this.state.total} onCheckoutClicked={this.onCheckoutClicked} /> ); } });
Conclusions
It’s not a surprise that most of the libraries feel very close to each other ‘cause we are talking of the same pattern.
Isomorphic Flux is another topic, which we touched on a bit but it deserves a separate blog post. Before comparison I only saw Fluxible that really deals with server-side contexts per request. However isomorphic examples with Alt and especially Flummox prove that there are easy ways to have isomorphic apps with Flux. And that’s why we need a standalone repo with isomorphic comparison. The example app should be a bit more complex as well, probably with some routing etc.
As a conclusion I would like to say that it was a very intresting experiment. I’ve opened Alt.js and Flummox for myself which I’ve already apart from the crowd. Their APIs look exactly how I imagined some sort of simplified Flux without boilerplate code and some additional cool features too. Thanks everybody who contributed so far and stay tuned with the upcomings!
One of the most well-known Javascript related phrases sounds like "Everything in Javascript is an object!". But is it really true? There were numerous articles and blog posts trying to uncover the uncertainties around this statement. Finally there is my attempt to structurize the knowledge. And it turns out that the truth, as usual, lies somewhere in the middle.
In order to understand who is who in the world of Javascript data types let's take a look on the following example:
var foo = 'my string'; var bar = new String('my string');
At the first glance both variables create similar strings but if we will try to compare them the result will be completely different from someone's expectations:
console.log(foo === bar); // false
So let's assume for a minute that we're doing something wrong in this example and the statement that everything is an object is "truthy". We need to check these variables once more whether they have in its prototype chain the prototype property of the Object constructor:
foo instanceof Object // false bar instanceof Object // true
That’s the heart of the matter, our foo variable is just a Primitive value and is not an Object in any means! [1] On the other hand bar variable is created with constructor which explicitly wrap primitive into object (more about wrappers below in this post). We're able to get object's primitive counterpart by built-in valueOf() method: [2]
bar.valueOf(); // 'my string'
Another interesting moment that's worth mentioning looks like:
Calling String object without using the new keyword means a non-constructor context and returns a primitive.
Primitives
Similar behavior touches numbers and booleans as well. But there are another important characteristics that differentiate primitives from objects. One of them is immutability. [3] You won't be able to assign any property to the string, boolean or number literals like you do with the objects:
var num = 123; num.dodo = 'bird'; console.log(num.dodo); // undefined
In his survey [4] from the year 2002 Douglas Crockford points that null and undefined are special values. We agree with that statement as their behavior differs from other primitives. For example calling methods or adding properties on such value will end up in TypeError:
var smth = null; smth.prop = 'value'; // TypeError: Cannot set property 'value' of null
The second major difference is how primitives and objects are compared with each other.
var strA = 'value'; var strB = 'value'; console.log(strA === strB); // true var objA = {prop: 'value'}; var objB = {prop: 'value'}; console.log(objA === objB); // false
In spite that objects look similar they are not the same. In this example we just created two objects but their comparison could return true only if they will rely on the same underlying object:
While objects are compared by reference, primitives data types are compared by their value. And the trick with referencing doesn't work for them. As we already know they are immutable thus every time the new copy is returned:
ECMAScript6 will introduce into Javascript one more Primitive data type called Symbol.[5]
Wrappers and Objects
As we just found out primitives do not have any methods. But how then it's possible to do such things?
'string'.replace('st', 'b'); // new string "bring" is created
The answer is that primitives remain primitives and do not become objects but special temporary wrapper object is used automagically by Javascript in order to call the method or perform the property lookup (similar to what we did with new String()).
One more important innovation from ECMAScript6 is that creating an explicit wrapper object around primitive data types like we did in our first example is no longer supported for upcoming types. In such cases an error will be thrown:
var s = new Symbol('foo'); // TypeError
However, existing primitive wrapper objects like new Boolean, new String and new Number can still be created for legacy reasons.
Lastly we are ready to say few words about the real first class citizens of the "Javascript data types country".
It's generally accepted to point 3 main object types in Javascript - Object, Array and Function. [4] However the list of built-in global objects may vary due to environment where code is executed. [6] It's important to understand that all objects in Javascript start from Object (yes, even functions!) and inherit methods and properties from Object.prototype although they may be overridden. [6]
function sum (x, y) { return x + y; } sum.description = 'Returns the sum of two numbers'; console.log(sum.description); // 'Returns the sum of two numbers' console.log(sum(1,2)); // 3
References
Hope this small overview will be helpful for someone. There is a list of great resources on that topic below. All of them are worth checking out.
I'm a big fan of docker and especially dokku technology. Together with DigitalOcean they make a perfect fit and simplify product shipping process a lot while making it as easy as running:
app:~$ git push production master
But sometimes you're faced with the problem of managing several Node.js application on one server that were already setup to use bash scripts and probably you want to utilize the full power of PM2 process manager as well.
In the case when the length of bash scripts list becomes more than 2 and you have the feeling that it will increase even more...
user@server:~$ ls -a app1-production-restart.sh app1-staging-restart.sh app2-production-restart.sh app2-staging-restart.sh ...
...it's a good time to consider switching to some tool that will make all dirty work for you.
Similar story happened to me and node-tiny-dploy was born. This command-line tool is very easy to use and it copes with the basic flow of node.js+pm2 app like:
cd /to/app/ git pull npm install bower install # optionally gulp build # (or grunt build) optionally pm2 start app # with the list of available pm2 options
The module provides several commands to:
- automatically setup application in "/var/www" folder
- keep git repository up to date
- make silent pm2 reloads or force restarts then
How to use
To install module on your server just run:
npm install tiny-dploy -g
And then create your first app with dploy setup - cli interface will ask you several questions in order to automatically configure application for your needs, for example:
user@server:~$ dploy setup name: staging git url: [email protected]:user/test-app.git git branch (master): staging # defaults to `master` node (app.js): app.coffee # defaults to `app.js` folder in /var/www/ : app-dir # will look at `name` if not specified pm2 process: app # will look at folder or `name` if not specified pm2 opts: -i 4 # available pm2 options build tool (grunt/gulp/N): grunt use bower? (Y/n): Y NODE_ENV (development): staging NODE_PORT (80): 8080 -----> Clone git repo into folder with name "app-dir" ...
This will git clone repository from our fake [email protected]:user/test-app.git to /var/www/app-dir, configure it and start with PM2. Huh, easy isn't it? Now there's no need in multiple shell scripts! In order to update app with the latest changes from git branch and reload it just run:
user@server:~$ dploy reload staging
The full list of commands and other features is available at GitHub and I recommend to overlook it.
As you may know Require.js is probably the most wide spread JavaScript module loader that is used for browser development nowadays. Everybody knows that in some ways Require (and AMD) sucks, especially when we are talking about the long lines of code dependencies that you need to declare and to write your module names twice:
define(['dep1', 'dep2', 'dep3', 'dep4', 'dep5'], function (dep1, dep2, dep3, dep4, dep5) { return function () { ... }; });
Personally I prefer CommonJS style and that’s where the idea behind Melchior.js is starting from. If you know the trick you can achieve something similar with Require.js too:
define(function (require) { var dep1 = require('dep1'); var dep2 = require('dep2'); });
But that was not enough for us and we came up with the idea of "Chainable Module Definition" to add some structure and make simplicity of method chaining to work for you in the browser when just creating modules or loading scripts.
Before we start the guide I need to mention that Melchior.js is not production ready yet but it’s fine enough to play with.
Simple example
The goal of this tutorial is to show you the fundamentals in the easiest possible way in order to be able to experiment with Melchior, through a minimalist example.
index.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Basic example of MelchiorJS integration</title> </head> <body> <div id="container"> <p>Check console and js files</p> </div> <script data-main="js/main" src="js/vendor/melchior.js"></script> </body> </html>
We begin with a basic structure. The script tag that calls melchior.js includes a "data-main" attribute pointing to the "js/main.js" file, without an extension (we can however keep it if we want).
Important part here is that if you want Melchior to act as a script loader you will need to add config in your main file. Please note that Melchior loads modules via XHR and thus you will need to open html file through a simple static server (here’s an example) in order to make it work properly.
// paths to modules melchiorjs.config({ paths: { 'module1': 'js/module1', 'module2': 'js/module2' } }) // your entry point .module('core') .require('module1') .require('module2', 'two') // aliased as `two` .run(function () { console.log(module1.getName() === two.getModuleOneName()); // true });
That’s how our main entry file will look like. The require() function takes two arguments: module name string and optional alias string that will be accessible inside run() block.
js/module1.js
melchiorjs.module('module1') .body(function () { var _name = 'module1 name'; return { getName: function () { return _name; } }; });
Here we return an object that exposes a getName() method allowing us to to get the private variable _name.
For the second module we have declared a dependency on the first one which becomes available under the same name in the body() function.
This module returns an object too, which exposes the getModuleOneName() method. Thus you see how we can make use of a dependency within a module. But you are totally free on what to do with those dependencies and I’m sure you will find some more interesting ways than in the example!
Loading dependencies that aren’t modules
Probably you will need to load third-party libraries that aren’t defined as Melchior modules, like for example jQuery or underscore.js. For this case Melchior provides a "shim" system for us which is very similar to the one that Require.js has.
melchiorjs.config({ // paths to modules paths: { 'module1': 'js/module1', 'module2': 'js/module2', // the same name as global that lib exposes // saves from optional `shim` property on config 'jQuery': 'js/vendor/jquery', // it will need shim because library exposes `_` globally 'underscore': 'js/vendor/underscore' }, // provide shim to non-melchior modules shim: { 'underscore': { exports: '_' } } }) // your entry point .module('core') .require('module1') .require('module2', 'two') .require('jQuery', '$') .run(function () { console.log(module1.getName() === two.getModuleOneName()); // true console.log('jQuery version:', $.fn.jquery); // 1.9.0 });
The 'paths' declared are relative to the location of the main.js file and don’t include their .js extension optionally. Under the 'shim' key of the configuration object we use module names as keys to point to the global variable defined by the library we want to get hold of.
If the global variable defined by the library is same as the module name you would like to use then you can omit declaring a shim key for it (take a look on jQuery in config).
Melchior handles third-party libs by automatically wrapping them in melchiorjs.module() so you don’t need to add anything by yourself.
Conclusion
I hope this walkthrough will help you straighten things up on how to use MelchiorJS or just inspire you with some DIY spirit.
Melchior is a great technical adventure and the story of its creation contains several interesting pitfalls due to JavaScript nature. Hopefully it will broad the choice of in-browser module loaders. In plans we have several improvements on the existing code base and such features as compiler for concatenating files and extending the require() method. If you’re interested or have any suggestion, please let me know by writing an issue in the Github repository or pledge the project via BountySource. As always, feel free to leave a comment or question on the subject!
ngActivityIndicator.js - preloaders for Angular.js apps made easy
Recently I've decided to move a small bunch of code that was used in several of my Angular.js apps into a separate module. That's how appeared ngActivityIndicator.js, find more details on usage under the hood.
This small lib is an Angular provider for loading indicators, which you can use on directives, controllers or services. The most handy piece of it is a directive called ng-activity-indicator which can be used to inject the indicator into the DOM automatically.
Another useful option is a set of 3 built-in CSS preloaders inside. You don't need to worry about the styles anymore, just pick-up the right loader for your app and start using it!
So if you don't need much customized behavior your app master view integration with ngActivityIndicator should be as easy as adding one line of code:
If it feels like not enough styles for you I strongly recommend to take a look at CSS-loaders repository. All of them can be easily integrated into indicator service.
I should also say few words about API. Naming of methods and concept was highly inpired by iOS class named UIActivityIndicatorView, it helps a lot with integrating different styles and simplifies things.
More usage examples and customization options are listed on Github and you can see it in action on this Demo. Happy preloading ;)
Good news from Likeastore! We decided to open-source social icons pack that we use inside application.
This pack consists of the services that app already supports, some of them will be added in the nearest future. There are 20 high-quality images and you are free to choose how to use it. Get the pack on github!
Slim progress bars for Angular.js applications with ngprogress-lite.js
At first demo - I think most of us saw trickle loading bars on such popular services as Youtube or Medium, isn't it?
Nprogress.js is an original jQuery plugin that popularized such loading effect. Unfortunately I noticed that there were no similar stable modules for Angular.js applications.
I didn't want to add additional bytes of jQuery to my project just because of that reason and that's why I created a port of nprogress.js for Angular.js - ngprogress-lite.js.
To start using you just need to inject provider inside your angular module and start calling methods inside your controllers, services or directives:
var app = angular.module('example', ['ngProgressLite']); app.controller('MainCtrl', function (ngProgressLite) { ngProgressLite.start(); setTimeout(function () { ngProgressLite.done(); }, 1500); });
You can check the result once more here and read documentation inside github repository. Also I would like to add that it's highly customizable (including templating), as well as it has the same API as original jQuery dependent solution.
Vote for Streamlikes - hack entry for Node Knockout 2013 competition
Last weekend I participated in Node Knockout online hackathon. The voting is currently going on, so I would like to present my small hack here.
Streamlikes was planned as a radio for recent popular tracks and mixes of your favorite bands and artists. Unfortunately I didn't have enough time to finish everything, but it already works in a way by getting likes from Facebook Graph API, and streaming shuffler.fm tracks suggestions with HTML5 Web Audio API.
I suppose that all technical details and some inputs about the competition itself will be put in a separate article soon. So keep in touch!
And please vote for Streamlikes simply by clicking the button at the bottom of the page! Thanks! ;)
UPDATE (Dec 14, 2013): Finally competition is over and winners announced! My entry finished in Top 100 overall and took 13th and 14th place in Solo and Design categories respectively. Thanks everyone who was voting for Streamlikes! For now I won't proceed with app's development because of the lack of time and it will present on Joyent's competition server as long as it will be possible.
Tweeting command-line application with Flatiron.js
Writing command-line interfaces with node.js is extremely easy and fun, especially if you use flatiron.js framework for this purpose. I've created node-tweet-cli application which allows to post tweets directly from your shell and now I want to share some details of its development process.
If you haven't heard, flatiron.js is adaptable, decoupled framework which can be used for web (both server and client sides) and command line applications in which we are interested in.
Commands
Our application is a CLI interface that manages login process to user's twitter account and tweeting from terminal. That's why basically our app will know several commands and the main are:
- tweet login - tweet new ...
Find out the full list of commands at modules docs page.
Bootstrapping
We have cli.js file where initializing of all our commands and options happens:
var path = require('path'); var flatiron = require('flatiron'); var app = module.exports = flatiron.app; app.use(flatiron.plugins.cli, { source: path.join(__dirname, 'commands'), argv: { version: { alias: 'v', description: 'print version of app', string: true }, } });
As you can see from this example all our commands are single files that are laying inside "commands" folder of our application. All of them have pretty similar structure:
var cli = require('../cli'); var newCmd = function () { cli.log.info('command new is called'); cli.log.info('version ' + cli.argv.version); }; newCmd.usage = ['describing usage of this command']; module.exports = newCmd;
In this example we simply log 2 strings in console but in our node-tweet-cli app we are making twitter's API request here.
Just another cool possibility is options which are added into argv object and can be called be like "--version" or "--colors" etc. All of them will be accessible as booleans through our main cli module that we have created one step before.
Using
That's it! Now we want to test and use our new interface. For that purpose we need an executable "./bin/tweet.js" file:
Yesterday I had a chance to participate as a speaker in a very cool event organized by local javascript community in Kiev called KyivJS.
In my talk I was speaking about my experience of using mongodb, node.js on top with express.js and angular.js as client-side framework in likeastore project.
Nowadays there are a lot of talks about different javascript frameworks, trying to guess which one is the best, as well as never ending discussions appear even about what stack of technologies to use.
There were a lot of talks about angular.js, it seems getting more and more people around it. Node.js becomes more popular too and a lot of companies start using it in production already, sometimes in flavor with express.js (Myspace, Geeklist, Groupon, etc.), sometimes not. The main thing here is that all of these technologies in MEAN stack are modern and quite popular. They have a huge advantage that all parts of our application will speak equally well one programming language - javascript.
End to end testing with zombie.js, mocha.js and should.js
Recently I had a chance to play with zombie.js while creating tests for new user authorization of our likeastore app.
As you may know zombie.js is not a fully functional web browser like phantom.js. It only simulates environment but this fact makes it lightweight and very fast (unlike phantom) and also easy to integrate with mocha.js or any other test framework. In my example I used zombie together with mocha and I need to say that it was very simple and fun. Of course there are another interesting alternatives like casperjs' node brother named Spooky but one of the advantages of zombie, including those that were mentioned before, is its speed, solid API and good documentation as well.
Briefly I will show how "likeastore" subscribtion spec was setup and how it work together with our beloved zombie. It's quite simple example and anything you might need can be found in official docs.
So after we wrote acceptance tests, ran them and saw that everything's ok but empty and pending, let's bootstrap our zombie browser.
subscribtion.spec.js
describe('user subscribtion flow', function () { var browser; before(function () { browser = new Zombie(); }); ... after(function () { browser.close(); }); });
As you may notice there is no require('zombie') inside spec itself, that's because I decided to make it global in testHooks.js file that can be required with mocha.opts on test run:
Pretty easy, right? And now we are ready to take a look on the main stage. Here we have nice zombie API methods that will deal with quering elements in DOM, filling and submiting forms, fetching some text also. More descriptive is the code itself:
describe('welcome page', function () { before(function (done) { browser.visit(config.siteUrl, function () { done(); }); }); it('should contain subscribe form', function () { browser.query('form.subscribe').should.be.ok; }); describe('when user submits form', function () { ... }); });
And now we are ready to submit form and test 2 major scenarios:
incorrect user behavior
var email; describe('when field is empty', function () { before(function (done) { browser.pressButton('.do-subscribe', function () { email = browser.query('.email'); done(); }); }); it('should add error class', function () { email.className.should.include('error'); }); }); describe('when data is incorrect', function () { before(function (done) { browser .fill('email', 'tester1@') .pressButton('.do-subscribe', function () { email = browser.query('.email'); done(); }); }); it('should add error class', function () { email.className.should.include('error'); }); });
"everything's fine" scenario
describe('when data is valid', function () { before(function (done) { browser .fill('email', '[email protected]') .pressButton('.do-subscribe', function () { email = browser.query('.email'); done(); }); }); it('should add success class', function () { email.className.should.include('success'); }); });
That's it! Of course we omit some configuration and simplification issues like special settings file storing CSS classes , etc. But anyway this example shows how easily user interaction testing can be achieved together with zombie.
Finally I had some time to finish Dookie - a small library that extends Stylus preprocessor with a bulk of useful mixins and components. In this post I want to share some details on it.
The idea was not to create a framework but summarize helpful utilities in one node.js package. That's how dookie-css appeared.
Overview
Full lib's documentation can be found at github repository, but here's an overview of some main points provided:
- resets (including normalize.css), - shorhands for css properties and small handy mixins, - gradients, - vendor prefixes, - optional global mixins
For example dookie-css allows you to simplify element's size, positioning or gradients:
.class size: 200px absolute: top 10px left 15px gradient: #1abc9c #16a085
Tests for styles.. sounds weird? But It's absolutely wrong opinion, that's important thing to remember - when you have deal with Stylus, you are testing functions that generate the styles and not static css.
If you are using mocha framework writing tests becomes real fun :)
The only thing to do is to setup helping rendering function:
describe('test() mixin', function () { var css; beforeEach(function (done) { stylusHelper('test(value)', function (err, res) { should.not.exist(err); should.exist(res); css = res.trim(); done(); }); }); it('should bla bla...', function () { css.should.equal(value); }); });
Mocha has such feature as string diffs! When the strings are small, mocha will use a character diff, when consisting of several lines a line-numbered “gutter” is added. So failing mixin test-case will look like shown at the picture and having a nice diff:
Btw I had a chance to find several bugs while creating Dookie unit tests, so they were very helpful. And I definetely know that without testing it would take much more time to detect them.
Among other things, visual tests are also nice to have. For my purpose and to simplify the task I've created visual test runner. It does two main things - starts local test server and then runs Casper.js script to capture a screenshot of the page where you can find all the mixins .
To conclude
If you didn't use Stylus in your projects, you definetly should try. It will add flexibility to your css. While using such libs as Dookie will help to not reinvent the wheel but concentrate on your app specific needs.
Geolocation in realtime with Node.js, Socket.io and Leaflet
Recently I've wrote a tutorial for amazing Codrops magazine about how to set your Node.js real-time geolocation app. Read it here or you can visit the demo and watch who's viewing this experiment at the same time. Pull from github repo to run locally.
Take a look on the experimental plugin for popins that I coded on these sunny holidays :) It uses interesting concept for showing popup windows that was suggested by Hakimel. All documetation and demo you can find here: http://labs.voronianski.com/jquery.avgrund.js/