Completed
Push — master ( e2c47b...19fc28 )
by Felipe
52s
created

test/router.js   F

Complexity

Total Complexity 153
Complexity/F 1.01

Size

Lines of Code 1062
Function Count 151

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
c 1
b 0
f 0
nc 2
dl 0
loc 1062
rs 2.3235
wmc 153
mnd 1
bc 151
fnc 151
bpm 1
cpm 1.0132
noi 504

How to fix   Complexity   

Complexity

Complex classes like test/router.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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