1 |
|
2 | window.history.pushState = window.history.replaceState = function () {};
|
3 |
|
4 | var tape = require('tape');
|
5 | var test = tape;
|
6 |
|
7 | tape.Test.prototype.strictEqual = function () {
|
8 | this.equal.apply(this, arguments);
|
9 | };
|
10 |
|
11 | var Backbone = {
|
12 | Router: require('../ampersand-router'),
|
13 | history: require('../ampersand-history')
|
14 | };
|
15 | Backbone.History = Backbone.history.constructor;
|
16 |
|
17 | function 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 |
|
79 |
|
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 |
|
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 |
|
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 | })();
|