UNPKG

32.6 kBJavaScriptView Raw
1//Don't want to call these, but it breaks IE9, so welp
2window.history.pushState = window.history.replaceState = function () {};
3
4var tape = require('tape');
5var test = tape;
6
7tape.Test.prototype.strictEqual = function () {
8 this.equal.apply(this, arguments);
9};
10
11var Backbone = {
12 Router: require('../ampersand-router'),
13 history: require('../ampersand-history')
14};
15Backbone.History = Backbone.history.constructor;
16
17function module(moduleName, opts) {
18 test = function (name, n, cb) {
19 if (!cb && typeof n === 'function') {
20 cb = n;
21 n = null;
22 }
23
24 tape(moduleName + ': ' + name, function (t) {
25 if (opts.setup) opts.setup();
26 if (n) t.plan(n);
27 cb(t);
28 if (opts.teardown) opts.teardown();
29 if (!n) t.end();
30 });
31 };
32 test.only = function (name, n, cb) {
33 tape.only(moduleName + ': ' + name, function (t) {
34 if (opts.setup) opts.setup();
35 if (n) t.plan(n);
36 cb(t);
37 if (opts.teardown) opts.teardown();
38 if (!n) t.end();
39 });
40 };
41}
42
43
44(function () {
45 var bind = require('amp-bind');
46 var extend = require('amp-extend');
47 var each = require('amp-each');
48 var pick = require('amp-pick');
49
50 var router = null;
51 var location = null;
52 var lastRoute = null;
53 var lastArgs = [];
54
55 var onRoute = function (router, route, args) {
56 lastRoute = route;
57 lastArgs = args;
58 };
59
60 var Location = function (href) {
61 this.replace(href);
62 };
63
64 extend(Location.prototype, {
65 parser: document.createElement('a'),
66
67 replace: function (href) {
68 this.parser.href = href;
69 extend(this, pick(this.parser,
70 'href',
71 'hash',
72 'host',
73 'search',
74 'fragment',
75 'pathname',
76 'protocol'
77 ));
78 // In IE, anchor.pathname does not contain a leading slash though
79 // window.location.pathname does.
80 if (!/^\//.test(this.pathname)) this.pathname = '/' + this.pathname;
81 },
82
83 toString: function () {
84 return this.href;
85 }
86 });
87
88 module("Router", {
89 setup: function () {
90 location = new Location('http://example.com');
91 history.location = location;
92 Backbone.history = extend(new Backbone.History(), {location: location});
93 router = new Router({testing: 101, history: Backbone.history});
94 Backbone.history.interval = 9;
95 Backbone.history.start({pushState: false});
96 lastRoute = null;
97 lastArgs = [];
98 Backbone.history.on('route', onRoute);
99 },
100
101 teardown: function () {
102 Backbone.history.stop();
103 Backbone.history.off('route', onRoute);
104 }
105 });
106
107 var ExternalObject = {
108 value: 'unset',
109
110 routingFunction: function (value) {
111 this.value = value;
112 }
113 };
114 ExternalObject.routingFunction = bind(ExternalObject.routingFunction, ExternalObject);
115
116 var Router = Backbone.Router.extend({
117
118 count: 0,
119
120 routes: {
121 "noCallback": "noCallback",
122 "counter": "counter",
123 "search/:query": "search",
124 "search/:query/p:page": "search",
125 "charñ": "charUTF",
126 "char%C3%B1": "charEscaped",
127 "contacts": "contacts",
128 "contacts/new": "newContact",
129 "contacts/:id": "loadContact",
130 "route-event/:arg": "routeEvent",
131 "optional(/:item)": "optionalItem",
132 "named/optional/(y:z)": "namedOptional",
133 "splat/*args/end": "splat",
134 ":repo/compare/*from...*to": "github",
135 "decode/:named/*splat": "decode",
136 "*first/complex-*part/*rest": "complex",
137 "query/:entity": "query",
138 "function/:value": ExternalObject.routingFunction,
139 "*anything": "anything"
140 },
141
142 initialize : function (options) {
143 this.testing = options.testing;
144 this.route('implicit', 'implicit');
145 },
146
147 counter: function () {
148 this.count++;
149 },
150
151 implicit: function () {
152 this.count++;
153 },
154
155 search: function (query, page) {
156 this.query = query;
157 this.page = page;
158 },
159
160 charUTF: function () {
161 this.charType = 'UTF';
162 },
163
164 charEscaped: function () {
165 this.charType = 'escaped';
166 },
167
168 contacts: function () {
169 this.contact = 'index';
170 },
171
172 newContact: function () {
173 this.contact = 'new';
174 },
175
176 loadContact: function () {
177 this.contact = 'load';
178 },
179
180 optionalItem: function (arg) {
181 this.arg = arg != void 0 ? arg : null;
182 },
183
184 splat: function (args) {
185 this.args = args;
186 },
187
188 github: function (repo, from, to) {
189 this.repo = repo;
190 this.from = from;
191 this.to = to;
192 },
193
194 complex: function (first, part, rest) {
195 this.first = first;
196 this.part = part;
197 this.rest = rest;
198 },
199
200 query: function (entity, args) {
201 this.entity = entity;
202 this.queryArgs = args;
203 },
204
205 anything: function (whatever) {
206 this.anything = whatever;
207 },
208
209 namedOptional: function (z) {
210 this.z = z;
211 },
212
213 decode: function (named, path) {
214 this.named = named;
215 this.path = path;
216 },
217
218 routeEvent: function (arg) {
219 }
220
221 });
222
223 test("initialize", 1, function (t) {
224 t.equal(router.testing, 101);
225 });
226
227 test("routes (simple)", 4, function (t) {
228 location.replace('http://example.com#search/news');
229 Backbone.history.checkUrl();
230 t.equal(router.query, 'news');
231 t.equal(router.page, null);
232 t.equal(lastRoute, 'search');
233 t.equal(lastArgs[0], 'news');
234 });
235
236 test("routes (simple, but unicode)", 4, function (t) {
237 location.replace('http://example.com#search/' + encodeURIComponent('тест'));
238 Backbone.history.checkUrl();
239 t.equal(router.query, 'тест');
240 t.equal(router.page, null);
241 t.equal(lastRoute, 'search');
242 t.equal(lastArgs[0], 'тест');
243 });
244
245 test("routes (two part)", 2, function (t) {
246 location.replace('http://example.com#search/nyc/p10');
247 Backbone.history.checkUrl();
248 t.equal(router.query, 'nyc');
249 t.equal(router.page, '10');
250 });
251
252 test("routes via navigate", 2, function (t) {
253 Backbone.history.navigate('search/manhattan/p20', {trigger: true});
254 t.equal(router.query, 'manhattan');
255 t.equal(router.page, '20');
256 });
257
258 test("routes via navigate with params", 1, function (t) {
259 Backbone.history.navigate('query/test?a=b', {trigger: true});
260 t.equal(router.queryArgs, 'a=b');
261 });
262
263 test("routes via navigate for backwards-compatibility", 2, function (t) {
264 Backbone.history.navigate('search/manhattan/p20', true);
265 t.equal(router.query, 'manhattan');
266 t.equal(router.page, '20');
267 });
268
269 test("reports matched route via nagivate", 1, function (t) {
270 t.ok(Backbone.history.navigate('search/manhattan/p20', true));
271 });
272
273 test("route precedence via navigate", 6, function (t) {
274 // check both 0.9.x and backwards-compatibility options
275 each([ { trigger: true }, true ], function (options) {
276 Backbone.history.navigate('contacts', options);
277 t.equal(router.contact, 'index');
278 Backbone.history.navigate('contacts/new', options);
279 t.equal(router.contact, 'new');
280 Backbone.history.navigate('contacts/foo', options);
281 t.equal(router.contact, 'load');
282 });
283 });
284
285 test("loadUrl is not called for identical routes.", 1, function (t) {
286 Backbone.history.loadUrl = function () {t.ok(false); };
287 location.replace('http://example.com#route');
288 Backbone.history.navigate('route');
289 Backbone.history.navigate('/route');
290 Backbone.history.navigate('/route');
291 t.ok(true);
292 });
293
294 test("use implicit callback if none provided", 1, function (t) {
295 router.count = 0;
296 router.navigate('implicit', {trigger: true});
297 t.equal(router.count, 1);
298 });
299
300 test("routes via navigate with {replace: true}", 1, function (t) {
301 location.replace('http://example.com#start_here');
302 Backbone.history.checkUrl();
303 location.replace = function (href) {
304 t.strictEqual(href, new Location('http://example.com#end_here').href);
305 };
306 Backbone.history.navigate('end_here', {replace: true});
307 });
308
309 test("routes (splats)", 1, function (t) {
310 location.replace('http://example.com#splat/long-list/of/splatted_99args/end');
311 Backbone.history.checkUrl();
312 t.equal(router.args, 'long-list/of/splatted_99args');
313 });
314
315 test("routes (github)", 3, function (t) {
316 location.replace('http://example.com#backbone/compare/1.0...braddunbar:with/slash');
317 Backbone.history.checkUrl();
318 t.equal(router.repo, 'backbone');
319 t.equal(router.from, '1.0');
320 t.equal(router.to, 'braddunbar:with/slash');
321 });
322
323 test("routes (optional)", 2, function (t) {
324 location.replace('http://example.com#optional');
325 Backbone.history.checkUrl();
326 t.ok(!router.arg);
327 location.replace('http://example.com#optional/thing');
328 Backbone.history.checkUrl();
329 t.equal(router.arg, 'thing');
330 });
331
332 test("routes (complex)", 3, function (t) {
333 location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven');
334 Backbone.history.checkUrl();
335 t.equal(router.first, 'one/two/three');
336 t.equal(router.part, 'part');
337 t.equal(router.rest, 'four/five/six/seven');
338 });
339
340 test("routes (query)", 5, function (t) {
341 location.replace('http://example.com#query/mandel?a=b&c=d');
342 Backbone.history.checkUrl();
343 t.equal(router.entity, 'mandel');
344 t.equal(router.queryArgs, 'a=b&c=d');
345 t.equal(lastRoute, 'query');
346 t.equal(lastArgs[0], 'mandel');
347 t.equal(lastArgs[1], 'a=b&c=d');
348 });
349
350 test("routes (anything)", 1, function (t) {
351 location.replace('http://example.com#doesnt-match-a-route');
352 Backbone.history.checkUrl();
353 t.equal(router.anything, 'doesnt-match-a-route');
354 });
355
356 test("routes (function)", 3, function (t) {
357 router.on('route', function (name) {
358 t.ok(name === '');
359 });
360 t.equal(ExternalObject.value, 'unset');
361 location.replace('http://example.com#function/set');
362 Backbone.history.checkUrl();
363 t.equal(ExternalObject.value, 'set');
364 });
365
366 test("Decode named parameters, not splats.", 2, function (t) {
367 location.replace('http://example.com#decode/a%2Fb/c%2Fd/e');
368 Backbone.history.checkUrl();
369 t.strictEqual(router.named, 'a/b');
370 t.strictEqual(router.path, 'c/d/e');
371 });
372
373 test("fires event when router doesn't have callback on it", 1, function (t) {
374 router.on("route:noCallback", function () {t.ok(true); });
375 location.replace('http://example.com#noCallback');
376 Backbone.history.checkUrl();
377 });
378
379 test("No events are triggered if #execute returns false.", 1, function (t) {
380 var Router = Backbone.Router.extend({
381
382 routes: {
383 foo: function () {
384 t.ok(true);
385 }
386 },
387
388 execute: function (callback, args) {
389 callback.apply(this, args);
390 return false;
391 }
392
393 });
394
395 var router = new Router({ history: Backbone.history });
396
397 router.on('route route:foo', function () {
398 t.ok(false);
399 });
400
401 Backbone.history.on('route', function () {
402 t.ok(false);
403 });
404
405 location.replace('http://example.com#foo');
406 Backbone.history.checkUrl();
407 });
408
409 test("#933, #908 - leading slash", 2, function (t) {
410 location.replace('http://example.com/root/foo');
411
412 Backbone.history.stop();
413 Backbone.history = extend(new Backbone.History(), {location: location});
414 Backbone.history.start({root: '/root', hashChange: false, silent: true});
415 t.strictEqual(Backbone.history.getFragment(), 'foo');
416
417 Backbone.history.stop();
418 Backbone.history = extend(new Backbone.History(), {location: location});
419 Backbone.history.start({root: '/root/', hashChange: false, silent: true});
420 t.strictEqual(Backbone.history.getFragment(), 'foo');
421 });
422
423 test("#1003 - History is started before navigate is called", 1, function (t) {
424 Backbone.history.stop();
425 Backbone.history.navigate = function () {t.ok(Backbone.History.started); };
426 Backbone.history.start();
427 // If this is not an old IE navigate will not be called.
428 if (!Backbone.history.iframe) t.ok(true);
429 });
430
431 test("#967 - Route callback gets passed encoded values.", 3, function (t) {
432 var route = 'has%2Fslash/complex-has%23hash/has%20space';
433 Backbone.history.navigate(route, {trigger: true});
434 t.strictEqual(router.first, 'has/slash');
435 t.strictEqual(router.part, 'has#hash');
436 t.strictEqual(router.rest, 'has space');
437 });
438
439 test("correctly handles URLs with % (#868)", 3, function (t) {
440 location.replace('http://example.com#search/fat%3A1.5%25');
441 Backbone.history.checkUrl();
442 location.replace('http://example.com#search/fat');
443 Backbone.history.checkUrl();
444 t.equal(router.query, 'fat');
445 t.equal(router.page, null);
446 t.equal(lastRoute, 'search');
447 });
448
449 test("#2666 - Hashes with UTF8 in them.", 2, function (t) {
450 Backbone.history.navigate('charñ', {trigger: true});
451 t.equal(router.charType, 'UTF');
452 Backbone.history.navigate('char%C3%B1', {trigger: true});
453 t.equal(router.charType, 'UTF');
454 });
455
456 test("#1185 - Use pathname when hashChange is not wanted.", 1, function (t) {
457 Backbone.history.stop();
458 location.replace('http://example.com/path/name#hash');
459 Backbone.history = extend(new Backbone.History(), {location: location});
460 Backbone.history.start({hashChange: false});
461 var fragment = Backbone.history.getFragment();
462 t.strictEqual(fragment, location.pathname.replace(/^\//, ''));
463 });
464
465 test("#1206 - Strip leading slash before location.assign.", 1, function (t) {
466 Backbone.history.stop();
467 location.replace('http://example.com/root/');
468 Backbone.history = extend(new Backbone.History(), {location: location});
469 Backbone.history.start({hashChange: false, root: '/root/'});
470 location.assign = function (pathname) {
471 t.strictEqual(pathname, '/root/fragment');
472 };
473 Backbone.history.navigate('/fragment');
474 });
475
476 test("#1387 - Root fragment without trailing slash.", 1, function (t) {
477 Backbone.history.stop();
478 location.replace('http://example.com/root');
479 Backbone.history = extend(new Backbone.History(), {location: location});
480 Backbone.history.start({hashChange: false, root: '/root/', silent: true});
481 t.strictEqual(Backbone.history.getFragment(), '');
482 });
483
484 test("#1366 - History does not prepend root to fragment.", 2, function (t) {
485 Backbone.history.stop();
486 location.replace('http://example.com/root/');
487 Backbone.history = extend(new Backbone.History(), {
488 location: location,
489 history: {
490 pushState: function (state, title, url) {
491 t.strictEqual(url, '/root/x');
492 }
493 }
494 });
495 Backbone.history.start({
496 root: '/root/',
497 pushState: true,
498 hashChange: false
499 });
500 Backbone.history.navigate('x');
501 t.strictEqual(Backbone.history.fragment, 'x');
502 });
503
504 test("Normalize root.", 1, function (t) {
505 Backbone.history.stop();
506 location.replace('http://example.com/root');
507 Backbone.history = extend(new Backbone.History(), {
508 location: location,
509 history: {
510 pushState: function (state, title, url) {
511 t.strictEqual(url, '/root/fragment');
512 }
513 }
514 });
515 Backbone.history.start({
516 pushState: true,
517 root: '/root',
518 hashChange: false
519 });
520 Backbone.history.navigate('fragment');
521 });
522
523 test("Normalize root.", 1, function (t) {
524 Backbone.history.stop();
525 location.replace('http://example.com/root#fragment');
526 Backbone.history = extend(new Backbone.History(), {
527 location: location,
528 history: {
529 pushState: function (state, title, url) {},
530 replaceState: function (state, title, url) {
531 t.strictEqual(url, '/root/fragment');
532 }
533 }
534 });
535 Backbone.history.start({
536 pushState: true,
537 root: '/root'
538 });
539 });
540
541 test("Normalize root.", 1, function (t) {
542 Backbone.history.stop();
543 location.replace('http://example.com/root');
544 Backbone.history = extend(new Backbone.History(), {location: location});
545 Backbone.history.loadUrl = function () {t.ok(true); };
546 Backbone.history.start({
547 pushState: true,
548 root: '/root'
549 });
550 });
551
552 test("Normalize root - leading slash.", 1, function (t) {
553 Backbone.history.stop();
554 location.replace('http://example.com/root');
555 Backbone.history = extend(new Backbone.History(), {
556 location: location,
557 history: {
558 pushState: function () {},
559 replaceState: function () {}
560 }
561 });
562 Backbone.history.start({root: 'root'});
563 t.strictEqual(Backbone.history.root, '/root/');
564 });
565
566 test("Transition from hashChange to pushState.", 1, function (t) {
567 Backbone.history.stop();
568 location.replace('http://example.com/root#x/y');
569 Backbone.history = extend(new Backbone.History(), {
570 location: location,
571 history: {
572 pushState: function () {},
573 replaceState: function (state, title, url) {
574 t.strictEqual(url, '/root/x/y');
575 }
576 }
577 });
578 Backbone.history.start({
579 root: 'root',
580 pushState: true
581 });
582 });
583
584 test("#1619: Router: Normalize empty root", 1, function (t) {
585 Backbone.history.stop();
586 location.replace('http://example.com/');
587 Backbone.history = extend(new Backbone.History(), {
588 location: location,
589 history: {
590 pushState: function () {},
591 replaceState: function () {}
592 }
593 });
594 Backbone.history.start({root: ''});
595 t.strictEqual(Backbone.history.root, '/');
596 });
597
598 test("#1619: Router: nagivate with empty root", 1, function (t) {
599 Backbone.history.stop();
600 location.replace('http://example.com/');
601 Backbone.history = extend(new Backbone.History(), {
602 location: location,
603 history: {
604 pushState: function (state, title, url) {
605 t.strictEqual(url, '/fragment');
606 }
607 }
608 });
609 Backbone.history.start({
610 pushState: true,
611 root: '',
612 hashChange: false
613 });
614 Backbone.history.navigate('fragment');
615 });
616
617 test("Transition from pushState to hashChange.", 1, function (t) {
618 Backbone.history.stop();
619 location.replace('http://example.com/root/x/y?a=b');
620 location.replace = function (url) {
621 t.strictEqual(url, '/root/#x/y?a=b');
622 };
623 Backbone.history = extend(new Backbone.History(), {
624 location: location,
625 history: {
626 pushState: null,
627 replaceState: null
628 }
629 });
630 Backbone.history.start({
631 root: 'root',
632 pushState: true
633 });
634 });
635
636 test("#1695 - hashChange to pushState with search.", 1, function (t) {
637 Backbone.history.stop();
638 location.replace('http://example.com/root#x/y?a=b');
639 Backbone.history = extend(new Backbone.History(), {
640 location: location,
641 history: {
642 pushState: function () {},
643 replaceState: function (state, title, url) {
644 t.strictEqual(url, '/root/x/y?a=b');
645 }
646 }
647 });
648 Backbone.history.start({
649 root: 'root',
650 pushState: true
651 });
652 });
653
654 test("#1746 - Router allows empty route.", 1, function (t) {
655 var Router = Backbone.Router.extend({
656 routes: {'': 'empty'},
657 empty: function () {},
658 route: function (route) {
659 t.strictEqual(route, '');
660 }
661 });
662 new Router();
663 });
664
665 test("#1794 - Trailing space in fragments.", 1, function (t) {
666 var history = new Backbone.History();
667 t.strictEqual(history.getFragment('fragment '), 'fragment');
668 });
669
670 test("#1820 - Leading slash and trailing space.", 1, function (t) {
671 var history = new Backbone.History();
672 t.strictEqual(history.getFragment('/fragment '), 'fragment');
673 });
674
675 test("#1980 - Optional parameters.", 2, function (t) {
676 location.replace('http://example.com#named/optional/y');
677 Backbone.history.checkUrl();
678 t.strictEqual(router.z, undefined);
679 location.replace('http://example.com#named/optional/y123');
680 Backbone.history.checkUrl();
681 t.strictEqual(router.z, '123');
682 });
683
684 test("#2062 - Trigger 'route' event on router instance.", 2, function (t) {
685 router.on('route', function (name, args) {
686 t.strictEqual(name, 'routeEvent');
687 t.deepEqual(args, ['x', null]);
688 });
689 location.replace('http://example.com#route-event/x');
690 Backbone.history.checkUrl();
691 });
692
693 test("#2255 - Extend routes by making routes a function.", 1, function (t) {
694 var RouterBase = Backbone.Router.extend({
695 routes: function () {
696 return {
697 home: "root",
698 index: "index.html"
699 };
700 }
701 });
702
703 var RouterExtended = RouterBase.extend({
704 routes: function () {
705 var _super = RouterExtended.__super__.routes;
706 return extend(_super(),
707 { show: "show",
708 search: "search" });
709 }
710 });
711
712 var router = new RouterExtended();
713 t.deepEqual({home: "root", index: "index.html", show: "show", search: "search"}, router.routes);
714 });
715
716 test("#2538 - hashChange to pushState only if both requested.", 1, function (t) {
717 Backbone.history.stop();
718 location.replace('http://example.com/root?a=b#x/y');
719 Backbone.history = extend(new Backbone.History(), {
720 location: location,
721 history: {
722 pushState: function () {},
723 replaceState: function () {t.ok(false); }
724 }
725 });
726 Backbone.history.start({
727 root: 'root',
728 pushState: true,
729 hashChange: false
730 });
731 t.ok(true);
732 });
733
734 test('No hash fallback.', 1, function (t) {
735 Backbone.history.stop();
736 Backbone.history = extend(new Backbone.History(), {
737 location: location,
738 history: {
739 pushState: function () {},
740 replaceState: function () {}
741 }
742 });
743
744 var Router = Backbone.Router.extend({
745 routes: {
746 hash: function () {t.ok(false); }
747 }
748 });
749 var router = new Router({ history: Backbone.history });
750
751 location.replace('http://example.com/');
752 Backbone.history.start({
753 pushState: true,
754 hashChange: false
755 });
756 location.replace('http://example.com/nomatch#hash');
757 Backbone.history.checkUrl();
758 t.ok(true);
759 });
760
761 test('#2656 - No trailing slash on root.', 1, function (t) {
762 Backbone.history.stop();
763 Backbone.history = extend(new Backbone.History(), {
764 location: location,
765 history: {
766 pushState: function (state, title, url) {
767 t.strictEqual(url, '/root');
768 }
769 }
770 });
771 location.replace('http://example.com/root/path');
772 Backbone.history.start({pushState: true, hashChange: false, root: 'root'});
773 Backbone.history.navigate('');
774 });
775
776 test('#2656 - No trailing slash on root.', 1, function (t) {
777 Backbone.history.stop();
778 Backbone.history = extend(new Backbone.History(), {
779 location: location,
780 history: {
781 pushState: function (state, title, url) {
782 t.strictEqual(url, '/');
783 }
784 }
785 });
786 location.replace('http://example.com/path');
787 Backbone.history.start({pushState: true, hashChange: false});
788 Backbone.history.navigate('');
789 });
790
791 test('#2765 - Fragment matching sans query/hash.', 2, function (t) {
792 Backbone.history.stop();
793 Backbone.history = extend(new Backbone.History(), {
794 location: location,
795 history: {
796 pushState: function (state, title, url) {
797 t.strictEqual(url, '/path?query#hash');
798 }
799 }
800 });
801
802 var Router = Backbone.Router.extend({
803 routes: {
804 path: function () {t.ok(true); }
805 }
806 });
807 var router = new Router({ history: Backbone.history });
808
809 location.replace('http://example.com/');
810 Backbone.history.start({pushState: true, hashChange: false});
811 Backbone.history.navigate('path?query#hash', true);
812 });
813
814 test('Do not decode the search params.', 1, function (t) {
815 var Router = Backbone.Router.extend({
816 routes: {
817 path: function (params) {
818 t.strictEqual(params, 'x=y z');
819 }
820 }
821 });
822 var router = new Router({ history: Backbone.history });
823 Backbone.history.navigate('path?x=y%20z', true);
824 });
825
826 test('Navigate to a hash url.', 1, function (t) {
827 Backbone.history.stop();
828 Backbone.history = extend(new Backbone.History(), {location: location});
829 Backbone.history.start({pushState: true});
830 var Router = Backbone.Router.extend({
831 routes: {
832 path: function (params) {
833 t.strictEqual(params, 'x=y');
834 }
835 }
836 });
837 var router = new Router({ history: Backbone.history });
838 location.replace('http://example.com/path?x=y#hash');
839 Backbone.history.checkUrl();
840 });
841
842 test('#navigate to a hash url.', 1, function (t) {
843 Backbone.history.stop();
844 Backbone.history = extend(new Backbone.History(), {location: location});
845 Backbone.history.start({pushState: true});
846 var Router = Backbone.Router.extend({
847 routes: {
848 path: function (params) {
849 t.strictEqual(params, 'x=y');
850 }
851 }
852 });
853 var router = new Router({ history: Backbone.history });
854 Backbone.history.navigate('path?x=y#hash', true);
855 });
856
857 test('unicode pathname', 1, function (t) {
858 location.replace('http://example.com/myyjä');
859 Backbone.history.stop();
860 Backbone.history = extend(new Backbone.History(), {location: location});
861 var Router = Backbone.Router.extend({
862 routes: {
863 'myyjä': function () {
864 t.ok(true);
865 }
866 }
867 });
868 var router = new Router({ history: Backbone.history });
869 Backbone.history.start({pushState: true});
870 });
871
872 test('newline in route', 1, function (t) {
873 location.replace('http://example.com/stuff%0Anonsense?param=foo%0Abar');
874 Backbone.history.stop();
875 Backbone.history = extend(new Backbone.History(), {location: location});
876 var Router = Backbone.Router.extend({
877 routes: {
878 'stuff\nnonsense': function () {
879 t.ok(true);
880 }
881 }
882 });
883 new Router({ history: Backbone.history });
884 Backbone.history.start({pushState: true});
885 });
886
887 test('Router#execute receives callback, args, name.', 3, function (t) {
888 location.replace('http://example.com#foo/123/bar?x=y');
889 Backbone.history.stop();
890 Backbone.history = extend(new Backbone.History(), {location: location});
891 var Router = Backbone.Router.extend({
892 routes: {'foo/:id/bar': 'foo'},
893 foo: function () {},
894 execute: function (callback, args, name) {
895 t.strictEqual(callback, this.foo);
896 t.deepEqual(args, ['123', 'x=y']);
897 t.strictEqual(name, 'foo');
898 }
899 });
900 var router = new Router({ history: Backbone.history });
901 Backbone.history.start();
902 });
903
904 test("pushState to hashChange with only search params.", 1, function (t) {
905 Backbone.history.stop();
906 location.replace('http://example.com?a=b');
907 location.replace = function (url) {
908 t.strictEqual(url, '/#?a=b');
909 };
910 Backbone.history = extend(new Backbone.History(), {
911 location: location,
912 history: null
913 });
914 Backbone.history.start({pushState: true});
915 });
916
917 test("#3123 - History#navigate decodes before comparison.", 1, function (t) {
918 Backbone.history.stop();
919 location.replace('http://example.com/shop/search?keyword=short%20dress');
920 Backbone.history = extend(new Backbone.History(), {
921 location: location,
922 history: {
923 pushState: function () {t.ok(false); },
924 replaceState: function () {t.ok(false); }
925 }
926 });
927 Backbone.history.start({pushState: true});
928 Backbone.history.navigate('shop/search?keyword=short%20dress', true);
929 t.strictEqual(Backbone.history.fragment, 'shop/search?keyword=short dress');
930 });
931
932 test('#3175 - Urls in the params', 1, function (t) {
933 Backbone.history.stop();
934 location.replace('http://example.com#login?a=value&backUrl=https%3A%2F%2Fwww.msn.com%2Fidp%2Fidpdemo%3Fspid%3Dspdemo%26target%3Db');
935 Backbone.history = extend(new Backbone.History(), {location: location});
936 var router = new Backbone.Router({ history: Backbone.history });
937 router.route('login', function (params) {
938 t.strictEqual(params, 'a=value&backUrl=https%3A%2F%2Fwww.msn.com%2Fidp%2Fidpdemo%3Fspid%3Dspdemo%26target%3Db');
939 });
940 Backbone.history.start();
941 });
942
943 test("redirectTo", 2, function (t) {
944 Backbone.history.stop();
945 location.replace('http://example.com/redirect');
946 Backbone.history = extend(new Backbone.History(), {location: location});
947 var router = new Backbone.Router({ history: Backbone.history });
948 router.route('redirect', function () {
949 t.ok('yup');
950 this.redirectTo('other');
951 });
952 router.route('other', function () {
953 t.pass();
954 });
955 Backbone.history.start({pushState: true});
956 });
957
958})();