December 2014–January 2015 · Learning & research
Google Code-in & FOSSASIA
An early open-source notebook of utilities, tests and tutorials.

The Code-in collection moves between practical tools and explanations of how the web works. It includes an angle converter, a JSON validator, a wallpaper, and writing about Jekyll, automated testing and p5.js.
Other tutorials document moving a MediaWiki installation and working on web infrastructure. Together they capture the shift from building individual pages to understanding the systems behind them.

The original notebook
Writing from the 2014–2015 collection, preserved as historical tutorials.
Running jekyll locally for FOSSASIA
Github Pages allows one to use Jekyll on their site. Github compiles everything on their own servers and serves them to visitors.
However, for testing and development, it is a wise idea to have Jekyll running on your local environment. This quick guide will run you through getting jekyll running on your computer.
Why Jekyll
We've begun to use Jekyll for FOSSASIA's Google Code-in site. This tutorial was because of a task on GCI.
Jekyll is useful for sites hosted on Github because it allows using Coffeescript and SASS. You get to separate out the data from the template by using Jekyll Data Files. You can use Variables and YAML Front Matter for more advance customization.
In our case, we primarily used Jekyll to separate logic from data by using Data Files, and to use SASS for better stylesheets. FOSSASIA's GCI site allows students to add their own information and photos. Previously, students would have to copy-paste a section of HTML code and make changes in the HTML to get themselves to appear on the site. This was difficult for inexperienced students and often led to problems in code, like syntax errors and uneven indenting - all very confusing to maintain. Adding a new student's info almost always resulted in a merge conflict, and all merges had to be done manually.
The new version with jekyll has a students.json file in it's _data directory. The file is an array of objects, one for each student. A student can add information like their social media links, their photo, and their image simply by editing this JSON file. For social media profiles, they simply need to enter their username, not the whole URL - the template handles the rest.
The template code is now separate and is run by nested loops using Liquid. This ensure perfect uniformity and making changes are easier. For example, if we want to change the animation style, it is simply one change instead of changing every occurrence.
Using SCSS allows the site to run SCSS-lint, which ensures that the CSS written is uniform and free of errors. Variables and nesting by SCSS is also useful in the website's design.
Setting Up
First, you should have a local copy of the fossasia site. You'll notice a file called 'Gemfile' in the root, this is required for installing and configuring the gem.
You also need Ruby and Node.JS installed. Windows users can get ruby from RubyInstaller.
Next, we'll install Bundler. Bundler is the package manager for Ruby, that will make managing installs of Jekyll and other gems very easy. Install Bundler by running gem install bundler in the command line.
Navigate to the fossasia.github.io folder (where the Gemfile is located) on the command line. Run bundle install to install dependencies for the github-pages gem. The pages gem installs many dependencies, which include jekyll, jekyll-coffeescript, jekyll-sass-converter - All very useful for an average development project.See the full list here. We don't exactly use many of these dependencies, but it is important to have all to exactly mimic Github. Apart from that, the pages gem isn't really much different from the normal jekyll gem.
Running!
Running bundle exec jekyll serve in the repo's directory will compile and run your site exactly how Github would compile and run it. You'll be able to see the site on your computer by visiting localhost:4000. Congrats!
Made with ♥ for Code-In
Mocking, Spying, and Stubbing
In test-driven development (TDD), mocking, spying, and stubbing are three important methods. Mocking allows checking functions without dependencies, increasing speed and reducing chances of error; spying allows to check the 'indirect output' of code; stubbing allows to simulate functions to reduce their complexity and increase speed for testing.
In the post, I'll be talking about testing through Mocha and Sinon.JS, both based on Node JS.
The mailer
In this post we'll be discussing on running tests on a mailer function. This takes two arguments, req (request), and res (response). The function looks like this:
function rootPost(req, res) {
var email = {
from: 'Fossasia <fossasia@fossasia.com>',
to: req.body.to,
subject: req.body.subject,
text: req.body.message,
};
mailer.send(email, function(error, info) {
if ( error ) {
req.flash('info', error);
} else {
req.flash('info', 'Email sent sucessfully!');
}
res.render('index', { flash: req.flash('info') });
});
}
req.body contains all information of the email (subject, message, etc).
The inner mailer function is what actually sends the email. It calls many dependencies, and we'll have to mock it for efficient testing.
req.flash() gives useful information on if the mailer is sent or not. We'll need to spy on this method.
The function can be considered finished when it finally runs res.render(...). We'll need to mock res.render() to check for that.
Supplying arguments
The basic structure of our test will be as follows:
var testRequest = {};
testRequest.body = {
to: 'mail@namanyayg.com',
subject: 'Test',
message: 'Test',
};
...
testResponse = {
render: function() {
...
}
};
routes.rootPost(testRequest, testResponse);
// This is the rootPost function as above
We'll be supplying testRequest and testResponse to the rootPost function. testRequest.body be an object with the email's info.
Spying
Sinon.JS provides a .spy() method to create a test spy that records some basic information about the function it is spying on, how many times it's called, what arguments it was supplied with, etc. The .spy() method does not modify the function in question.
We'll be spying on an existing method, namely, the req.flash() method. At the end of the test, we'll need to check if the arguments passed to req.flash() contain 'Email Sent Successfully!' or not. If not, the the function has failed and there's some problem in the test.
Create a spy is simple - You simply use the sinon.spy() method. Since we need to spy on req.flash(), we'll do this:
testRequest.flash = sinon.spy();
With this one-liner, we'll be able to check if the arguments passed to testRequst.flash() have 'Email sent successfully!' or not.
Mocking and stubbing
In Sinon, one way to mock a function is to create a stub. A stub is like a glorified spy, it can do everything that a spy can and it is able to modify the function itself.
The syntax to create a stub is:
var stubFoo = sinon.stub(parentObject, 'childFunction', function() {
// This holds what parentObject.childFunction() is replaced with
});
We'll be stubbing the mailer.send() function, since we don't want it to actually send an email, but just check if it can send an email and if it has correct parameters. In the mock, we'll check if the arguments we receive match the arguments we supplied, if yes, we'll run the anonymous function that mailer.send() accepts as it's second argument.
var mailerSpy = sinon.stub(mailer, 'send', function(arguments, callback) {
// Compares test request body and actual body
assert.equal( arguments.to, testRequest.body.to, 'To field does not match' );
assert.equal( arguments.subject, testRequest.body.subject, 'Subject does not match' );
assert.equal( arguments.text, testRequest.body.message, 'Message body does not match' );
console.log(' - Given arguments match used arguments')
// Runs the function we supply as the second argument in mailer.send();
callback();
return false;
});
Modifying
At the end of the callback, res.render() is called. We already have spied on req.flash() and we can check inside res.render()'s mock if it's value matches to 'Email sent successfully!'.
At the start, we supplied testResponse to routers.rootPost() in place of res. Hence, we need to create testResponse.render() in our test to mock res.render().
We create a new method in testResponse, render. Here we'll output the value of the second argument we found from our testRequest.flash() spy. It will either be an error or 'Email sent successfully'. We will check if it the latter, if so, the test is considered to have passed.
testResponse = {
render: function() {
console.log( ' -', testRequest.flash.args[0][1] )
assert.equal(testRequest.flash.args[0][1], 'Email sent sucessfully!')
done();
}
};
Wrapping it up
We run our test through Mocha, and if we seen a green radical sign check mark that means the test passed. We successfully mocked two functions and spied on one.
Made with ♥ for Code-In
p5.js Introduction
p5.js is an easy-to-use JavaScript library that is a 'software sketchbook', letting artists, designers, and hobbyists use the web as a visual development tool. It is inspired by the Processing project.
Getting Started
Create a index.html file on your computer with some skeleton code:
<html>
<head>
<title>p5.js</title>
</head>
<body>
</body>
</html>
Just before the </body>, create two <script> tags linking to the p5 library and your local JavaScript file.
<body>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.3.12/p5.min.js" />
<script type="text/javascript" src="scripts.js" />
</body>
Create the file scripts.js in the same folder as your index.html file. Place the following starter code in scripts.js (taken from p5)
function setup() {
}
function draw() {
ellipse(50, 50, 80, 80);
}
Open index.html with a modern browser such as Chrome or Firefox. You should see a circle on your browser.
You'll see something like the following:
Multiple instances in one page
Often it is needed to 'embed' examples in a HTML document (such as this page does). To do that, p5 allows creation of a namespace.
A namespace works by creating a namespaced function that takes a single argument. Create a new variable that makes a new instance of p5. The instance takes two variables, the first being the namespaced function, the second being the ID of the HTML container you want the sketch rendered in.
var namespace = function( sketch ) {
...
}
var p5Instance = new p5(namespace, 'containerID');
I have been using this method to create the above circle like this:
<div id="ex1"></div>
var ex1 = function( s ) {
}
var one = new p5(ex1, 'ex1');
Which renders the canvas inside <div id="ex1"></div>. I've used s instead of sketch because it is shorter to repeat.
Inside the namespaced function, you can use all p5 methods, functions, and variables normally—they just have to be accessed through the argument that the instance passes (in my case, s).
var ex1 = function( s ) {
var someVariable = 42;
function helper() {
console.log('I aid in sketching');
}
s.setup = function() {
...
}
s.draw = function() {
...
}
}
var one = new p5(ex1, 'ex1');
The syntax is a bit different from p5's regular syntax, it seems more object-like. This is because we're using a namespaced function now, rather than exposing everything to the global scope. Variables and functions can be declared normally, but to use p5's method, they need to follow the above syntax.
Inside the s.setup() and s.draw() blocks, you again need to use the s object to refer to p5 methods such as ellipse() or fill().
The complete code for making the ellipse above is as follows:
<html>
<head><title>p5</title></head>
<body>
...
<div id="ex1"></div>
...
</body>
</html>
var ex1 = function( s ) {
s.setup = function() {
}
s.draw = function() {
s.ellipse(50, 50, 80, 80);
}
}
var one = new p5(ex1, 'ex1');
My experience
p5.js turned out to be extremely easy to use with an intuitive syntax. It wasn't difficult to pick the library and get going with p5. It scaled well, and allowed expansive and complicated designs while keeping the syntax simple.
I've created a simple drawing through p5 that shows a star that follow's the user's mouse:
Complete code of the above drawing is below (Note: it uses a namespaced function as explained above).
<html>
<head><title>p5</title></head>
<body>
...
<div id="ex2"></div>
...
</body>
</html>
var ex2 = function( s ) {
var opacity = 200;
var step = 3;
var round = 0;
// Opacity, step, and round are used to
// make the star blink
s.setup = function() {
s.createCanvas(640, 480);
}
s.draw = function() {
s.stroke(0, 0, 0, 0);
s.background(30, 144, 255);
// Increases/decreases opacity
// appropriately
if ( round % 2 == 0 )
opacity += step;
else
opacity -= step;
if ( opacity >= 255 || opacity <= 200 )
round++;
s.fill(255, opacity); // Change fill through (rgb, a)
star(s.mouseX, s.mouseY); // Follow the mouse
}
function star(x, y) {
// Modified p5 code to create
// a 5-pointed star
s.translate(x, y); // Sets origin to center of the star
s.rotate(s.frameCount / 200); // Rotates the star
var angle = (Math.PI * 2) / 5;
var halfAngle = angle/2.0;
s.beginShape();
for (var a = 0; a < Math.PI * 2; a += angle) {
var sx = s.cos(a) * 50;
var sy = s.sin(a) * 50;
s.vertex(sx, sy);
sx = s.cos(a+halfAngle) * 30;
sy = s.sin(a+halfAngle) * 30;
s.vertex(sx, sy);
}
s.endShape(s.CLOSE);
}
}
var ex2 = new p5(ex2, 'ex2');
Made with ♥ for Code-In
Moving foss.vn to a new server
foss.vn is FOSSASIA's wiki, running on Mediawiki. I worked on a task that required me to move the site to a new server.
I had the old server's SSH details, while the new server had only FTP access and a separate MySQL database host.
I referred to the official guide for directions, then came up with my own solutions to a few problem that came while I was moving servers.
A quick guide on porting mediawiki installations is:
- Move database
- Move all files
- Done
Moving the database
We first export the database using mysqldump.
mysqldump -h hostname -u userid --password --default-character-set=binary dbname > backup.sql
You'll be asked for a password.
The backup.sql file is what we need to import to the new database.
To import via the command line, run:
mysql -u new-userid -h new-hostname -p new-dbname < dump_of_wikidb.sql
This requires that a table named new-dbname is ready on the new-hostname, with new-userid having complete rights. If this is not there, you'll need to configure additional details.
Moving the files
Mediawiki requires an exact copy of the current files uploaded to the remote server.
The most straightforward solution is to download all files and upload them. However, this is going to take a long time and will require lots of manual input.
I moved the files to the new server by using ncftp. It is a command line ftp tool. Using ncftpput allows to recursively upload the entire directory to the required directory on the server.
cd mediawiki-directory
ncftpput -u username -v -R -z remote-host remote-directory *
Run the above command. This asks for the password, enter it and let ncftpput finish. It can take a while depending on the size of your install.
Once you've moved the database and the files, you'll need to make changes in the LocalSettings.php files to edit the mysql login data.
Wrapping up
Once you've moved files and the database, it's time to test! Visit the URL provided by your host and have a look. You should see all content there, with perhaps some styling errors. The errors go as soon as you redirect the domain.
Made with ♥ for Code-In