var expect = chai.expect;
var router = new RouterRouter();

// Override browser's native Location object. See:
// https://github.com/jashkenas/backbone/blob/master/test/router.js#L13-L41
var Location = function(href) {
	this.replace(href);
};

Location.prototype = {
	parser: document.createElement('a'),

	replace: function(href) {
		this.parser.href = href;

		this.href = this.parser.href;
		this.hash = this.parser.hash;
		this.host = this.parser.host;
		this.search = this.parser.search;
		this.fragment = this.parser.fragment;
		this.pathname = this.parser.pathname;
		this.protocol = this.parser.protocol;

		// In IE, anchor.pathname does not contain a leading slash though
		// window.location.pathname does.
		if (!/^\//.test(this.pathname)) this.pathname = '/' + this.pathname;
	},

	toString: function() {
		return this.href;
	}
};

describe('RouterRouter', function() {
	it('should match an empty string.', function() {
		isIndex = false;

		router.location = new Location('http://example.com');

		router.route('', function() {
			isIndex = true;
		});

		expect(isIndex).to.equal(true);
	});

	it('should match parameter parts.', function() {
		router.location = new Location('http://example.com/1/2/3');

		router.route(':foo/:bar/:biz', function(foo, bar, biz) {
			expect(foo).to.equal('1');
			expect(bar).to.equal('2');
			expect(biz).to.equal('3');
		});
	});

	it('should match splat parts.', function() {
		router.location = new Location('http://example.com/path/to/some/file.txt');

		router.route('path/*foo', function(foo) {
			expect(foo).to.equal('to/some/file.txt');
		});
	});

	it('should match optional parts.', function() {
		router.location = new Location('http://example.com/blog/sample-post-title');

		router.route(':foo(/:bar)', function(foo, bar) {
			expect(foo).to.equal('blog');
			expect(bar).to.equal('sample-post-title');
		});

		router.location = new Location('http://example.com/blog');

		router.route(':foo(/:bar)', function(foo, bar) {
			expect(foo).to.equal('blog');
			expect(bar).to.equal(null);
		});
	});
});
@@ -1594,34 +1594,40 @@
 );%0A%09%09%7D);%0A%09%7D);%0A%0A%09
-it
+describe
 ('should match o
@@ -1635,24 +1635,105 @@
 tional parts
+ and', function() %7B%0A%09%09it('returns the optional part when an optional part matches
 .', function
@@ -1729,32 +1729,33 @@
 ', function() %7B%0A
+%09
 %09%09router.locatio
@@ -1816,24 +1816,25 @@
 title');%0A%0A%09%09
+%09
 router.route
@@ -1862,32 +1862,33 @@
 ion(foo, bar) %7B%0A
+%09
 %09%09%09expect(foo).t
@@ -1899,32 +1899,33 @@
 ual('blog');%0A%09%09%09
+%09
 expect(bar).to.e
@@ -1953,21 +1953,101 @@
 le');%0A%09%09
-%7D);%0A%0A
+%09%7D);%0A%09%09%7D);%0A%0A%09%09it('returns null when an optional part does not match.', function() %7B%0A%09
 %09%09router
@@ -2098,24 +2098,25 @@
 /blog');%0A%0A%09%09
+%09
 router.route
@@ -2148,24 +2148,25 @@
 foo, bar) %7B%0A
+%09
 %09%09%09expect(fo
@@ -2185,24 +2185,25 @@
 'blog');%0A%09%09%09
+%09
 expect(bar).
@@ -2218,16 +2218,23 @@
 (null);%0A
+%09%09%09%7D);%0A
 %09%09%7D);%0A%09%7D

Split optional parts test into separate tests. PR #5 feedback.