Writing testling-ci tests is super easy. The only thing your test runner needs to do is to produce TAP output on console.log or process.stdout.

Let's create a new node module called testling-ci-test-example and let's add cross-browser tests to it. Once the tests run, you get a badge like this that shows in which browsers your code works:


If you click the badge you go to the test status page.

First, let's create index.js that exports a few functions, some of which work in some browsers and fail in others:

// doesn't work in IE<9
//
exports.timesTwo = function (list) {
    return list.map(function (x) { return x*2 });
}

// works everywhere
//
exports.timesThree = function (list) {
    var ret = [];
    for (var i = 0; i < list.length; i++) {
        ret[i] = list[i]*3;
    }
    return ret;
}

Now let's write tests for this module. We'll put tests in tests/test.js:

var test = require('tape');
var exampleLib = require('../index.js');

test('timesTwo test', function (t) {
  t.plan(1);
  t.deepEqual(exampleLib.timesTwo([1,2,3]), [2,4,6]);
});

test('timesThree test', function (t) {
  t.plan(1);
  t.deepEqual(exampleLib.timesThree([1,2,3]), [3,6,9]);
});

The tests use tape module that console.log's TAP formatted output.

Now let's add testling field to package.json:

"testling" : {
    "files" : "test/*.js",
    "browsers" : {
        "ie" : [ 6, 7, 8, 9, 10 ],
        "ff" : [ 3.5, 10, 15.0, 16.0, 17.0 ],
        "chrome" : [ 10, 20, 21, 22, 23 ],
        "safari" : [ 5.1 ],
        "opera" : [ 10, 11, 12 ]
    }
}

Finally, let's setup the github hook and point it to git.testling.com. First go to the settings of the repository,

Next, go to the service hooks,

Then, choose WebHook URLs,

Finally, type git.testling.com in the webhook URL field and press update settings,

And we're done. If we visit http://ci.testling.com/pkrumins/testling-ci-test-example we'll see the badge and which browsers the tests succeeded and in which browsers the code failed:

We can instantly see that the code fails in IE6, IE7, and IE8 because these versions of IE don't have Array.prototype.map, and that the code works everywhere else. So awesome!

For more information about testling-ci see ci.testling.com.


ci.testling.com

About Browserling

Our mission at Browserling Inc is to make the developers' life easier. Follow us on twitter for updates - @browserling, @testling, @substack, @pkrumins.

We at Browserling are proud to announce Testling-CI! Testling-CI lets you write continuous integration cross-browser tests that run on every git push!


ci.testling.com

There are a ton of modules on npm and github that aren't just for node.js but for browsers, too. However, figuring out which browsers these modules work with can be tricky. It's often that case that some module used to work in browsers but has accidentally stopped working because the developer hadn't checked that their code still worked recently enough. If you use npm for frontend and backend modules, this can be particularly frustrating.

Testling-CI (http://ci.testling.com) is a service for running your browser tests on every commit. Just add a "testling" field to your package.json like this:

"testling" : {
    "files" : "test/*.js",
    "browsers" : {
        "iexplore" : [ "6.0", "7.0", "8.0", "9.0" ],
        "chrome" : [ "20.0" ],
        "firefox" : [ "10.0", "15.0" ],
        "safari" : [ "5.1" ],
        "opera" : [ "12.0" ]
    }
}

Then add a github webhook for http://git.testling.com and your browser tests will be run on every commit in exactly the browsers you've specified!

Once the tests run you get a badge you can put in your readme with the current browser test status. Here's how it looks:

If you click the badge you go to the test status page.

All your tests need to do is output TAP-formatted text output. Many test harnesses already support this format and the protocol is simple enough that you can just console.log() valid output yourself.

We recommend using tape to output TAP or if you use Mocha, we've a testling-ci example using Mocha. We'll support many more test harnesses later.

Your browser tests can even use node-style require()s bundled with browserify so that you can use exactly the same tests for node and the browser. If your browser tests aren't written the node way you can still run them with the "scripts" field. See testling-ci homepage for full documentation.

This service is free for open source modules published to github. If you want to run this service on your private repos, contact us and we can enroll you in our testling professional edition beta!

For full documentation and more examples visit ci.testling.com!

About Browserling

Our mission at Browserling Inc is to make the developers' life easier. Testling-CI is our third product. Take a look our first two products Browserling and Testling.

Browserling lets you do manual cross-browser testing in all major browsers, such as Internet Explorer 6, 7, 8, 9; Chrome; Safari; Firefox and Opera.

Testling lets you do automated cross-browser JavaScript testing. You write your tests in JavaScript and we run them on the browsers and tell you the results. Testling-CI is built on top of Testling.

We're also soon launching our fourth amazing product. Stay tuned! Follow us on twitter for updates - @browserling, @testling, @substack, @pkrumins.

Important Update:

We've changed goals are we're not launching a fourth product.

We've retired Testling as we built Testling-CI.

All questions about Testling-CI: feedback@browserling.com

Ok, this is going to be an article for beginners but with a spin at the end even for the most advanced users. Let's say you want to run a command inside of chroot as another user all in a single command and be back at your shell. How do you do it? Turns out it can be easily done by combining several commands in a beautiful way:

sudo chroot /chroot su - user -c "cmd args"

It may seem a pretty crazy combination of commands but it's all really easy to undestand. First, let's take a look at man chroot. It says,

sudo chroot /chroot command

Okay, so we can run command inside of chroot as root, but how do we run the command inside of chroot as another user? How about using su for command? Let's try that:

sudo chroot /chroot su - user

This runs su inside of chroot as user but we get an interactive shell. Let's take a closer look at man su. It says that we could try:

sudo su - user -c "cmd args"

This runs the cmd args through the shell. Great! So let's use this together with chroot again:

sudo chroot /chroot su - user -c "cmd args"

Excellent! Almost what we needed. However there is still one small problem. If the user has a custom environment (such as different PATHs to executables or some other customizations), it won't get initialized, so we've to source the initialization file(s) ourselves:

sudo chroot /chroot su - user -c ". ~/.bash_profile; cmd args"

This does what we wanted and runs cmd args inside of chroot located at /new-root-path as user and after running the command it quits and we're back at our shell.

What a beautiful way to combine commands!

On Sourcing ~/.bash_profile

Some people couldn't understand why I was sourcing ~/.bash_profile. The reason is because I was unable to find another way to invoke the login shell and have the environment initialized.

I tried this:

sudo chroot /chroot su -l user -c "cmd args"

And it just wouldn't execute ~/.bash_profile. Su's man page says that -l invokes a login shell, however I don't see that happening. Here's the transcript that demonstrates it:

pkrumins$ pwd
/chroot

pkrumins$ sudo cat ./home/testuser1/.bash_profile 
echo "moo"
PATH="/test/bin"

pkrumins$ sudo chroot /chroot su -l testuser1 -c 'echo $PATH'
/bin:/usr/bin

pkrumins$ sudo chroot /chroot su -l testuser1 
moo

testuser1$ echo $PATH
/test/bin

testuser1$ ^D
logout

pkrumins$ sudo chroot /chroot su -l testuser1 -c '. ~/.bash_profile; echo $PATH'       
moo
/test/bin

pkrumins$ sudo chroot /chroot su -l testuser1
moo

testuser1$ /bin/bash -l -c 'echo $PATH'
moo
/test/bin

This definitely looks like a bug in su to me when -l and -c are used together. So the only way to get the environment loaded is by sourcing the initialization files yourself.

Update

I went through su's source code (can be found in util-linux package) and it turns out it's not a bug in su!

Here are the arguments that su passes to execv when I run su user -c 'echo $PATH' (see run_shell function in su.c):

shell: /bin/bash
args[0]: -bash
args[1]: -c
args[2]: echo $PATH

As you can see, args[0][0] is -, which makes bash a login shell, so bash should be executing the startup files, but it does not!

To figure out what was happening, I built a custom version of bash and added a bunch of debugging statements. I found that there are two different login-shell states! Who'd have thought? One that you get when you've set args[0][0] to -, the other that you get when you've used the -l argument (to bash, not su!).

In case args[0][0] is -, and you're using -c to execute code, bash will not execute startup files because it's in this "non-interactive positive-login-shell" state. However if you use -l and -c, it goes into "non-interactive negative-login-shell" state, and it will execute startup files (see run_startup_files function in bash's shell.c source file).

That was one hell of an adventure debugging this. So if you want bash to execute startup files through su, use my ". ~/.bash_profile" sourcing trick! (Or define NON_INTERACTIVE_LOGIN_SHELLS when building bash).

This article is part of the article series "Bash One-Liners Explained."
<- previous article next article ->

This is the fifth part of the Bash One-Liners Explained article series. In this part I'll teach you how to quickly navigate around the command line in bash using emacs-style keyboard shortcuts. That's right, emacs-style keyboard shortcuts. It might surprise you but by default bash uses emacs-style keyboard shortcuts for navigating around the command line. Keep reading to learn more!

See the first part of the series for introduction. After I'm done with the series I'll release an ebook (similar to my ebooks on awk, sed, and perl), and also bash1line.txt (similar to my perl1line.txt).

Also see my other articles about working fast in bash:

Parts of this post are based on my earlier post Working Productively in Bash's Emacs Command Line Editing Mode. Check it out, too!

And grab the emacs keyboard shortcut cheat sheet!

Let's start.

Part V: Navigating around in emacs mode

0. Introduction to input editing modes

Bash uses the readline library for input editing. The readline library supports emacs style key bindings, vi style key bindings as well as custom key bindings. By default readline will use the emacs style key bindings but you can easily switch to vi editing mode or customize them.

You can switch between the emacs and vi editing modes through set -o emacs and set -o vi commands.

The key bindings can be customized through the ~/.inputrc file or the bind command. For example, bind '"\C-f": "ls\n"' binds CTRL+f to execute ls command. You can learn more about readline's key binding syntax by consulting the readline section of the bash man page.

I'll cover the emacs editing mode in this article. In the next two articles I'll cover the vi editing mode and customizing readline.

1. Move to the beginning of the line

Press Ctrl+a

Ctrl+a moves the cursor to the beginning of the line. Here's an illustration. Let's say you've typed cd info in the terminal:

Before pressing Ctrl+a

Pressing Ctrl+a moves the cursor to the beginning of the line:

After pressing Ctrl+a

2. Move to the end of the line

Press Ctrl+e

Ctrl+e moves the cursor to the end of the line. Here's an illustration. Let's say you've typed mkdir foo bar baz in the terminal and your cursor is somewhere in the middle:

Before pressing Ctrl+e

Pressing Ctrl+e moves the cursor to the end of the line:

After pressing Ctrl+e

3. Move one word backward

Press Esc+b or Alt+b

Esc+b or Alt+b moves the cursor one word backward. You'll often see Meta+b but there is no such key on the keyboards anymore. Therefore either Esc+b or Alt+b will work, depending on how your terminal is configured.

Here's an illustration. Let's say you've typed echo 'hello world' in the terminal and your cursor is after hello:

Before pressing Meta+b

Pressing Esc+b or Alt+b moves the cursor one word backward:

After pressing Meta+b

4. Move one word forward

Press Esc+f or Alt+f

Esc+f or Alt+f moves the cursor one word forward. Here's an illustration. Let's say you've typed echo 'hello world' in the terminal and your cursor is before hello:

Before pressing Meta+f

Pressing Esc+b or Alt+b moves the cursor one word forward:

After pressing Meta+f

5. Delete the last word

Press Ctrl+w

Ctrl+w deletes the last word. Deleting a word is also known as killing a word. Each killed word gets stored in the kill ring buffer. If you accidentally killed a word press Ctrl+y to paste it back. Pasting from the kill ring buffer is also known as yanking.

Here's an illustration. Let's say you've typed cd /foo:

Before pressing Ctrl+w

Pressing Ctrl+w deletes /foo:

After pressing Ctrl+w

6. Paste the deleted word(s) back

Press Ctrl+y

Ctrl+y pastes whatever is in the kill buffer back to the terminal. Here's an illustration. Let's say you had typed cd /foo (see the previous example), and you killed the last word, which is /foo so your command line looks like:

Before pressing Ctrl+y

Pressing Ctrl+y brings /foo back:

After pressing Ctrl+y

7. Move one character backward

Press Ctrl+b

Ctrl+b moves the cursor one char backward. Here's an illustration. Let's say you had typed echo foo bar baz on the command line:

Before pressing Ctrl+b

Pressing Ctrl+b moves the cursor one character backward:

After pressing Ctrl+b

8. Move one character forward

Press Ctrl+f

Ctrl+f moves the cursor one char forward. Here's an illustration. Let's say you moved one character backward (as in the previous example):

Before pressing Ctrl+f

Pressing Ctrl+f moves the cursor one character forward:

After pressing Ctrl+f

9. Delete the whole line

Press Ctrl+u

Ctrl+u kills the whole line and puts it in the kill buffer. Same as with killed words, you can paste the whole line back by pressing Ctrl+y.

Here's an illustration. Let's say you've typed echo moo in your command line:

Before pressing Ctrl+u

Pressing Ctrl+u deletes the whole line:

After pressing Ctrl+u

10. Search the history backward

Press Ctrl+r

This is probably one of the most used keyboard shortcuts in bash. Pressing Ctrl+r searches the command history backwards. For example, you can press Ctrl+r and then type the first few characters of some command that you executed earlier to quickly find it.

Here's an illustration. Let's say you had executed a complicated command such as this one:

joinlines () { sed ':a; N; s/\n/'"$1"'/; ba'; }

And now you wish to modify it but you don't want to keep going through the history to find it. Press Ctrl+r and type something you remember from the command like joi:

After pressing Ctrl+r

11. Search the history forward

Press Ctrl+s

If you press Ctrl+s, most likely your terminal will freeze because by default your terminal interprets Ctrl+s as the stop-flow signal. When I was less experienced this was driving me crazy. I'd accidentally press Ctrl+s and my terminal would freeze. And I had no idea what was happening. Later I learned that I can press CTRL+q to unfreeze the terminal (Ctrl+q starts the flow again.)

The right way to go is to change the terminal behavior for Ctrl+s via the stty command:

$ stty stop 'undef'

This will undefine the key binding for the stop-flow signal and you'll be able to use bash's Ctrl+s.

Ctrl+s comes handy when you've searched too far with Ctrl+r. Then you can just simply reverse the search direction by pressing Ctrl+r.

Here's an illustration. Let's say you typed awk and pressed Ctrl+r a few times and you skipped past the awk command that you wanted to find:

Before pressing Ctrl+s

Pressing Ctrl+s reverses the history search direction:

After pressing Ctrl+s

12. Exchange two adjacent characters quickly

Press Ctrl+t

Ctrl+t transposes two characters (exchanges them) and moves the cursor one character forward. Here's an illustration. Let's say you've mistyped echo in ehco bar baz and your cursor is at the letter c:

Before pressing Ctrl+t

Pressing Ctrl+t exchanges c with h and moves the cursor one char forward:

After pressing Ctrl+t

13. Exchange two adjacent words quickly

Press Esc+t or Alt+t

Esc+t or Alt+t transposes two words (exchanges them) and moves the cursor one word forward. Here's an illustration. Let's say you've typed foo bar baz and your cursor is at the word bar:

Before pressing Meta+t

Pressing Esc+t or Alt+t exchanges foo with bar and moves the cursor one word forward:

After pressing Meta+t

14. Uppercase the rest of the word

Press Esc+u or Alt+u

Esc+u or Alt+u uppercases the rest of the word. Here's an illustration. Let's say you've typed foo bar baz and your cursor is at the beginning of bar:

Before pressing Meta+u

Pressing Esc+u or Alt+u uppercases the whole word and bar becomes BAR:

After pressing Meta+u

15. Lowercase the rest of the word

Press Esc+l or Alt+l

Esc+t or Alt+t uppercases the rest of the word. Here's an illustration. Let's say you've typed foo BAR baz and your cursor is at the beginning of BAR:

Before pressing Meta+l

Pressing Esc+l or Alt+l lowercases the whole word and BAR becomes bar:

After pressing Meta+l

16. Capitalize a word

Press Esc+c or Alt+c

Esc+c or Alt+c properly capitalizes a word. Here's an illustration. Let's say you've typed foo bar baz and your cursor is at the beginning of bar:

Before pressing Meta+c

Pressing Esc+c or Alt+c capitalizes the first letter of the word and bar becomes Bar:

After pressing Meta+c

17. Insert a raw character (such as TAB or Ctrl+c)

Press Ctrl+v

Ctrl+v inserts the next character typed verbatim. For example, Ctrl+v followed by <TAB> would insert a literal tab in the command line, or Ctrl+v followed by Ctrl+m would insert a Windows newline (aka carriage return CR).

Here's an illustration. Let's say you've typed echo foo:

Before pressing Ctrl+v

Pressing Ctrl+v followed by Ctrl+m inserts a literal Ctrl+m:

After pressing Ctrl+v Ctrl+m

18. Comment the current line (append # at the beginning quickly)

Press Esc+# or Alt+#

Esc+# or Alt+# quickly comments the line. Here's an illustration. Let's say you typed echo foo bar baz:

Before pressing Meta+#

Pressing Ctrl+# inserts the comment symbol # at the beginning of the line:

After pressing Meta+#

19. Open the current command in a text editor quickly

Press Ctrl+x, Ctrl+e

Pressing CTRL+x followed by CTRL+e opens the current command in your favorite text editor. Exiting the editor will execute the command.

20. Delete a character to the left

Press Ctrl+h

Ctrl+h deletes the character to the left of the cursor. Here's an illustration. Let's say you've typed echo qwerty:

Before pressing Ctrl+h

Pressing Ctrl+h deletes the character to the left:

After pressing Ctrl+h

21. Delete a character to the right

Press Ctrl+d

Ctrl+d deletes the character to the right of the cursor. Here's an illustration. Let's say you've typed echo qwerty:

Before pressing Ctrl+d

Pressing Ctrl+d deletes the character to the right:

After pressing Ctrl+d

22. Incremental undo

Press Ctrl+x, Ctrl+u

Pressing Ctrl+x followed by Ctrl+u undoes a change. Here's an illustration. Let's say you typed foo bar baz and then deleted baz and typed moo:

Before pressing Ctrl+x Ctrl+u

Pressing Ctrl+x, Ctrl+u a few times undoes the last changes and you end up with foo bar baz again:

After pressing Ctrl+x Ctrl+u

23. Insert the last argument from the previous command

Press Esc+. or Alt+.

Esc+. or Alt+. inserts the last argument from the previous command at the current cursor position. Here's an illustration. Let's say you had run ls archive.tgz:

Before pressing Meta+.

And now you want to extract the archive. So all you've to do is type tar -xzf and press Esc+. or Alt+.:

Before pressing Meta+.

24. Undo all changes to the line

Press Esc+r or Alt+r

Esc+r or Alt+r undoes all changes to the line. It's useful when you're going through the command history with Ctrl+r and make changes. If you mess up, you can quickly revert back to the original command by pressing Esc+r or Alt+r.

Here's an illustration. Let's say you searched for grep in history:

Before pressing Meta+r

And let's say you wanted to make some changes to the command but messed up:

Before pressing Meta+r

Pressing Esc+r or Alt+r undoes all the changes and you end up with the original grep command that was in the history:

After pressing Meta+r

25. Clear the screen

Press Ctrl+l

Ctrl+l clears the screen. Alternatively you can type reset.

26. Change input mode to vi

$ set -o vi

This command changes the key bindings to vi's. If vi's your favorite editor, you'll love this. I'll cover the vi mode in more details in the next part of the article.

Cheat Sheet

I made a cheat sheet that lists all the default emacs mode keyboard shortcuts. Download the emacs keyboard shortcut cheat sheet.

Enjoy!

Enjoy the article and let me know in the comments what you think about it!

I thought I'd share my favorite regex of all time:

[ -~]

Any ideas what this regexp matches?

It matches all ASCII characters from the space to the tilde. What are those characters? They're all printable characters!

Take a look at the ASCII table. The printable characters start at the space and end at the tilde:


[ -~] matches all printable ascii characters (light blue background)

I love this.

Update:

Would you like to wear this regular expression? I just had an idea to make it a t-shirt as this blog post is getting so popular. Check out this t-shirt that I made:

This shirt is available through Teespring. Teespring is like Kickstarter for t-shirts. If 50 people buy the shirt, everyone gets their shirt. Otherwise no one gets charged and no one gets the shirt.