diff --git a/packages/ember/tests/routing/query_params_test.js b/packages/ember/tests/routing/query_params_test.js index 71d2a05d3ea..337ca8be02f 100644 --- a/packages/ember/tests/routing/query_params_test.js +++ b/packages/ember/tests/routing/query_params_test.js @@ -5,1489 +5,1370 @@ import { A as emberA, String as StringUtils } from 'ember-runtime'; -import { Route, NoneLocation } from 'ember-routing'; import { run, get, computed, - Mixin, meta } from 'ember-metal'; -import { compile } from 'ember-template-compiler'; -import { Application } from 'ember-application'; +import { Route } from 'ember-routing'; import { jQuery } from 'ember-views'; -import { setTemplates } from 'ember-glimmer'; - -let App, router, container; - -function bootApplication() { - router = container.lookup('router:main'); - run(App, 'advanceReadiness'); -} - -function handleURL(path) { - return run(() => { - return router.handleURL(path).then(function(value) { - ok(true, 'url: `' + path + '` was handled'); - return value; - }, function(reason) { - ok(false, 'failed to visit:`' + path + '` reason: `' + QUnit.jsDump.parse(reason)); - throw reason; - }); - }); -} - -let startingURL = ''; -let expectedReplaceURL, expectedPushURL; - -function setAndFlush(obj, prop, value) { - run(obj, 'set', prop, value); -} - -const TestLocation = NoneLocation.extend({ - initState() { - this.set('path', startingURL); - }, - - setURL(path) { - if (expectedReplaceURL) { - ok(false, 'pushState occurred but a replaceState was expected'); - } - if (expectedPushURL) { - equal(path, expectedPushURL, 'an expected pushState occurred'); - expectedPushURL = null; - } - this.set('path', path); - }, - - replaceURL(path) { - if (expectedPushURL) { - ok(false, 'replaceState occurred but a pushState was expected'); - } - if (expectedReplaceURL) { - equal(path, expectedReplaceURL, 'an expected replaceState occurred'); - expectedReplaceURL = null; - } - this.set('path', path); + +import { QueryParamTestCase, moduleFor } from 'internal-test-helpers'; + +moduleFor('Query Params - main', class extends QueryParamTestCase { + // Sets up a controller with a single query param + setSingleQPController(routeName, param = 'foo', defaultValue = 'bar', options = {}) { + this.registerController(routeName, Controller.extend({ + queryParams: [param], + [param]: defaultValue + }, options)); } -}); -function sharedSetup() { - run(() => { - App = Application.create({ - name: 'App', - rootElement: '#qunit-fixture' + ['@test No replaceURL occurs on startup because default values don\'t show up in URL'](assert) { + assert.expect(1); + + this.setSingleQPController('index'); + + return this.visitAndAssert('/'); + } + + ['@test Calling transitionTo does not lose query params already on the activeTransition'](assert) { + assert.expect(2); + + this.router.map(function() { + this.route('parent', function() { + this.route('child'); + this.route('sibling'); + }); }); - App.deferReadiness(); + this.registerRoute('parent.child', Route.extend({ + afterModel() { + this.transitionTo('parent.sibling'); + } + })); - container = App.__container__; + this.setSingleQPController('parent'); - App.register('location:test', TestLocation); + return this.visit('/parent/child?foo=lol').then(() => { + this.assertCurrentPath('/parent/sibling?foo=lol', 'redirected to the sibling route, instead of child route'); + assert.equal(this.getController('parent').get('foo'), 'lol', 'controller has value from the active transition'); + }); + } - startingURL = expectedReplaceURL = expectedPushURL = ''; + ['@test Single query params can be set on the controller and reflected in the url'](assert) { + assert.expect(3); - App.Router.reopen({ - location: 'test' + this.router.map(function() { + this.route('home', { path: '/' }); }); - App.LoadingRoute = Route.extend({ + this.setSingleQPController('home'); + + return this.visitAndAssert('/').then(() => { + let controller = this.getController('home'); + + this.setAndFlush(controller, 'foo', '456'); + this.assertCurrentPath('/?foo=456'); + + this.setAndFlush(controller, 'foo', '987'); + this.assertCurrentPath('/?foo=987'); }); + } + + ['@test Query params can map to different url keys configured on the controller'](assert) { + assert.expect(6); + + this.registerController('index', Controller.extend({ + queryParams: [{ foo: 'other_foo', bar: { as: 'other_bar' } }], + foo: 'FOO', + bar: 'BAR' + })); + + return this.visitAndAssert('/').then(() => { + let controller = this.getController('index'); - App.register('template:application', compile('{{outlet}}')); - App.register('template:home', compile('

Hours

')); - }); -} + this.setAndFlush(controller, 'foo', 'LEX'); + this.assertCurrentPath('/?other_foo=LEX', 'QP mapped correctly without \'as\''); -function sharedTeardown() { - try { - run(() => { - App.destroy(); - App = null; + this.setAndFlush(controller, 'foo', 'WOO'); + this.assertCurrentPath('/?other_foo=WOO', 'QP updated correctly without \'as\''); + + this.transitionTo('/?other_foo=NAW'); + assert.equal(controller.get('foo'), 'NAW', 'QP managed correctly on URL transition'); + + this.setAndFlush(controller, 'bar', 'NERK'); + this.assertCurrentPath('/?other_bar=NERK&other_foo=NAW', 'QP mapped correctly with \'as\''); + + this.setAndFlush(controller, 'bar', 'NUKE'); + this.assertCurrentPath('/?other_bar=NUKE&other_foo=NAW', 'QP updated correctly with \'as\''); }); - } finally { - setTemplates({}); } -} -// jscs:disable + ['@test Routes have a private overridable serializeQueryParamKey hook'](assert) { + assert.expect(2); + + this.registerRoute('index', Route.extend({ + serializeQueryParamKey: StringUtils.dasherize + })); + + this.setSingleQPController('index', 'funTimes', ''); -QUnit.module('Routing with Query Params', { - setup() { - sharedSetup(); - }, + return this.visitAndAssert('/').then(() => { + let controller = this.getController('index'); - teardown() { - sharedTeardown(); + this.setAndFlush(controller, 'funTimes', 'woot'); + this.assertCurrentPath('/?fun-times=woot'); + }); } -}); -QUnit.test('Calling transitionTo does not lose query params already on the activeTransition', function() { - expect(2); - App.Router.map(function() { - this.route('parent', function() { - this.route('child'); - this.route('sibling'); + ['@test Can override inherited QP behavior by specifying queryParams as a computed property'](assert) { + assert.expect(3); + + this.setSingleQPController('index', 'a', 0, { + queryParams: computed(function() { + return ['c']; + }), + c: true }); - }); - App.ParentChildRoute = Route.extend({ - afterModel: function() { - ok(true, 'The after model hook was called'); - this.transitionTo('parent.sibling'); - } - }); + return this.visitAndAssert('/').then(() => { + let indexController = this.getController('index'); - App.ParentController = Controller.extend({ - queryParams: ['foo'], - foo: 'bar' - }); + this.setAndFlush(indexController, 'a', 1); + this.assertCurrentPath('/', 'QP did not update due to being overriden'); - startingURL = '/parent/child?foo=lol'; - bootApplication(); + this.setAndFlush(indexController, 'c', false); + this.assertCurrentPath('/?c=false', 'QP updated with overriden param'); + }); + } - let parentController = container.lookup('controller:parent'); + ['@test Can concatenate inherited QP behavior by specifying queryParams as an array'](assert) { + assert.expect(3); - equal(parentController.get('foo'), 'lol'); -}); + this.setSingleQPController('index', 'a', 0, { + queryParams: ['c'], + c: true + }); -QUnit.test('Single query params can be set on the controller [DEPRECATED]', function() { - App.Router.map(function() { - this.route('home', { path: '/' }); - }); + return this.visitAndAssert('/').then(() => { + let indexController = this.getController('index'); - App.HomeController = Controller.extend({ - queryParams: ['foo'], - foo: '123' - }); + this.setAndFlush(indexController, 'a', 1); + this.assertCurrentPath('/?a=1', 'Inherited QP did update'); - bootApplication(); + this.setAndFlush(indexController, 'c', false); + this.assertCurrentPath('/?a=1&c=false', 'New QP did update'); + }); + } - let controller = container.lookup('controller:home'); + ['@test model hooks receives query params'](assert) { + assert.expect(2); - setAndFlush(controller, 'foo', '456'); + this.setSingleQPController('index'); - equal(router.get('location.path'), '/?foo=456'); + this.registerRoute('index', Route.extend({ + model(params) { + assert.deepEqual(params, { foo: 'bar' }); + } + })); - setAndFlush(controller, 'foo', '987'); - equal(router.get('location.path'), '/?foo=987'); -}); + return this.visitAndAssert('/'); + } -QUnit.test('Single query params can be set on the controller [DEPRECATED]', function() { - App.Router.map(function() { - this.route('home', { path: '/' }); - }); + ['@test model hooks receives query params with dynamic segment params'](assert) { + assert.expect(2); - App.HomeController = Controller.extend({ - queryParams: ['foo'], - foo: '123' - }); + this.router.map(function() { + this.route('index', { path: '/:id' }); + }); - bootApplication(); + this.setSingleQPController('index'); - let controller = container.lookup('controller:home'); + this.registerRoute('index', Route.extend({ + model(params) { + assert.deepEqual(params, { foo: 'bar', id: 'baz' }); + } + })); - setAndFlush(controller, 'foo', '456'); + return this.visitAndAssert('/baz'); + } - equal(router.get('location.path'), '/?foo=456'); + ['@test model hooks receives query params (overridden by incoming url value)'](assert) { + assert.expect(2); - setAndFlush(controller, 'foo', '987'); - equal(router.get('location.path'), '/?foo=987'); -}); + this.router.map(function() { + this.route('index', { path: '/:id' }); + }); -QUnit.test('Query params can map to different url keys configured on the controller [DEPRECATED]', function() { - App.IndexController = Controller.extend({ - queryParams: [{ foo: 'other_foo', bar: { as: 'other_bar' } }], - foo: 'FOO', - bar: 'BAR' - }); + this.setSingleQPController('index'); - bootApplication(); - equal(router.get('location.path'), ''); + this.registerRoute('index', Route.extend({ + model(params) { + assert.deepEqual(params, { foo: 'baz', id: 'boo' }); + } + })); - let controller = container.lookup('controller:index'); - setAndFlush(controller, 'foo', 'LEX'); + return this.visitAndAssert('/boo?foo=baz'); + } - equal(router.get('location.path'), '/?other_foo=LEX'); - setAndFlush(controller, 'foo', 'WOO'); - equal(router.get('location.path'), '/?other_foo=WOO'); + // FIXME: What is the correct behavior below? + ['@skip dynamic segment and query param have same name'](assert) { + assert.expect(2); - run(router, 'transitionTo', '/?other_foo=NAW'); - equal(controller.get('foo'), 'NAW'); + this.router.map(function() { + this.route('index', { path: '/:foo' }); + }); - setAndFlush(controller, 'bar', 'NERK'); - run(router, 'transitionTo', '/?other_bar=NERK&other_foo=NAW'); -}); + this.setSingleQPController('index'); -QUnit.test('Routes have overridable serializeQueryParamKey hook', function() { - App.IndexRoute = Route.extend({ - serializeQueryParamKey: StringUtils.dasherize - }); + this.registerRoute('index', Route.extend({ + model(params) { + assert.deepEqual(params, { foo: 'boo' }); + } + })); - App.IndexController = Controller.extend({ - queryParams: 'funTimes', - funTimes: '' - }); + return this.visitAndAssert('/boo?foo=baz'); + } - bootApplication(); - equal(router.get('location.path'), ''); + ['@test controllers won\'t be eagerly instantiated by internal query params logic'](assert) { + assert.expect(10); - let controller = container.lookup('controller:index'); - setAndFlush(controller, 'funTimes', 'woot'); + this.router.map(function() { + this.route('cats', function() { + this.route('index', { path: '/' }); + }); + this.route('home', { path: '/' }); + this.route('about'); + }); - equal(router.get('location.path'), '/?fun-times=woot'); -}); + this.registerTemplate('home', `

{{link-to 'About' 'about' (query-params lol='wat') id='link-to-about'}}

`); + this.registerTemplate('about', `

{{link-to 'Home' 'home' (query-params foo='naw')}}

`); + this.registerTemplate('cats.index', `

{{link-to 'Cats' 'cats' (query-params name='domino') id='cats-link'}}

`); -QUnit.test('No replaceURL occurs on startup because default values don\'t show up in URL', function() { - expect(0); + let homeShouldBeCreated = false; + let aboutShouldBeCreated = false; + let catsIndexShouldBeCreated = false; - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: '123' - }); + this.registerRoute('home', Route.extend({ + setup() { + homeShouldBeCreated = true; + this._super(...arguments); + } + })); - expectedReplaceURL = '/?foo=123'; + this.setSingleQPController('home', 'foo', '123', { + init() { + this._super(...arguments); + assert.ok(homeShouldBeCreated, 'HomeController should be created at this time'); + } + }); - bootApplication(); -}); + this.registerRoute('about', Route.extend({ + setup() { + aboutShouldBeCreated = true; + this._super(...arguments); + } + })); -QUnit.test('Can override inherited QP behavior by specifying queryParams as a computed property', function() { - expect(0); - let SharedMixin = Mixin.create({ - queryParams: ['a'], - a: 0 - }); - - App.IndexController = Controller.extend(SharedMixin, { - queryParams: computed(function() { - return ['c']; - }), - c: true - }); - - bootApplication(); - let indexController = container.lookup('controller:index'); - - expectedReplaceURL = 'not gonna happen'; - run(indexController, 'set', 'a', 1); -}); + this.setSingleQPController('about', 'lol', 'haha', { + init() { + this._super(...arguments); + assert.ok(aboutShouldBeCreated, 'AboutController should be created at this time'); + } + }); -QUnit.test('model hooks receives query params', function() { - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); + this.registerRoute('cats.index', Route.extend({ + model() { + return []; + }, + setup() { + catsIndexShouldBeCreated = true; + this._super(...arguments); + }, + setupController(controller, context) { + controller.set('model', context); + } + })); + + this.registerController('cats.index', Controller.extend({ + queryParams: ['breed', 'name'], + breed: 'Golden', + name: null, + init() { + this._super(...arguments); + assert.ok(catsIndexShouldBeCreated, 'CatsIndexController should be created at this time'); + } + })); - App.IndexRoute = Route.extend({ - model(params) { - deepEqual(params, { omg: 'lol' }); - } - }); + return this.visitAndAssert('/').then(() => { + let controller = this.getController('home'); - bootApplication(); + this.setAndFlush(controller, 'foo', '456'); + this.assertCurrentPath('/?foo=456'); + assert.equal(jQuery('#link-to-about').attr('href'), '/about?lol=wat', 'link to about is correct'); - equal(router.get('location.path'), ''); -}); + this.transitionTo('about'); + this.assertCurrentPath('/about'); -QUnit.test('controllers won\'t be eagerly instantiated by internal query params logic', function() { - expect(10); - App.Router.map(function() { - this.route('cats', function() { - this.route('index', { path: '/' }); - }); - this.route('home', { path: '/' }); - this.route('about'); - }); - - App.register('template:home', compile("

{{link-to 'About' 'about' (query-params lol='wat') id='link-to-about'}}

")); - App.register('template:about', compile("

{{link-to 'Home' 'home' (query-params foo='naw')}}

")); - App.register('template:cats.index', compile("

{{link-to 'Cats' 'cats' (query-params name='domino') id='cats-link'}}

")); - - let homeShouldBeCreated = false; - let aboutShouldBeCreated = false; - let catsIndexShouldBeCreated = false; - - App.HomeRoute = Route.extend({ - setup() { - homeShouldBeCreated = true; - this._super(...arguments); - } - }); - - App.HomeController = Controller.extend({ - queryParams: ['foo'], - foo: '123', - init() { - this._super(...arguments); - ok(homeShouldBeCreated, 'HomeController should be created at this time'); - } - }); - - App.AboutRoute = Route.extend({ - setup() { - aboutShouldBeCreated = true; - this._super(...arguments); - } - }); - - App.AboutController = Controller.extend({ - queryParams: ['lol'], - lol: 'haha', - init() { - this._super(...arguments); - ok(aboutShouldBeCreated, 'AboutController should be created at this time'); - } - }); - - App.CatsIndexRoute = Route.extend({ - model() { - return []; - }, - setup() { - catsIndexShouldBeCreated = true; - this._super(...arguments); - }, - setupController(controller, context) { - controller.set('model', context); - } - }); - - App.CatsIndexController = Controller.extend({ - queryParams: ['breed', 'name'], - breed: 'Golden', - name: null, - init() { - this._super(...arguments); - ok(catsIndexShouldBeCreated, 'CatsIndexController should be created at this time'); - } - }); - - bootApplication(); - - equal(router.get('location.path'), '', 'url is correct'); - let controller = container.lookup('controller:home'); - setAndFlush(controller, 'foo', '456'); - equal(router.get('location.path'), '/?foo=456', 'url is correct'); - equal(jQuery('#link-to-about').attr('href'), '/about?lol=wat', 'link to about is correct'); - - run(router, 'transitionTo', 'about'); - equal(router.get('location.path'), '/about', 'url is correct'); - - run(router, 'transitionTo', 'cats'); - - equal(router.get('location.path'), '/cats', 'url is correct'); - equal(jQuery('#cats-link').attr('href'), '/cats?name=domino', 'link to cats is correct'); - run(jQuery('#cats-link'), 'click'); - equal(router.get('location.path'), '/cats?name=domino', 'url is correct'); -}); + this.transitionTo('cats'); + this.assertCurrentPath('/cats'); + assert.equal(jQuery('#cats-link').attr('href'), '/cats?name=domino', 'link to cats is correct'); -QUnit.test('query params have been set by the time setupController is called', function() { - expect(1); + run(jQuery('#cats-link'), 'click'); + this.assertCurrentPath('/cats?name=domino'); + }); + } - App.ApplicationController = Controller.extend({ - queryParams: ['foo'], - foo: 'wat' - }); + ['@test query params have been set by the time setupController is called'](assert) { + assert.expect(2); - App.ApplicationRoute = Route.extend({ - setupController(controller) { - equal(controller.get('foo'), 'YEAH', 'controller\'s foo QP property set before setupController called'); - } - }); + this.setSingleQPController('application'); - startingURL = '/?foo=YEAH'; - bootApplication(); -}); + this.registerRoute('application', Route.extend({ + setupController(controller) { + assert.equal(controller.get('foo'), 'YEAH', 'controller\'s foo QP property set before setupController called'); + } + })); -QUnit.test('model hooks receives query params (overridden by incoming url value)', function() { - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); + return this.visitAndAssert('/?foo=YEAH'); + } - App.IndexRoute = Route.extend({ - model(params) { - deepEqual(params, { omg: 'yes' }); - } - }); + ['@test mapped query params have been set by the time setupController is called'](assert) { + assert.expect(2); - startingURL = '/?omg=yes'; - bootApplication(); + this.setSingleQPController('application', { faz: 'foo' }); - equal(router.get('location.path'), '/?omg=yes'); -}); + this.registerRoute('application', Route.extend({ + setupController(controller) { + assert.equal(controller.get('faz'), 'YEAH', 'controller\'s foo QP property set before setupController called'); + } + })); + + return this.visitAndAssert('/?foo=YEAH'); + } -QUnit.test('Route#paramsFor fetches query params', function() { - expect(1); + ['@test Route#paramsFor fetches query params with default value'](assert) { + assert.expect(2); - App.Router.map(function() { - this.route('index', { path: '/:something' }); - }); + this.router.map(function() { + this.route('index', { path: '/:something' }); + }); - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: 'fooapp' - }); + this.setSingleQPController('index'); - App.IndexRoute = Route.extend({ - model(params, transition) { - deepEqual(this.paramsFor('index'), { something: 'omg', foo: 'fooapp' }, 'could retrieve params for index'); - } - }); + this.registerRoute('index', Route.extend({ + model(params, transition) { + assert.deepEqual(this.paramsFor('index'), { something: 'baz', foo: 'bar' }, 'could retrieve params for index'); + } + })); - startingURL = '/omg'; - bootApplication(); -}); + return this.visitAndAssert('/baz'); + } -QUnit.test('model hook can query prefix-less application params (overridden by incoming url value)', function() { - App.ApplicationController = Controller.extend({ - queryParams: ['appomg'], - appomg: 'applol' - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); - - App.ApplicationRoute = Route.extend({ - model(params) { - deepEqual(params, { appomg: 'appyes' }); - } - }); - - App.IndexRoute = Route.extend({ - model(params) { - deepEqual(params, { omg: 'yes' }); - deepEqual(this.paramsFor('application'), { appomg: 'appyes' }); - } - }); - - startingURL = '/?appomg=appyes&omg=yes'; - bootApplication(); - - equal(router.get('location.path'), '/?appomg=appyes&omg=yes'); -}); + ['@test Route#paramsFor fetches query params with non-default value'](assert) { + assert.expect(2); + + this.router.map(function() { + this.route('index', { path: '/:something' }); + }); + this.setSingleQPController('index'); -QUnit.test('Route#paramsFor fetches falsy query params', function() { - expect(1); + this.registerRoute('index', Route.extend({ + model(params, transition) { + assert.deepEqual(this.paramsFor('index'), { something: 'baz', foo: 'boo' }, 'could retrieve params for index'); + } + })); - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: true - }); + return this.visitAndAssert('/baz?foo=boo'); + } - App.IndexRoute = Route.extend({ - model(params, transition) { - equal(params.foo, false); - } - }); + ['@test Route#paramsFor fetches default falsy query params'](assert) { + assert.expect(2); - startingURL = '/?foo=false'; - bootApplication(); -}); + this.router.map(function() { + this.route('index', { path: '/:something' }); + }); -QUnit.test('model hook can query prefix-less application params', function() { - App.ApplicationController = Controller.extend({ - queryParams: ['appomg'], - appomg: 'applol' - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); - - App.ApplicationRoute = Route.extend({ - model(params) { - deepEqual(params, { appomg: 'applol' }); - } - }); - - App.IndexRoute = Route.extend({ - model(params) { - deepEqual(params, { omg: 'lol' }); - deepEqual(this.paramsFor('application'), { appomg: 'applol' }); - } - }); - - bootApplication(); - - equal(router.get('location.path'), ''); -}); + this.setSingleQPController('index', 'foo', false); -QUnit.test('can opt into full transition by setting refreshModel in route queryParams', function() { - expect(6); - App.ApplicationController = Controller.extend({ - queryParams: ['appomg'], - appomg: 'applol' - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); - - let appModelCount = 0; - App.ApplicationRoute = Route.extend({ - model(params) { - appModelCount++; - } - }); - - let indexModelCount = 0; - App.IndexRoute = Route.extend({ - queryParams: { - omg: { - refreshModel: true - } - }, - model(params) { - indexModelCount++; - - if (indexModelCount === 1) { - deepEqual(params, { omg: 'lol' }); - } else if (indexModelCount === 2) { - deepEqual(params, { omg: 'lex' }); + this.registerRoute('index', Route.extend({ + model(params, transition) { + assert.deepEqual(this.paramsFor('index'), { something: 'baz', foo: false }, 'could retrieve params for index'); } - } - }); + })); - bootApplication(); + return this.visitAndAssert('/baz'); + } - equal(appModelCount, 1); - equal(indexModelCount, 1); + ['@test Route#paramsFor fetches non-default falsy query params'](assert) { + assert.expect(2); - let indexController = container.lookup('controller:index'); - setAndFlush(indexController, 'omg', 'lex'); + this.router.map(function() { + this.route('index', { path: '/:something' }); + }); - equal(appModelCount, 1); - equal(indexModelCount, 2); -}); + this.setSingleQPController('index', 'foo', true); -QUnit.test('refreshModel does not cause a second transition during app boot ', function() { - expect(0); - App.ApplicationController = Controller.extend({ - queryParams: ['appomg'], - appomg: 'applol' - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); - - App.IndexRoute = Route.extend({ - queryParams: { - omg: { - refreshModel: true + this.registerRoute('index', Route.extend({ + model(params, transition) { + assert.deepEqual(this.paramsFor('index'), { something: 'baz', foo: false }, 'could retrieve params for index'); } - }, - refresh() { - ok(false); - } - }); - - startingURL = '/?appomg=hello&omg=world'; - bootApplication(); -}); + })); -QUnit.test('queryParams are updated when a controller property is set and the route is refreshed. Issue #13263 ', function() { - setTemplates({ - application: compile( - '' + - '{{foo}}' + - '{{outlet}}' - ) - }); - App.ApplicationController = Controller.extend({ - queryParams: ['foo'], - foo: 1, - actions: { - increment: function() { - this.incrementProperty('foo'); - this.send('refreshRoute'); + return this.visitAndAssert('/baz?foo=false'); + } + + ['@test model hook can query prefix-less application params'](assert) { + assert.expect(4); + + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + + this.registerRoute('application', Route.extend({ + model(params) { + assert.deepEqual(params, { appomg: 'applol' }); } - } - }); + })); - App.ApplicationRoute = Route.extend({ - actions: { - refreshRoute: function() { - this.refresh(); + this.registerRoute('index', Route.extend({ + model(params) { + assert.deepEqual(params, { omg: 'lol' }); + assert.deepEqual(this.paramsFor('application'), { appomg: 'applol' }); } - } - }); - - startingURL = '/'; - bootApplication(); - equal(jQuery('#test-value').text().trim(), '1'); - equal(router.get('location.path'), '/', 'url is correct'); - run(jQuery('#test-button'), 'click'); - equal(jQuery('#test-value').text().trim(), '2'); - equal(router.get('location.path'), '/?foo=2', 'url is correct'); - run(jQuery('#test-button'), 'click'); - equal(jQuery('#test-value').text().trim(), '3'); - equal(router.get('location.path'), '/?foo=3', 'url is correct'); -}); + })); + + return this.visitAndAssert('/'); + } + + ['@test model hook can query prefix-less application params (overridden by incoming url value)'](assert) { + assert.expect(4); + + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); -QUnit.test('Use Ember.get to retrieve query params \'refreshModel\' configuration', function() { - expect(6); - App.ApplicationController = Controller.extend({ - queryParams: ['appomg'], - appomg: 'applol' - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); - - let appModelCount = 0; - App.ApplicationRoute = Route.extend({ - model(params) { - appModelCount++; - } - }); - - let indexModelCount = 0; - App.IndexRoute = Route.extend({ - queryParams: EmberObject.create({ - unknownProperty(keyName) { - return { refreshModel: true }; + this.registerRoute('application', Route.extend({ + model(params) { + assert.deepEqual(params, { appomg: 'appyes' }); } - }), - model(params) { - indexModelCount++; - - if (indexModelCount === 1) { - deepEqual(params, { omg: 'lol' }); - } else if (indexModelCount === 2) { - deepEqual(params, { omg: 'lex' }); + })); + + this.registerRoute('index', Route.extend({ + model(params) { + assert.deepEqual(params, { omg: 'yes' }); + assert.deepEqual(this.paramsFor('application'), { appomg: 'appyes' }); } - } - }); + })); - bootApplication(); + return this.visitAndAssert('/?appomg=appyes&omg=yes'); + } - equal(appModelCount, 1); - equal(indexModelCount, 1); + ['@test can opt into full transition by setting refreshModel in route queryParams'](assert) { + assert.expect(7); - let indexController = container.lookup('controller:index'); - setAndFlush(indexController, 'omg', 'lex'); + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); - equal(appModelCount, 1); - equal(indexModelCount, 2); -}); + let appModelCount = 0; + this.registerRoute('application', Route.extend({ + model(params) { + appModelCount++; + } + })); + + let indexModelCount = 0; + this.registerRoute('index', Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + model(params) { + indexModelCount++; + + if (indexModelCount === 1) { + assert.deepEqual(params, { omg: 'lol' }, 'params are correct on first pass'); + } else if (indexModelCount === 2) { + assert.deepEqual(params, { omg: 'lex' }, 'params are correct on second pass'); + } + } + })); -QUnit.test('can use refreshModel even w URL changes that remove QPs from address bar', function() { - expect(4); + return this.visitAndAssert('/').then(() => { + assert.equal(appModelCount, 1, 'app model hook ran'); + assert.equal(indexModelCount, 1, 'index model hook ran'); - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); + let indexController = this.getController('index'); + this.setAndFlush(indexController, 'omg', 'lex'); - let indexModelCount = 0; - App.IndexRoute = Route.extend({ - queryParams: { - omg: { - refreshModel: true - } - }, - model(params) { - indexModelCount++; - - let data; - if (indexModelCount === 1) { - data = 'foo'; - } else if (indexModelCount === 2) { - data = 'lol'; + assert.equal(appModelCount, 1, 'app model hook did not run again'); + assert.equal(indexModelCount, 2, 'index model hook ran again due to refreshModel'); + }); + } + + ['@test refreshModel does not cause a second transition during app boot '](assert) { + assert.expect(1); + + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + + this.registerRoute('index', Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + refresh() { + assert.ok(false); } + })); - deepEqual(params, { omg: data }, 'index#model receives right data'); - } - }); + return this.visitAndAssert('/?appomg=hello&omg=world'); + } - startingURL = '/?omg=foo'; - bootApplication(); - handleURL('/'); + ['@test queryParams are updated when a controller property is set and the route is refreshed. Issue #13263 '](assert) { + this.registerTemplate('application', '{{foo}}{{outlet}}'); - let indexController = container.lookup('controller:index'); - equal(indexController.get('omg'), 'lol'); -}); + this.setSingleQPController('application', 'foo', 1, { + actions: { + increment() { + this.incrementProperty('foo'); + this.send('refreshRoute'); + } + } + }); -QUnit.test('can opt into a replace query by specifying replace:true in the Router config hash', function() { - expect(2); - App.ApplicationController = Controller.extend({ - queryParams: ['alex'], - alex: 'matchneer' - }); - - App.ApplicationRoute = Route.extend({ - queryParams: { - alex: { - replace: true + this.registerRoute('application', Route.extend({ + actions: { + refreshRoute() { + this.refresh(); + } } - } - }); + })); - bootApplication(); + return this.visitAndAssert('/').then(() => { + assert.equal(jQuery('#test-value').text().trim(), '1'); - equal(router.get('location.path'), ''); + run(jQuery('#test-button'), 'click'); + assert.equal(jQuery('#test-value').text().trim(), '2'); + this.assertCurrentPath('/?foo=2'); - let appController = container.lookup('controller:application'); - expectedReplaceURL = '/?alex=wallace'; - setAndFlush(appController, 'alex', 'wallace'); -}); + run(jQuery('#test-button'), 'click'); + assert.equal(jQuery('#test-value').text().trim(), '3'); + this.assertCurrentPath('/?foo=3'); + }); + } + + ['@test Use Ember.get to retrieve query params \'refreshModel\' configuration'](assert) { + assert.expect(7); + + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); -QUnit.test('Route query params config can be configured using property name instead of URL key', function() { - expect(2); - App.ApplicationController = Controller.extend({ - queryParams: [ - { commitBy: 'commit_by' } - ] - }); - - App.ApplicationRoute = Route.extend({ - queryParams: { - commitBy: { - replace: true + let appModelCount = 0; + this.registerRoute('application', Route.extend({ + model(params) { + appModelCount++; } - } - }); + })); + + let indexModelCount = 0; + this.registerRoute('index', Route.extend({ + queryParams: EmberObject.create({ + unknownProperty(keyName) { + return { refreshModel: true }; + } + }), + model(params) { + indexModelCount++; + + if (indexModelCount === 1) { + assert.deepEqual(params, { omg: 'lol' }); + } else if (indexModelCount === 2) { + assert.deepEqual(params, { omg: 'lex' }); + } + } + })); - bootApplication(); + return this.visitAndAssert('/').then(() => { + assert.equal(appModelCount, 1); + assert.equal(indexModelCount, 1); - equal(router.get('location.path'), ''); + let indexController = this.getController('index'); + this.setAndFlush(indexController, 'omg', 'lex'); - let appController = container.lookup('controller:application'); - expectedReplaceURL = '/?commit_by=igor_seb'; - setAndFlush(appController, 'commitBy', 'igor_seb'); -}); + assert.equal(appModelCount, 1); + assert.equal(indexModelCount, 2); + }); + } + ['@test can use refreshModel even with URL changes that remove QPs from address bar'](assert) { + assert.expect(4); -QUnit.test('An explicit replace:false on a changed QP always wins and causes a pushState', function() { - expect(3); - App.ApplicationController = Controller.extend({ - queryParams: ['alex', 'steely'], - alex: 'matchneer', - steely: 'dan' - }); + this.setSingleQPController('index', 'omg', 'lol'); - App.ApplicationRoute = Route.extend({ - queryParams: { - alex: { - replace: true + let indexModelCount = 0; + this.registerRoute('index', Route.extend({ + queryParams: { + omg: { + refreshModel: true + } }, - steely: { - replace: false + model(params) { + indexModelCount++; + + let data; + if (indexModelCount === 1) { + data = 'foo'; + } else if (indexModelCount === 2) { + data = 'lol'; + } + + assert.deepEqual(params, { omg: data }, 'index#model receives right data'); } - } - }); + })); - bootApplication(); + return this.visitAndAssert('/?omg=foo').then(() => { + this.transitionTo('/'); - let appController = container.lookup('controller:application'); - expectedPushURL = '/?alex=wallace&steely=jan'; - run(appController, 'setProperties', { alex: 'wallace', steely: 'jan' }); + let indexController = this.getController('index'); + assert.equal(indexController.get('omg'), 'lol'); + }); + } - expectedPushURL = '/?alex=wallace&steely=fran'; - run(appController, 'setProperties', { steely: 'fran' }); + ['@test can opt into a replace query by specifying replace:true in the Route config hash'](assert) { + assert.expect(2); - expectedReplaceURL = '/?alex=sriracha&steely=fran'; - run(appController, 'setProperties', { alex: 'sriracha' }); -}); + this.setSingleQPController('application', 'alex', 'matchneer'); -QUnit.test('can opt into full transition by setting refreshModel in route queryParams when transitioning from child to parent', function() { - App.register('template:parent', compile('{{outlet}}')); - App.register('template:parent.child', compile('{{link-to \'Parent\' \'parent\' (query-params foo=\'change\') id=\'parent-link\'}}')); + this.registerRoute('application', Route.extend({ + queryParams: { + alex: { + replace: true + } + } + })); - App.Router.map(function() { - this.route('parent', function() { - this.route('child'); + return this.visitAndAssert('/').then(() => { + let appController = this.getController('application'); + this.expectedReplaceURL = '/?alex=wallace'; + this.setAndFlush(appController, 'alex', 'wallace'); }); - }); + } + + ['@test Route query params config can be configured using property name instead of URL key'](assert) { + assert.expect(2); + + this.registerController('application', Controller.extend({ + queryParams: [{ commitBy: 'commit_by' }] + })); - let parentModelCount = 0; - App.ParentRoute = Route.extend({ - model() { - parentModelCount++; - }, - queryParams: { - foo: { - refreshModel: true + this.registerRoute('application', Route.extend({ + queryParams: { + commitBy: { + replace: true + } } - } - }); + })); - App.ParentController = Controller.extend({ - queryParams: ['foo'], - foo: 'abc' - }); + return this.visitAndAssert('/').then(() => { + let appController = this.getController('application'); + this.expectedReplaceURL = '/?commit_by=igor_seb'; + this.setAndFlush(appController, 'commitBy', 'igor_seb'); + }); + } + + ['@test An explicit replace:false on a changed QP always wins and causes a pushState'](assert) { + assert.expect(3); + + this.registerController('application', Controller.extend({ + queryParams: ['alex', 'steely'], + alex: 'matchneer', + steely: 'dan' + })); + + this.registerRoute('application', Route.extend({ + queryParams: { + alex: { + replace: true + }, + steely: { + replace: false + } + } + })); - startingURL = '/parent/child?foo=lol'; - bootApplication(); + return this.visit('/').then(() => { + let appController = this.getController('application'); + this.expectedPushURL = '/?alex=wallace&steely=jan'; + run(appController, 'setProperties', { alex: 'wallace', steely: 'jan' }); - equal(parentModelCount, 1); + this.expectedPushURL = '/?alex=wallace&steely=fran'; + run(appController, 'setProperties', { steely: 'fran' }); - container.lookup('controller:parent'); + this.expectedReplaceURL = '/?alex=sriracha&steely=fran'; + run(appController, 'setProperties', { alex: 'sriracha' }); + }); + } - run(jQuery('#parent-link'), 'click'); + ['@test can opt into full transition by setting refreshModel in route queryParams when transitioning from child to parent'](assert) { + this.registerTemplate('parent', '{{outlet}}'); + this.registerTemplate('parent.child', '{{link-to \'Parent\' \'parent\' (query-params foo=\'change\') id=\'parent-link\'}}'); - equal(parentModelCount, 2); -}); + this.router.map(function() { + this.route('parent', function() { + this.route('child'); + }); + }); -QUnit.test('Use Ember.get to retrieve query params \'replace\' configuration', function() { - expect(2); - App.ApplicationController = Controller.extend({ - queryParams: ['alex'], - alex: 'matchneer' - }); - - App.ApplicationRoute = Route.extend({ - queryParams: EmberObject.create({ - unknownProperty(keyName) { - // We are simulating all qps requiring refresh - return { replace: true }; + let parentModelCount = 0; + this.registerRoute('parent', Route.extend({ + model() { + parentModelCount++; + }, + queryParams: { + foo: { + refreshModel: true + } } - }) - }); + })); - bootApplication(); + this.setSingleQPController('parent', 'foo', 'abc'); - equal(router.get('location.path'), ''); + return this.visit('/parent/child?foo=lol').then(() => { + assert.equal(parentModelCount, 1); - let appController = container.lookup('controller:application'); - expectedReplaceURL = '/?alex=wallace'; - setAndFlush(appController, 'alex', 'wallace'); -}); + run(jQuery('#parent-link'), 'click'); + assert.equal(parentModelCount, 2); + }); + } + + ['@test Use Ember.get to retrieve query params \'replace\' configuration'](assert) { + assert.expect(2); + + this.setSingleQPController('application', 'alex', 'matchneer'); + + this.registerRoute('application', Route.extend({ + queryParams: EmberObject.create({ + unknownProperty(keyName) { + // We are simulating all qps requiring refresh + return { replace: true }; + } + }) + })); + + return this.visitAndAssert('/').then(() => { + let appController = this.getController('application'); + this.expectedReplaceURL = '/?alex=wallace'; + this.setAndFlush(appController, 'alex', 'wallace'); + }); + } + + ['@test can override incoming QP values in setupController'](assert) { + assert.expect(3); + + this.router.map(function() { + this.route('about'); + }); + + this.setSingleQPController('index', 'omg', 'lol'); -QUnit.test('can override incoming QP values in setupController', function() { - expect(3); - - App.Router.map(function() { - this.route('about'); - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); - - App.IndexRoute = Route.extend({ - setupController(controller) { - ok(true, 'setupController called'); - controller.set('omg', 'OVERRIDE'); - }, - actions: { - queryParamsDidChange() { - ok(false, 'queryParamsDidChange shouldn\'t fire'); + this.registerRoute('index', Route.extend({ + setupController(controller) { + assert.ok(true, 'setupController called'); + controller.set('omg', 'OVERRIDE'); + }, + actions: { + queryParamsDidChange() { + assert.ok(false, 'queryParamsDidChange shouldn\'t fire'); + } } - } - }); - - startingURL = '/about'; - bootApplication(); - equal(router.get('location.path'), '/about'); - run(router, 'transitionTo', 'index'); - equal(router.get('location.path'), '/?omg=OVERRIDE'); -}); + })); -QUnit.test('can override incoming QP array values in setupController', function() { - expect(3); - - App.Router.map(function() { - this.route('about'); - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: ['lol'] - }); - - App.IndexRoute = Route.extend({ - setupController(controller) { - ok(true, 'setupController called'); - controller.set('omg', ['OVERRIDE']); - }, - actions: { - queryParamsDidChange() { - ok(false, 'queryParamsDidChange shouldn\'t fire'); + return this.visitAndAssert('/about').then(() => { + this.transitionTo('index'); + this.assertCurrentPath('/?omg=OVERRIDE'); + }); + } + + ['@test can override incoming QP array values in setupController'](assert) { + assert.expect(3); + + this.router.map(function() { + this.route('about'); + }); + + this.setSingleQPController('index', 'omg', ['lol']); + + this.registerRoute('index', Route.extend({ + setupController(controller) { + assert.ok(true, 'setupController called'); + controller.set('omg', ['OVERRIDE']); + }, + actions: { + queryParamsDidChange() { + assert.ok(false, 'queryParamsDidChange shouldn\'t fire'); + } } - } - }); - - startingURL = '/about'; - bootApplication(); - equal(router.get('location.path'), '/about'); - run(router, 'transitionTo', 'index'); - equal(router.get('location.path'), '/?omg=' + encodeURIComponent(JSON.stringify(['OVERRIDE']))); -}); + })); -QUnit.test('URL transitions that remove QPs still register as QP changes', function() { - expect(2); + return this.visitAndAssert('/about').then(() => { + this.transitionTo('index'); + this.assertCurrentPath('/?omg=' + encodeURIComponent(JSON.stringify(['OVERRIDE']))); + }); + } - App.IndexController = Controller.extend({ - queryParams: ['omg'], - omg: 'lol' - }); + ['@test URL transitions that remove QPs still register as QP changes'](assert) { + assert.expect(2); - startingURL = '/?omg=borf'; - bootApplication(); + this.setSingleQPController('index', 'omg', 'lol'); - let indexController = container.lookup('controller:index'); - equal(indexController.get('omg'), 'borf'); - run(router, 'transitionTo', '/'); - equal(indexController.get('omg'), 'lol'); -}); + return this.visit('/?omg=borf').then(() => { + let indexController = this.getController('index'); + assert.equal(indexController.get('omg'), 'borf'); -QUnit.test('Subresource naming style is supported', function() { - App.Router.map(function() { - this.route('abc.def', { path: '/abcdef' }, function() { - this.route('zoo'); + this.transitionTo('/'); + assert.equal(indexController.get('omg'), 'lol'); }); - }); + } - App.register('template:application', compile('{{link-to \'A\' \'abc.def\' (query-params foo=\'123\') id=\'one\'}}{{link-to \'B\' \'abc.def.zoo\' (query-params foo=\'123\' bar=\'456\') id=\'two\'}}{{outlet}}')); + ['@test Subresource naming style is supported'](assert) { + assert.expect(5); - App.AbcDefController = Controller.extend({ - queryParams: ['foo'], - foo: 'lol' - }); + this.router.map(function() { + this.route('abc.def', { path: '/abcdef' }, function() { + this.route('zoo'); + }); + }); - App.AbcDefZooController = Controller.extend({ - queryParams: ['bar'], - bar: 'haha' - }); + this.registerTemplate('application', '{{link-to \'A\' \'abc.def\' (query-params foo=\'123\') id=\'one\'}}{{link-to \'B\' \'abc.def.zoo\' (query-params foo=\'123\' bar=\'456\') id=\'two\'}}{{outlet}}'); - bootApplication(); - equal(router.get('location.path'), ''); - equal(jQuery('#one').attr('href'), '/abcdef?foo=123'); - equal(jQuery('#two').attr('href'), '/abcdef/zoo?bar=456&foo=123'); + this.setSingleQPController('abc.def', 'foo', 'lol'); + this.setSingleQPController('abc.def.zoo', 'bar', 'haha'); - run(jQuery('#one'), 'click'); - equal(router.get('location.path'), '/abcdef?foo=123'); - run(jQuery('#two'), 'click'); - equal(router.get('location.path'), '/abcdef/zoo?bar=456&foo=123'); -}); + return this.visitAndAssert('/').then(() => { + assert.equal(jQuery('#one').attr('href'), '/abcdef?foo=123'); + assert.equal(jQuery('#two').attr('href'), '/abcdef/zoo?bar=456&foo=123'); -QUnit.test('transitionTo supports query params', function() { - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: 'lol' - }); + run(jQuery('#one'), 'click'); + this.assertCurrentPath('/abcdef?foo=123'); - bootApplication(); + run(jQuery('#two'), 'click'); + this.assertCurrentPath('/abcdef/zoo?bar=456&foo=123'); + }); + } - equal(router.get('location.path'), ''); + ['@test transitionTo supports query params'](assert) { + this.setSingleQPController('index', 'foo', 'lol'); - run(router, 'transitionTo', { queryParams: { foo: 'borf' } }); - equal(router.get('location.path'), '/?foo=borf', 'shorthand supported'); - run(router, 'transitionTo', { queryParams: { 'index:foo': 'blaf' } }); - equal(router.get('location.path'), '/?foo=blaf', 'longform supported'); - run(router, 'transitionTo', { queryParams: { 'index:foo': false } }); - equal(router.get('location.path'), '/?foo=false', 'longform supported (bool)'); - run(router, 'transitionTo', { queryParams: { foo: false } }); - equal(router.get('location.path'), '/?foo=false', 'shorhand supported (bool)'); -}); + return this.visitAndAssert('/').then(() => { + this.transitionTo({ queryParams: { foo: 'borf' } }); + this.assertCurrentPath('/?foo=borf', 'shorthand supported'); -QUnit.test('transitionTo supports query params (multiple)', function() { - App.IndexController = Controller.extend({ - queryParams: ['foo', 'bar'], - foo: 'lol', - bar: 'wat' - }); - - bootApplication(); - - equal(router.get('location.path'), ''); - - run(router, 'transitionTo', { queryParams: { foo: 'borf' } }); - equal(router.get('location.path'), '/?foo=borf', 'shorthand supported'); - run(router, 'transitionTo', { queryParams: { 'index:foo': 'blaf' } }); - equal(router.get('location.path'), '/?foo=blaf', 'longform supported'); - run(router, 'transitionTo', { queryParams: { 'index:foo': false } }); - equal(router.get('location.path'), '/?foo=false', 'longform supported (bool)'); - run(router, 'transitionTo', { queryParams: { foo: false } }); - equal(router.get('location.path'), '/?foo=false', 'shorhand supported (bool)'); -}); + this.transitionTo({ queryParams: { 'index:foo': 'blaf' } }); + this.assertCurrentPath('/?foo=blaf', 'longform supported'); -QUnit.test('setting controller QP to empty string doesn\'t generate null in URL', function() { - expect(1); - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: '123' - }); + this.transitionTo({ queryParams: { 'index:foo': false } }); + this.assertCurrentPath('/?foo=false', 'longform supported (bool)'); - bootApplication(); - let controller = container.lookup('controller:index'); + this.transitionTo({ queryParams: { foo: false } }); + this.assertCurrentPath('/?foo=false', 'shorhand supported (bool)'); + }); + } - expectedPushURL = '/?foo='; - setAndFlush(controller, 'foo', ''); -}); + ['@test transitionTo supports query params (multiple)'](assert) { + this.registerController('index', Controller.extend({ + queryParams: ['foo', 'bar'], + foo: 'lol', + bar: 'wat' + })); -QUnit.test('setting QP to empty string doesn\'t generate null in URL', function() { - expect(1); - App.IndexRoute = Route.extend({ - queryParams: { - foo: { - defaultValue: '123' - } - } - }); + return this.visitAndAssert('/').then(() => { + this.transitionTo({ queryParams: { foo: 'borf' } }); + this.assertCurrentPath('/?foo=borf', 'shorthand supported'); - bootApplication(); - let controller = container.lookup('controller:index'); + this.transitionTo({ queryParams: { 'index:foo': 'blaf' } }); + this.assertCurrentPath('/?foo=blaf', 'longform supported'); - expectedPushURL = '/?foo='; - setAndFlush(controller, 'foo', ''); -}); + this.transitionTo({ queryParams: { 'index:foo': false } }); + this.assertCurrentPath('/?foo=false', 'longform supported (bool)'); -QUnit.test('A default boolean value deserializes QPs as booleans rather than strings', function() { - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: false - }); + this.transitionTo({ queryParams: { foo: false } }); + this.assertCurrentPath('/?foo=false', 'shorhand supported (bool)'); + }); + } - App.IndexRoute = Route.extend({ - model(params) { - equal(params.foo, true, 'model hook received foo as boolean true'); - } - }); + ['@test setting controller QP to empty string doesn\'t generate null in URL'](assert) { + assert.expect(1); - startingURL = '/?foo=true'; - bootApplication(); + this.setSingleQPController('index', 'foo', '123'); - let controller = container.lookup('controller:index'); - equal(controller.get('foo'), true); + return this.visit('/').then(() => { + let controller = this.getController('index'); - handleURL('/?foo=false'); - equal(controller.get('foo'), false); -}); + this.expectedPushURL = '/?foo='; + this.setAndFlush(controller, 'foo', ''); + }); + } -QUnit.test('Query param without value are empty string', function() { - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: '' - }); + ['@test setting QP to empty string doesn\'t generate null in URL'](assert) { + assert.expect(1); - startingURL = '/?foo='; - bootApplication(); + this.registerRoute('index', Route.extend({ + queryParams: { + foo: { + defaultValue: '123' + } + } + })); - let controller = container.lookup('controller:index'); - equal(controller.get('foo'), ''); -}); + return this.visit('/').then(() => { + let controller = this.getController('index'); -QUnit.test('Array query params can be set', function() { - App.Router.map(function() { - this.route('home', { path: '/' }); - }); + this.expectedPushURL = '/?foo='; + this.setAndFlush(controller, 'foo', ''); + }); + } - App.HomeController = Controller.extend({ - queryParams: ['foo'], - foo: [] - }); + ['@test A default boolean value deserializes QPs as booleans rather than strings'](assert) { + assert.expect(3); - bootApplication(); + this.setSingleQPController('index', 'foo', false); - let controller = container.lookup('controller:home'); + this.registerRoute('index', Route.extend({ + model(params) { + assert.equal(params.foo, true, 'model hook received foo as boolean true'); + } + })); - setAndFlush(controller, 'foo', [1, 2]); + return this.visit('/?foo=true').then(() => { + let controller = this.getController('index'); + assert.equal(controller.get('foo'), true); - equal(router.get('location.path'), '/?foo=%5B1%2C2%5D'); + this.transitionTo('/?foo=false'); + assert.equal(controller.get('foo'), false); + }); + } - setAndFlush(controller, 'foo', [3, 4]); - equal(router.get('location.path'), '/?foo=%5B3%2C4%5D'); -}); + ['@test Query param without value are empty string'](assert) { + assert.expect(1); -QUnit.test('(de)serialization: arrays', function() { - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: [1] - }); + this.registerController('index', Controller.extend({ + queryParams: ['foo'], + foo: '' + })); - bootApplication(); + return this.visit('/?foo=').then(() => { + let controller = this.getController('index'); + assert.equal(controller.get('foo'), ''); + }); + } - equal(router.get('location.path'), ''); + ['@test Array query params can be set'](assert) { + assert.expect(2); - run(router, 'transitionTo', { queryParams: { foo: [2, 3] } }); - equal(router.get('location.path'), '/?foo=%5B2%2C3%5D', 'shorthand supported'); - run(router, 'transitionTo', { queryParams: { 'index:foo': [4, 5] } }); - equal(router.get('location.path'), '/?foo=%5B4%2C5%5D', 'longform supported'); - run(router, 'transitionTo', { queryParams: { foo: [] } }); - equal(router.get('location.path'), '/?foo=%5B%5D', 'longform supported'); -}); + this.router.map(function() { + this.route('home', { path: '/' }); + }); -QUnit.test('Url with array query param sets controller property to array', function() { - App.IndexController = Controller.extend({ - queryParams: ['foo'], - foo: '' - }); + this.setSingleQPController('home', 'foo', []); - startingURL = '/?foo[]=1&foo[]=2&foo[]=3'; - bootApplication(); + return this.visit('/').then(() => { + let controller = this.getController('home'); - let controller = container.lookup('controller:index'); - deepEqual(controller.get('foo'), ['1', '2', '3']); -}); + this.setAndFlush(controller, 'foo', [1, 2]); + this.assertCurrentPath('/?foo=%5B1%2C2%5D'); -QUnit.test('Array query params can be pushed/popped', function() { - App.Router.map(function() { - this.route('home', { path: '/' }); - }); - - App.HomeController = Controller.extend({ - queryParams: ['foo'], - foo: emberA() - }); - - bootApplication(); - - equal(router.get('location.path'), ''); - - let controller = container.lookup('controller:home'); - - run(controller.foo, 'pushObject', 1); - equal(router.get('location.path'), '/?foo=%5B1%5D'); - deepEqual(controller.foo, [1]); - run(controller.foo, 'popObject'); - equal(router.get('location.path'), '/'); - deepEqual(controller.foo, []); - run(controller.foo, 'pushObject', 1); - equal(router.get('location.path'), '/?foo=%5B1%5D'); - deepEqual(controller.foo, [1]); - run(controller.foo, 'popObject'); - equal(router.get('location.path'), '/'); - deepEqual(controller.foo, []); - run(controller.foo, 'pushObject', 1); - equal(router.get('location.path'), '/?foo=%5B1%5D'); - deepEqual(controller.foo, [1]); - run(controller.foo, 'pushObject', 2); - equal(router.get('location.path'), '/?foo=%5B1%2C2%5D'); - deepEqual(controller.foo, [1, 2]); - run(controller.foo, 'popObject'); - equal(router.get('location.path'), '/?foo=%5B1%5D'); - deepEqual(controller.foo, [1]); - run(controller.foo, 'unshiftObject', 'lol'); - equal(router.get('location.path'), '/?foo=%5B%22lol%22%2C1%5D'); - deepEqual(controller.foo, ['lol', 1]); -}); + this.setAndFlush(controller, 'foo', [3, 4]); + this.assertCurrentPath('/?foo=%5B3%2C4%5D'); + }); + } -QUnit.test('Overwriting with array with same content shouldn\'t refire update', function() { - expect(3); - let modelCount = 0; + ['@test (de)serialization: arrays'](assert) { + assert.expect(4); - App.Router.map(function() { - this.route('home', { path: '/' }); - }); + this.setSingleQPController('index', 'foo', [1]); - App.HomeRoute = Route.extend({ - model() { - modelCount++; - } - }); + return this.visitAndAssert('/').then(() => { + this.transitionTo({ queryParams: { foo: [2, 3] } }); + this.assertCurrentPath('/?foo=%5B2%2C3%5D', 'shorthand supported'); + this.transitionTo({ queryParams: { 'index:foo': [4, 5] } }); + this.assertCurrentPath('/?foo=%5B4%2C5%5D', 'longform supported'); + this.transitionTo({ queryParams: { foo: [] } }); + this.assertCurrentPath('/?foo=%5B%5D', 'longform supported'); + }); + } - App.HomeController = Controller.extend({ - queryParams: ['foo'], - foo: emberA([1]) - }); + ['@test Url with array query param sets controller property to array'](assert) { + assert.expect(1); - bootApplication(); + this.setSingleQPController('index', 'foo', ''); - equal(modelCount, 1); - let controller = container.lookup('controller:home'); - setAndFlush(controller, 'model', emberA([1])); - equal(modelCount, 1); - equal(router.get('location.path'), ''); -}); + return this.visit('/?foo[]=1&foo[]=2&foo[]=3').then(() => { + let controller = this.getController('index'); + assert.deepEqual(controller.get('foo'), ['1', '2', '3']); + }); + } -QUnit.test('Defaulting to params hash as the model should not result in that params object being watched', function() { - expect(1); + ['@test Array query params can be pushed/popped'](assert) { + assert.expect(17); - App.Router.map(function() { - this.route('other'); - }); + this.router.map(function() { + this.route('home', { path: '/' }); + }); - // This causes the params hash, which is returned as a route's - // model if no other model could be resolved given the provided - // params (and no custom model hook was defined), to be watched, - // unless we return a copy of the params hash. - App.ApplicationController = Controller.extend({ - queryParams: ['woot'], - woot: 'wat' - }); + this.setSingleQPController('home', 'foo', emberA()); - App.OtherRoute = Route.extend({ - model(p, trans) { - let m = meta(trans.params.application); - ok(!m.peekWatching('woot'), 'A meta object isn\'t constructed for this params POJO'); - } - }); + return this.visitAndAssert('/').then(() => { + let controller = this.getController('home'); - bootApplication(); + run(controller.foo, 'pushObject', 1); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); - run(router, 'transitionTo', 'other'); -}); + run(controller.foo, 'popObject'); + this.assertCurrentPath('/'); + assert.deepEqual(controller.foo, []); -QUnit.test('A child of a resource route still defaults to parent route\'s model even if the child route has a query param', function() { - expect(1); + run(controller.foo, 'pushObject', 1); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); - App.IndexController = Controller.extend({ - queryParams: ['woot'] - }); + run(controller.foo, 'popObject'); + this.assertCurrentPath('/'); + assert.deepEqual(controller.foo, []); - App.ApplicationRoute = Route.extend({ - model(p, trans) { - return { woot: true }; - } - }); + run(controller.foo, 'pushObject', 1); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); - App.IndexRoute = Route.extend({ - setupController(controller, model) { - deepEqual(model, { woot: true }, 'index route inherited model route from parent route'); - } - }); + run(controller.foo, 'pushObject', 2); + this.assertCurrentPath('/?foo=%5B1%2C2%5D'); + assert.deepEqual(controller.foo, [1, 2]); - bootApplication(); -}); + run(controller.foo, 'popObject'); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); + + run(controller.foo, 'unshiftObject', 'lol'); + this.assertCurrentPath('/?foo=%5B%22lol%22%2C1%5D'); + assert.deepEqual(controller.foo, ['lol', 1]); + }); + } + + ['@test Overwriting with array with same content shouldn\'t refire update'](assert) { + assert.expect(4); + + this.router.map(function() { + this.route('home', { path: '/' }); + }); -QUnit.test('opting into replace does not affect transitions between routes', function() { - expect(5); - App.register('template:application', compile( - '{{link-to \'Foo\' \'foo\' id=\'foo-link\'}}' + - '{{link-to \'Bar\' \'bar\' id=\'bar-no-qp-link\'}}' + - '{{link-to \'Bar\' \'bar\' (query-params raytiley=\'isthebest\') id=\'bar-link\'}}' + - '{{outlet}}' - )); - App.Router.map(function() { - this.route('foo'); - this.route('bar'); - }); - - App.BarController = Controller.extend({ - queryParams: ['raytiley'], - raytiley: 'israd' - }); - - App.BarRoute = Route.extend({ - queryParams: { - raytiley: { - replace: true + let modelCount = 0; + this.registerRoute('home', Route.extend({ + model() { + modelCount++; } - } - }); + })); - bootApplication(); - let controller = container.lookup('controller:bar'); + this.setSingleQPController('home', 'foo', emberA([1])); - expectedPushURL = '/foo'; - run(jQuery('#foo-link'), 'click'); + return this.visitAndAssert('/').then(() => { + assert.equal(modelCount, 1); - expectedPushURL = '/bar'; - run(jQuery('#bar-no-qp-link'), 'click'); + let controller = this.getController('home'); + this.setAndFlush(controller, 'model', emberA([1])); - expectedReplaceURL = '/bar?raytiley=woot'; - setAndFlush(controller, 'raytiley', 'woot'); + assert.equal(modelCount, 1); + this.assertCurrentPath('/'); + }); + } - expectedPushURL = '/foo'; - run(jQuery('#foo-link'), 'click'); + ['@test Defaulting to params hash as the model should not result in that params object being watched'](assert) { + assert.expect(1); - expectedPushURL = '/bar?raytiley=isthebest'; - run(jQuery('#bar-link'), 'click'); -}); + this.router.map(function() { + this.route('other'); + }); -QUnit.test('Undefined isn\'t deserialized into a string', function() { - expect(3); - App.Router.map(function() { - this.route('example'); - }); + // This causes the params hash, which is returned as a route's + // model if no other model could be resolved given the provided + // params (and no custom model hook was defined), to be watched, + // unless we return a copy of the params hash. + this.setSingleQPController('application', 'woot', 'wat'); - App.register('template:application', compile('{{link-to \'Example\' \'example\' id=\'the-link\'}}')); + this.registerRoute('other', Route.extend({ + model(p, trans) { + let m = meta(trans.params.application); + assert.ok(!m.peekWatching('woot'), 'A meta object isn\'t constructed for this params POJO'); + } + })); - App.ExampleController = Controller.extend({ - queryParams: ['foo'] - // uncommon to not support default value, but should assume undefined. - }); + return this.visit('/').then(() => { + this.transitionTo('other'); + }); + } - App.ExampleRoute = Route.extend({ - model(params) { - deepEqual(params, { foo: undefined }); - } - }); + ['@test A child of a resource route still defaults to parent route\'s model even if the child route has a query param'](assert) { + assert.expect(2); - bootApplication(); + this.setSingleQPController('index', 'woot', undefined, { + woot: undefined + }); - let $link = jQuery('#the-link'); - equal($link.attr('href'), '/example'); - run($link, 'click'); + this.registerRoute('application', Route.extend({ + model(p, trans) { + return { woot: true }; + } + })); - let controller = container.lookup('controller:example'); - equal(get(controller, 'foo'), undefined); -}); + this.registerRoute('index', Route.extend({ + setupController(controller, model) { + assert.deepEqual(model, { woot: true }, 'index route inherited model route from parent route'); + } + })); + + return this.visitAndAssert('/'); + } -QUnit.test('when refreshModel is true and loading action returns false, model hook will rerun when QPs change even if previous did not finish', function() { - expect(6); + ['@test opting into replace does not affect transitions between routes'](assert) { + assert.expect(5); - var appModelCount = 0; - var promiseResolve; + this.registerTemplate('application', '{{link-to \'Foo\' \'foo\' id=\'foo-link\'}}{{link-to \'Bar\' \'bar\' id=\'bar-no-qp-link\'}}{{link-to \'Bar\' \'bar\' (query-params raytiley=\'isthebest\') id=\'bar-link\'}}{{outlet}}'); - App.ApplicationRoute = Route.extend({ - queryParams: { - 'appomg': { - defaultValue: 'applol' + this.router.map(function() { + this.route('foo'); + this.route('bar'); + }); + + this.setSingleQPController('bar', 'raytiley', 'israd'); + + this.registerRoute('bar', Route.extend({ + queryParams: { + raytiley: { + replace: true + } } - }, - model(params) { - appModelCount++; - } - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'] - // uncommon to not support default value, but should assume undefined. - }); - - var indexModelCount = 0; - App.IndexRoute = Route.extend({ - queryParams: { - omg: { - refreshModel: true + })); + + return this.visit('/').then(() => { + let controller = this.getController('bar'); + + this.expectedPushURL = '/foo'; + run(jQuery('#foo-link'), 'click'); + + this.expectedPushURL = '/bar'; + run(jQuery('#bar-no-qp-link'), 'click'); + + this.expectedReplaceURL = '/bar?raytiley=woot'; + this.setAndFlush(controller, 'raytiley', 'woot'); + + this.expectedPushURL = '/foo'; + run(jQuery('#foo-link'), 'click'); + + this.expectedPushURL = '/bar?raytiley=isthebest'; + run(jQuery('#bar-link'), 'click'); + }); + } + + ['@test Undefined isn\'t deserialized into a string'](assert) { + assert.expect(3); + + this.router.map(function() { + this.route('example'); + }); + + this.registerTemplate('application', '{{link-to \'Example\' \'example\' id=\'the-link\'}}'); + + this.setSingleQPController('example', 'foo', undefined, { + foo: undefined + }); + + this.registerRoute('example', Route.extend({ + model(params) { + assert.deepEqual(params, { foo: undefined }); } - }, - actions: { - loading: function() { - return false; + })); + + return this.visit('/').then(() => { + let $link = jQuery('#the-link'); + assert.equal($link.attr('href'), '/example'); + run($link, 'click'); + + let controller = this.getController('example'); + assert.equal(get(controller, 'foo'), undefined); + }); + } + + ['@test when refreshModel is true and loading action returns false, model hook will rerun when QPs change even if previous did not finish'](assert) { + assert.expect(9); + + let appModelCount = 0; + let promiseResolve; + + this.registerRoute('application', Route.extend({ + queryParams: { + appomg: { + defaultValue: 'applol' + } + }, + model(params) { + appModelCount++; } - }, - model(params) { - indexModelCount++; - if (indexModelCount === 2) { - deepEqual(params, { omg: 'lex' }); - return new RSVP.Promise(function(resolve) { - promiseResolve = resolve; - return; - }); - } else if (indexModelCount === 3) { - deepEqual(params, { omg: 'hello' }, 'Model hook reruns even if the previous one didnt finish'); + })); + + this.setSingleQPController('index', 'omg', undefined, { + omg: undefined + }); + + let indexModelCount = 0; + this.registerRoute('index', Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + actions: { + loading: function() { + return false; + } + }, + model(params) { + indexModelCount++; + if (indexModelCount === 2) { + assert.deepEqual(params, { omg: 'lex' }); + return new RSVP.Promise(function(resolve) { + promiseResolve = resolve; + return; + }); + } else if (indexModelCount === 3) { + assert.deepEqual(params, { omg: 'hello' }, 'Model hook reruns even if the previous one didnt finish'); + } } - } - }); + })); - bootApplication(); + return this.visit('/').then(() => { + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 1); - equal(indexModelCount, 1); + let indexController = this.getController('index'); + this.setAndFlush(indexController, 'omg', 'lex'); - var indexController = container.lookup('controller:index'); - setAndFlush(indexController, 'omg', 'lex'); - equal(indexModelCount, 2); + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 2); - setAndFlush(indexController, 'omg', 'hello'); - equal(indexModelCount, 3); - run(function() { - promiseResolve(); - }); - equal(get(indexController, 'omg'), 'hello', 'At the end last value prevails'); -}); + this.setAndFlush(indexController, 'omg', 'hello'); + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 3); -QUnit.test('when refreshModel is true and loading action does not return false, model hook will not rerun when QPs change even if previous did not finish', function() { - expect(7); + run(function() { + promiseResolve(); + }); - var appModelCount = 0; - var promiseResolve; + assert.equal(get(indexController, 'omg'), 'hello', 'At the end last value prevails'); + }); + } - App.ApplicationRoute = Route.extend({ - queryParams: { - 'appomg': { - defaultValue: 'applol' - } - }, - model(params) { - appModelCount++; - } - }); - - App.IndexController = Controller.extend({ - queryParams: ['omg'] - // uncommon to not support default value, but should assume undefined. - }); - - var indexModelCount = 0; - App.IndexRoute = Route.extend({ - queryParams: { - omg: { - refreshModel: true - } - }, - model(params) { - indexModelCount++; - - if (indexModelCount === 2) { - deepEqual(params, { omg: 'lex' }); - return new RSVP.Promise(function(resolve) { - promiseResolve = resolve; - return; - }); - } else if (indexModelCount === 3) { - ok(false, 'shouldnt get here'); + ['@skip when refreshModel is true and loading action does not return false, model hook will not rerun when QPs change even if previous did not finish'](assert) { + assert.expect(9); + + let appModelCount = 0; + let promiseResolve; + + this.registerRoute('application', Route.extend({ + queryParams: { + 'appomg': { + defaultValue: 'applol' + } + }, + model(params) { + appModelCount++; } - } - }); + })); - bootApplication(); + this.setSingleQPController('index', 'omg', undefined, { + omg: undefined + }); - equal(appModelCount, 1); - equal(indexModelCount, 1); + let indexModelCount = 0; + this.registerRoute('index', Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + model(params) { + indexModelCount++; + + if (indexModelCount === 2) { + assert.deepEqual(params, { omg: 'lex' }, 'params are correct'); + return new RSVP.Promise(function(resolve) { + promiseResolve = resolve; + return; + }); + } else if (indexModelCount === 3) { + console.log('not here!'); + assert.ok(false, 'shouldnt get here'); + } + } + })); - var indexController = container.lookup('controller:index'); - setAndFlush(indexController, 'omg', 'lex'); + return this.visitAndAssert('/').then(() => { + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 1); - equal(appModelCount, 1); - equal(indexModelCount, 2); + let indexController = this.getController('index'); + this.setAndFlush(indexController, 'omg', 'lex'); - setAndFlush(indexController, 'omg', 'hello'); - equal(get(indexController, 'omg'), 'hello', ' value was set'); - equal(indexModelCount, 2); - run(function() { - promiseResolve(); - }); -}); + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 2); + this.setAndFlush(indexController, 'omg', 'hello'); + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 2); -QUnit.test('warn user that routes query params configuration must be an Object, not an Array', function() { - expect(1); + run(function() { + promiseResolve(); + }); - App.ApplicationRoute = Route.extend({ - queryParams: [ - { commitBy: { replace: true } } - ] - }); + assert.equal(get(indexController, 'omg'), 'hello', 'At the end last value prevails'); + }); + } - expectAssertion(function() { - bootApplication(); - }, 'You passed in `[{"commitBy":{"replace":true}}]` as the value for `queryParams` but `queryParams` cannot be an Array'); -}); + ['@test warn user that Route\'s queryParams configuration must be an Object, not an Array'](assert) { + assert.expect(1); -QUnit.test('handle routes names that clash with Object.prototype properties', function() { - expect(1); + this.registerRoute('application', Route.extend({ + queryParams: [ + { commitBy: { replace: true } } + ] + })); - App.Router.map(function() { - this.route('constructor'); - }); + expectAssertion(() => { + this.visit('/'); + }, 'You passed in `[{"commitBy":{"replace":true}}]` as the value for `queryParams` but `queryParams` cannot be an Array'); + } - App.ConstructorRoute = Route.extend({ - queryParams: { - foo: { - defaultValue: '123' - } - } - }); + ['@test handle route names that clash with Object.prototype properties'](assert) { + assert.expect(1); - bootApplication(); + this.router.map(function() { + this.route('constructor'); + }); - run(router, 'transitionTo', 'constructor', { queryParams: { foo: '999' } }); + this.registerRoute('constructor', Route.extend({ + queryParams: { + foo: { + defaultValue: '123' + } + } + })); - let controller = container.lookup('controller:constructor'); - equal(get(controller, 'foo'), '999'); + return this.visit('/').then(() => { + this.transitionTo('constructor', { queryParams: { foo: '999' } }); + let controller = this.getController('constructor'); + assert.equal(get(controller, 'foo'), '999'); + }); + } }); diff --git a/packages/ember/tests/routing/query_params_test/model_dependent_state_with_query_params_test.js b/packages/ember/tests/routing/query_params_test/model_dependent_state_with_query_params_test.js index 7cc96f9646d..5dad948ba12 100644 --- a/packages/ember/tests/routing/query_params_test/model_dependent_state_with_query_params_test.js +++ b/packages/ember/tests/routing/query_params_test/model_dependent_state_with_query_params_test.js @@ -1,291 +1,230 @@ import { Controller, - A as emberA, - String as StringUtils + A as emberA } from 'ember-runtime'; -import { Route, NoneLocation } from 'ember-routing'; +import { Route } from 'ember-routing'; import { run, computed } from 'ember-metal'; -import { compile } from 'ember-template-compiler'; -import { Application } from 'ember-application'; import { jQuery } from 'ember-views'; -import { setTemplates } from 'ember-glimmer'; +import { QueryParamTestCase, moduleFor } from 'internal-test-helpers'; -let App, router, registry, container; - -function bootApplication() { - router = container.lookup('router:main'); - run(App, 'advanceReadiness'); -} - -function handleURL(path) { - return run(function() { - return router.handleURL(path).then(function(value) { - ok(true, 'url: `' + path + '` was handled'); - return value; - }, function(reason) { - ok(false, 'failed to visit:`' + path + '` reason: `' + QUnit.jsDump.parse(reason)); - throw reason; - }); - }); -} +class ModelDependentQPTestCase extends QueryParamTestCase { + boot() { + this.setupApplication(); + return this.visitApplication(); + } -let startingURL = ''; -let expectedReplaceURL, expectedPushURL; + teardown() { + super(...arguments); + this.assert.ok(!this.expectedModelHookParams, 'there should be no pending expectation of expected model hook params'); + } -function setAndFlush(obj, prop, value) { - run(obj, 'set', prop, value); -} + reopenController(name, options) { + this.application.resolveRegistration(`controller:${name}`).reopen(options); + } -let TestLocation = NoneLocation.extend({ - initState() { - this.set('path', startingURL); - }, - - setURL(path) { - if (expectedReplaceURL) { - ok(false, 'pushState occurred but a replaceState was expected'); - } - if (expectedPushURL) { - equal(path, expectedPushURL, 'an expected pushState occurred'); - expectedPushURL = null; - } - this.set('path', path); - }, - - replaceURL(path) { - if (expectedPushURL) { - ok(false, 'replaceState occurred but a pushState was expected'); - } - if (expectedReplaceURL) { - equal(path, expectedReplaceURL, 'an expected replaceState occurred'); - expectedReplaceURL = null; - } - this.set('path', path); + reopenRoute(name, options) { + this.application.resolveRegistration(`route:${name}`).reopen(options); } -}); -function sharedSetup() { - run(function() { - App = Application.create({ - name: 'App', - rootElement: '#qunit-fixture' - }); + queryParamsStickyTest1(urlPrefix) { + let assert = this.assert; - App.deferReadiness(); + assert.expect(14); - registry = App.__registry__; - container = App.__container__; + return this.boot().then(() => { + run(this.$link1, 'click'); + this.assertCurrentPath(`${urlPrefix}/a-1`); - registry.register('location:test', TestLocation); + this.setAndFlush(this.controller, 'q', 'lol'); - startingURL = expectedReplaceURL = expectedPushURL = ''; + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - App.Router.reopen({ - location: 'test' - }); + run(this.$link2, 'click'); - App.LoadingRoute = Route.extend({ + assert.equal(this.controller.get('q'), 'wat'); + assert.equal(this.controller.get('z'), 0); + assert.deepEqual(this.controller.get('model'), { id: 'a-2' }); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); }); + } - registry.register('template:application', compile('{{outlet}}')); - registry.register('template:home', compile('

Hours

')); - }); -} + queryParamsStickyTest2(urlPrefix) { + let assert = this.assert; -function sharedTeardown() { - run(function() { - App.destroy(); - App = null; - setTemplates({}); - }); -} + assert.expect(24); -function queryParamsStickyTest1(urlPrefix) { - return function() { - this.boot(); + return this.boot().then(() => { + this.expectedModelHookParams = { id: 'a-1', q: 'lol', z: 0 }; + this.transitionTo(`${urlPrefix}/a-1?q=lol`); - run(this.$link1, 'click'); - equal(router.get('location.path'), `${urlPrefix}/a-1`); + assert.deepEqual(this.controller.get('model'), { id: 'a-1' }); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - setAndFlush(this.controller, 'q', 'lol'); + this.expectedModelHookParams = { id: 'a-2', q: 'lol', z: 0 }; + this.transitionTo(`${urlPrefix}/a-2?q=lol`); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); + assert.deepEqual(this.controller.get('model'), { id: 'a-2' }, 'controller\'s model changed to a-2'); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); // fail + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - run(this.$link2, 'click'); + this.expectedModelHookParams = { id: 'a-3', q: 'lol', z: 123 }; + this.transitionTo(`${urlPrefix}/a-3?q=lol&z=123`); - equal(this.controller.get('q'), 'wat'); - equal(this.controller.get('z'), 0); - deepEqual(this.controller.get('model'), { id: 'a-2' }); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - }; -} + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 123); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=lol&z=123`); + }); + } -function queryParamsStickyTest2(urlPrefix) { - return function() { - this.boot(); - - this.expectedModelHookParams = { id: 'a-1', q: 'lol', z: 0 }; - handleURL(`${urlPrefix}/a-1?q=lol`); - - deepEqual(this.controller.get('model'), { id: 'a-1' }); - equal(this.controller.get('q'), 'lol'); - equal(this.controller.get('z'), 0); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - - this.expectedModelHookParams = { id: 'a-2', q: 'lol', z: 0 }; - handleURL(`${urlPrefix}/a-2?q=lol`); - - deepEqual(this.controller.get('model'), { id: 'a-2' }, 'controller\'s model changed to a-2'); - equal(this.controller.get('q'), 'lol'); - equal(this.controller.get('z'), 0); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); // fail - equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - - this.expectedModelHookParams = { id: 'a-3', q: 'lol', z: 123 }; - handleURL(`${urlPrefix}/a-3?q=lol&z=123`); - - equal(this.controller.get('q'), 'lol'); - equal(this.controller.get('z'), 123); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=lol&z=123`); - }; -} + queryParamsStickyTest3(urlPrefix, articleLookup) { + let assert = this.assert; + + assert.expect(32); + + this.registerTemplate('application', `{{#each articles as |a|}} {{link-to 'Article' '${articleLookup}' a.id id=a.id}} {{/each}}`); + + return this.boot().then(() => { + this.expectedModelHookParams = { id: 'a-1', q: 'wat', z: 0 }; + this.transitionTo(articleLookup, 'a-1'); + + assert.deepEqual(this.controller.get('model'), { id: 'a-1' }); + assert.equal(this.controller.get('q'), 'wat'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); + + this.expectedModelHookParams = { id: 'a-2', q: 'lol', z: 0 }; + this.transitionTo(articleLookup, 'a-2', { queryParams: { q: 'lol' } }); + + assert.deepEqual(this.controller.get('model'), { id: 'a-2' }); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); + + this.expectedModelHookParams = { id: 'a-3', q: 'hay', z: 0 }; + this.transitionTo(articleLookup, 'a-3', { queryParams: { q: 'hay' } }); + + assert.deepEqual(this.controller.get('model'), { id: 'a-3' }); + assert.equal(this.controller.get('q'), 'hay'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=hay`); + + this.expectedModelHookParams = { id: 'a-2', q: 'lol', z: 1 }; + this.transitionTo(articleLookup, 'a-2', { queryParams: { z: 1 } }); + + assert.deepEqual(this.controller.get('model'), { id: 'a-2' }); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 1); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol&z=1`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=hay`); + }); + } -function queryParamsStickyTest3(urlPrefix, articleLookup) { - return function() { - registry.register('template:application', compile(`{{#each articles as |a|}} {{link-to 'Article' '${articleLookup}' a.id id=a.id}} {{/each}}`)); - - this.boot(); - - this.expectedModelHookParams = { id: 'a-1', q: 'wat', z: 0 }; - run(router, 'transitionTo', articleLookup, 'a-1'); - - deepEqual(this.controller.get('model'), { id: 'a-1' }); - equal(this.controller.get('q'), 'wat'); - equal(this.controller.get('z'), 0); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - - this.expectedModelHookParams = { id: 'a-2', q: 'lol', z: 0 }; - run(router, 'transitionTo', articleLookup, 'a-2', { queryParams: { q: 'lol' } }); - - deepEqual(this.controller.get('model'), { id: 'a-2' }); - equal(this.controller.get('q'), 'lol'); - equal(this.controller.get('z'), 0); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3`); - - this.expectedModelHookParams = { id: 'a-3', q: 'hay', z: 0 }; - run(router, 'transitionTo', articleLookup, 'a-3', { queryParams: { q: 'hay' } }); - - deepEqual(this.controller.get('model'), { id: 'a-3' }); - equal(this.controller.get('q'), 'hay'); - equal(this.controller.get('z'), 0); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=hay`); - - this.expectedModelHookParams = { id: 'a-2', q: 'lol', z: 1 }; - run(router, 'transitionTo', articleLookup, 'a-2', { queryParams: { z: 1 } }); - - deepEqual(this.controller.get('model'), { id: 'a-2' }); - equal(this.controller.get('q'), 'lol'); - equal(this.controller.get('z'), 1); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol&z=1`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=hay`); - }; -} + queryParamsStickyTest4(urlPrefix, articleLookup) { + let assert = this.assert; -function queryParamsStickyTest4(urlPrefix, articleLookup) { - return function() { - let articleClass = StringUtils.classify(articleLookup); + assert.expect(24); - App[`${articleClass}Controller`].reopen({ + this.setupApplication(); + + this.reopenController(articleLookup, { queryParams: { q: { scope: 'controller' } } }); - this.boot(); + return this.visitApplication().then(() => { + run(this.$link1, 'click'); + this.assertCurrentPath(`${urlPrefix}/a-1`); - run(this.$link1, 'click'); - equal(router.get('location.path'), `${urlPrefix}/a-1`); + this.setAndFlush(this.controller, 'q', 'lol'); - setAndFlush(this.controller, 'q', 'lol'); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=lol`); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=lol`); + run(this.$link2, 'click'); - run(this.$link2, 'click'); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.deepEqual(this.controller.get('model'), { id: 'a-2' }); - equal(this.controller.get('q'), 'lol'); - equal(this.controller.get('z'), 0); - deepEqual(this.controller.get('model'), { id: 'a-2' }); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=lol`); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=lol`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=lol`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=lol`); + this.expectedModelHookParams = { id: 'a-3', q: 'haha', z: 123 }; + this.transitionTo(`${urlPrefix}/a-3?q=haha&z=123`); - this.expectedModelHookParams = { id: 'a-3', q: 'haha', z: 123 }; - handleURL(`${urlPrefix}/a-3?q=haha&z=123`); + assert.deepEqual(this.controller.get('model'), { id: 'a-3' }); + assert.equal(this.controller.get('q'), 'haha'); + assert.equal(this.controller.get('z'), 123); - deepEqual(this.controller.get('model'), { id: 'a-3' }); - equal(this.controller.get('q'), 'haha'); - equal(this.controller.get('z'), 123); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=haha`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=haha`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=haha&z=123`); - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=haha`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=haha`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=haha&z=123`); + this.setAndFlush(this.controller, 'q', 'woot'); - setAndFlush(this.controller, 'q', 'woot'); + assert.equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=woot`); + assert.equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=woot`); + assert.equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=woot&z=123`); + }); + } - equal(this.$link1.attr('href'), `${urlPrefix}/a-1?q=woot`); - equal(this.$link2.attr('href'), `${urlPrefix}/a-2?q=woot`); - equal(this.$link3.attr('href'), `${urlPrefix}/a-3?q=woot&z=123`); - }; -} + queryParamsStickyTest5(urlPrefix, commentsLookupKey) { + let assert = this.assert; -function queryParamsStickyTest5(urlPrefix, commentsLookupKey) { - return function() { - this.boot(); + assert.expect(12); - run(router, 'transitionTo', commentsLookupKey, 'a-1'); + return this.boot().then(() => { + this.transitionTo(commentsLookupKey, 'a-1'); - let commentsCtrl = container.lookup(`controller:${commentsLookupKey}`); - equal(commentsCtrl.get('page'), 1); - equal(router.get('location.path'), `${urlPrefix}/a-1/comments`); + let commentsCtrl = this.getController(commentsLookupKey); + assert.equal(commentsCtrl.get('page'), 1); + this.assertCurrentPath(`${urlPrefix}/a-1/comments`); - setAndFlush(commentsCtrl, 'page', 2); - equal(router.get('location.path'), `${urlPrefix}/a-1/comments?page=2`); + this.setAndFlush(commentsCtrl, 'page', 2); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=2`); - setAndFlush(commentsCtrl, 'page', 3); - equal(router.get('location.path'), `${urlPrefix}/a-1/comments?page=3`); + this.setAndFlush(commentsCtrl, 'page', 3); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=3`); - run(router, 'transitionTo', commentsLookupKey, 'a-2'); - equal(commentsCtrl.get('page'), 1); - equal(router.get('location.path'), `${urlPrefix}/a-2/comments`); + this.transitionTo(commentsLookupKey, 'a-2'); + assert.equal(commentsCtrl.get('page'), 1); + this.assertCurrentPath(`${urlPrefix}/a-2/comments`); - run(router, 'transitionTo', commentsLookupKey, 'a-1'); - equal(commentsCtrl.get('page'), 3); - equal(router.get('location.path'), `${urlPrefix}/a-1/comments?page=3`); - }; -} + this.transitionTo(commentsLookupKey, 'a-1'); + assert.equal(commentsCtrl.get('page'), 3); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=3`); + }); + } + + queryParamsStickyTest6(urlPrefix, articleLookup, commentsLookup) { + let assert = this.assert; + + assert.expect(13); -function queryParamsStickyTest6(urlPrefix, articleLookup, commentsLookup) { - return function() { - let articleClass = StringUtils.classify(articleLookup); + this.setupApplication(); - App[`${articleClass}Route`].reopen({ + this.reopenRoute(articleLookup, { resetController(controller, isExiting) { this.controllerFor(commentsLookup).set('page', 1); if (isExiting) { @@ -294,115 +233,119 @@ function queryParamsStickyTest6(urlPrefix, articleLookup, commentsLookup) { } }); - registry.register('template:about', compile(`{{link-to 'A' '${commentsLookup}' 'a-1' id='one'}} {{link-to 'B' '${commentsLookup}' 'a-2' id='two'}}`)); + this.registerTemplate('about', `{{link-to 'A' '${commentsLookup}' 'a-1' id='one'}} {{link-to 'B' '${commentsLookup}' 'a-2' id='two'}}`); - this.boot(); + return this.visitApplication().then(() => { + this.transitionTo(commentsLookup, 'a-1'); - run(router, 'transitionTo', commentsLookup, 'a-1'); + let commentsCtrl = this.getController(commentsLookup); + assert.equal(commentsCtrl.get('page'), 1); + this.assertCurrentPath(`${urlPrefix}/a-1/comments`); - let commentsCtrl = container.lookup(`controller:${commentsLookup}`); - equal(commentsCtrl.get('page'), 1); - equal(router.get('location.path'), `${urlPrefix}/a-1/comments`); + this.setAndFlush(commentsCtrl, 'page', 2); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=2`); - setAndFlush(commentsCtrl, 'page', 2); - equal(router.get('location.path'), `${urlPrefix}/a-1/comments?page=2`); + this.transitionTo(commentsLookup, 'a-2'); + assert.equal(commentsCtrl.get('page'), 1); + assert.equal(this.controller.get('q'), 'wat'); - run(router, 'transitionTo', commentsLookup, 'a-2'); - equal(commentsCtrl.get('page'), 1); - equal(this.controller.get('q'), 'wat'); + this.transitionTo(commentsLookup, 'a-1'); - run(router, 'transitionTo', commentsLookup, 'a-1'); + this.assertCurrentPath(`${urlPrefix}/a-1/comments`); + assert.equal(commentsCtrl.get('page'), 1); - equal(router.get('location.path'), `${urlPrefix}/a-1/comments`); - equal(commentsCtrl.get('page'), 1); - - run(router, 'transitionTo', 'about'); - - equal(jQuery('#one').attr('href'), `${urlPrefix}/a-1/comments?q=imdone`); - equal(jQuery('#two').attr('href'), `${urlPrefix}/a-2/comments`); - }; + this.transitionTo('about'); + assert.equal(jQuery('#one').attr('href'), `${urlPrefix}/a-1/comments?q=imdone`); + assert.equal(jQuery('#two').attr('href'), `${urlPrefix}/a-2/comments`); + }); + } } - -QUnit.module('Model Dep Query Params', { - setup() { - sharedSetup(); - - App.Router.map(function() { +moduleFor('Query Params - model-dependent state', class extends ModelDependentQPTestCase { + setupApplication() { + this.router.map(function() { this.route('article', { path: '/a/:id' }, function() { this.route('comments', { resetNamespace: true }); }); this.route('about'); }); - let articles = this.articles = emberA([{ id: 'a-1' }, { id: 'a-2' }, { id: 'a-3' }]); + let articles = emberA([{ id: 'a-1' }, { id: 'a-2' }, { id: 'a-3' }]); - App.ApplicationController = Controller.extend({ - articles: this.articles - }); + this.registerController('application', Controller.extend({ + articles + })); let self = this; - App.ArticleRoute = Route.extend({ + let assert = this.assert; + this.registerRoute('article', Route.extend({ model(params) { if (self.expectedModelHookParams) { - deepEqual(params, self.expectedModelHookParams, 'the ArticleRoute model hook received the expected merged dynamic segment + query params hash'); + assert.deepEqual(params, self.expectedModelHookParams, 'the ArticleRoute model hook received the expected merged dynamic segment + query params hash'); self.expectedModelHookParams = null; } return articles.findBy('id', params.id); } - }); + })); - App.ArticleController = Controller.extend({ + this.registerController('article', Controller.extend({ queryParams: ['q', 'z'], q: 'wat', z: 0 - }); + })); - App.CommentsController = Controller.extend({ + this.registerController('comments', Controller.extend({ queryParams: 'page', page: 1 - }); - - registry.register('template:application', compile('{{#each articles as |a|}} {{link-to \'Article\' \'article\' a id=a.id}} {{/each}} {{outlet}}')); + })); - this.boot = function() { - bootApplication(); + this.registerTemplate('application', '{{#each articles as |a|}} 1{{link-to \'Article\' \'article\' a id=a.id}} {{/each}} {{outlet}}'); + } - self.$link1 = jQuery('#a-1'); - self.$link2 = jQuery('#a-2'); - self.$link3 = jQuery('#a-3'); + visitApplication() { + return this.visit('/').then(() => { + let assert = this.assert; - equal(self.$link1.attr('href'), '/a/a-1'); - equal(self.$link2.attr('href'), '/a/a-2'); - equal(self.$link3.attr('href'), '/a/a-3'); + this.$link1 = jQuery('#a-1'); + this.$link2 = jQuery('#a-2'); + this.$link3 = jQuery('#a-3'); - self.controller = container.lookup('controller:article'); - }; - }, + assert.equal(this.$link1.attr('href'), '/a/a-1'); + assert.equal(this.$link2.attr('href'), '/a/a-2'); + assert.equal(this.$link3.attr('href'), '/a/a-3'); - teardown() { - sharedTeardown(); - ok(!this.expectedModelHookParams, 'there should be no pending expectation of expected model hook params'); + this.controller = this.getController('article'); + }); } -}); - -QUnit.test('query params have \'model\' stickiness by default', queryParamsStickyTest1('/a')); -QUnit.test('query params have \'model\' stickiness by default (url changes)', queryParamsStickyTest2('/a')); + ['@test query params have \'model\' stickiness by default']() { + return this.queryParamsStickyTest1('/a'); + } -QUnit.test('query params have \'model\' stickiness by default (params-based transitions)', queryParamsStickyTest3('/a', 'article')); + ['@test query params have \'model\' stickiness by default (url changes)']() { + return this.queryParamsStickyTest2('/a'); + } -QUnit.test('\'controller\' stickiness shares QP state between models', queryParamsStickyTest4('/a', 'article')); + ['@test query params have \'model\' stickiness by default (params-based transitions)']() { + return this.queryParamsStickyTest3('/a', 'article'); + } -QUnit.test('\'model\' stickiness is scoped to current or first dynamic parent route', queryParamsStickyTest5('/a', 'comments')); + ['@test \'controller\' stickiness shares QP state between models']() { + return this.queryParamsStickyTest4('/a', 'article'); + } -QUnit.test('can reset query params using the resetController hook', queryParamsStickyTest6('/a', 'article', 'comments')); + ['@test \'model\' stickiness is scoped to current or first dynamic parent route']() { + return this.queryParamsStickyTest5('/a', 'comments'); + } -QUnit.module('Model Dep Query Params (nested)', { - setup() { - sharedSetup(); + ['@test can reset query params using the resetController hook']() { + return this.queryParamsStickyTest6('/a', 'article', 'comments'); + } +}); - App.Router.map(function() { +moduleFor('Query Params - model-dependent state (nested)', class extends ModelDependentQPTestCase { + setupApplication() { + this.router.map(function() { this.route('site', function() { this.route('article', { path: '/a/:id' }, function() { this.route('comments'); @@ -411,74 +354,82 @@ QUnit.module('Model Dep Query Params (nested)', { this.route('about'); }); - let site_articles = this.site_articles = emberA([{ id: 'a-1' }, { id: 'a-2' }, { id: 'a-3' }]); + let site_articles = emberA([{ id: 'a-1' }, { id: 'a-2' }, { id: 'a-3' }]); - App.ApplicationController = Controller.extend({ - articles: this.site_articles - }); + this.registerController('application', Controller.extend({ + articles: site_articles + })); let self = this; - App.SiteArticleRoute = Route.extend({ + let assert = this.assert; + this.registerRoute('site.article', Route.extend({ model(params) { if (self.expectedModelHookParams) { - deepEqual(params, self.expectedModelHookParams, 'the ArticleRoute model hook received the expected merged dynamic segment + query params hash'); + assert.deepEqual(params, self.expectedModelHookParams, 'the ArticleRoute model hook received the expected merged dynamic segment + query params hash'); self.expectedModelHookParams = null; } return site_articles.findBy('id', params.id); } - }); + })); - App.SiteArticleController = Controller.extend({ + this.registerController('site.article', Controller.extend({ queryParams: ['q', 'z'], q: 'wat', z: 0 - }); + })); - App.SiteArticleCommentsController = Controller.extend({ + this.registerController('site.article.comments', Controller.extend({ queryParams: 'page', page: 1 - }); - - registry.register('template:application', compile('{{#each articles as |a|}} {{link-to \'Article\' \'site.article\' a id=a.id}} {{/each}} {{outlet}}')); + })); - this.boot = function() { - bootApplication(); + this.registerTemplate('application', '{{#each articles as |a|}} {{link-to \'Article\' \'site.article\' a id=a.id}} {{/each}} {{outlet}}'); + } - self.$link1 = jQuery('#a-1'); - self.$link2 = jQuery('#a-2'); - self.$link3 = jQuery('#a-3'); + visitApplication() { + return this.visit('/').then(() => { + let assert = this.assert; - equal(self.$link1.attr('href'), '/site/a/a-1'); - equal(self.$link2.attr('href'), '/site/a/a-2'); - equal(self.$link3.attr('href'), '/site/a/a-3'); + this.$link1 = jQuery('#a-1'); + this.$link2 = jQuery('#a-2'); + this.$link3 = jQuery('#a-3'); - self.controller = container.lookup('controller:site.article'); - }; - }, + assert.equal(this.$link1.attr('href'), '/site/a/a-1'); + assert.equal(this.$link2.attr('href'), '/site/a/a-2'); + assert.equal(this.$link3.attr('href'), '/site/a/a-3'); - teardown() { - sharedTeardown(); - ok(!this.expectedModelHookParams, 'there should be no pending expectation of expected model hook params'); + this.controller = this.getController('site.article'); + }); } -}); -QUnit.test('query params have \'model\' stickiness by default', queryParamsStickyTest1('/site/a')); - -QUnit.test('query params have \'model\' stickiness by default (url changes)', queryParamsStickyTest2('/site/a')); + ['@test query params have \'model\' stickiness by default']() { + return this.queryParamsStickyTest1('/site/a'); + } -QUnit.test('query params have \'model\' stickiness by default (params-based transitions)', queryParamsStickyTest3('/site/a', 'site.article')); + ['@test query params have \'model\' stickiness by default (url changes)']() { + return this.queryParamsStickyTest2('/site/a'); + } -QUnit.test('\'controller\' stickiness shares QP state between models', queryParamsStickyTest4('/site/a', 'site.article')); + ['@test query params have \'model\' stickiness by default (params-based transitions)']() { + return this.queryParamsStickyTest3('/site/a', 'site.article'); + } -QUnit.test('\'model\' stickiness is scoped to current or first dynamic parent route', queryParamsStickyTest5('/site/a', 'site.article.comments')); + ['@test \'controller\' stickiness shares QP state between models']() { + return this.queryParamsStickyTest4('/site/a', 'site.article'); + } -QUnit.test('can reset query params using the resetController hook', queryParamsStickyTest6('/site/a', 'site.article', 'site.article.comments')); + ['@test \'model\' stickiness is scoped to current or first dynamic parent route']() { + return this.queryParamsStickyTest5('/site/a', 'site.article.comments'); + } -QUnit.module('Model Dep Query Params (nested & more than 1 dynamic segment)', { - setup() { - sharedSetup(); + ['@test can reset query params using the resetController hook']() { + return this.queryParamsStickyTest6('/site/a', 'site.article', 'site.article.comments'); + } +}); - App.Router.map(function() { +moduleFor('Query Params - model-dependent state (nested & more than 1 dynamic segment)', class extends ModelDependentQPTestCase { + setupApplication() { + this.router.map(function() { this.route('site', { path: '/site/:site_id' }, function() { this.route('article', { path: '/a/:article_id' }, function() { this.route('comments'); @@ -486,12 +437,12 @@ QUnit.module('Model Dep Query Params (nested & more than 1 dynamic segment)', { }); }); - let sites = this.sites = emberA([{ id: 's-1' }, { id: 's-2' }, { id: 's-3' }]); - let site_articles = this.site_articles = emberA([{ id: 'a-1' }, { id: 'a-2' }, { id: 'a-3' }]); + let sites = emberA([{ id: 's-1' }, { id: 's-2' }, { id: 's-3' }]); + let site_articles = emberA([{ id: 'a-1' }, { id: 'a-2' }, { id: 'a-3' }]); - App.ApplicationController = Controller.extend({ - siteArticles: this.site_articles, - sites: this.sites, + this.registerController('application', Controller.extend({ + siteArticles: site_articles, + sites, allSitesAllArticles: computed({ get() { let ret = []; @@ -505,379 +456,385 @@ QUnit.module('Model Dep Query Params (nested & more than 1 dynamic segment)', { return ret; } }) - }); + })); let self = this; - App.SiteRoute = Route.extend({ + let assert = this.assert; + this.registerRoute('site', Route.extend({ model(params) { if (self.expectedSiteModelHookParams) { - deepEqual(params, self.expectedSiteModelHookParams, 'the SiteRoute model hook received the expected merged dynamic segment + query params hash'); + assert.deepEqual(params, self.expectedSiteModelHookParams, 'the SiteRoute model hook received the expected merged dynamic segment + query params hash'); self.expectedSiteModelHookParams = null; } return sites.findBy('id', params.site_id); } - }); - App.SiteArticleRoute = Route.extend({ + })); + + this.registerRoute('site.article', Route.extend({ model(params) { if (self.expectedArticleModelHookParams) { - deepEqual(params, self.expectedArticleModelHookParams, 'the SiteArticleRoute model hook received the expected merged dynamic segment + query params hash'); + assert.deepEqual(params, self.expectedArticleModelHookParams, 'the SiteArticleRoute model hook received the expected merged dynamic segment + query params hash'); self.expectedArticleModelHookParams = null; } return site_articles.findBy('id', params.article_id); } - }); + })); - App.SiteController = Controller.extend({ + this.registerController('site', Controller.extend({ queryParams: ['country'], country: 'au' - }); + })); - App.SiteArticleController = Controller.extend({ + this.registerController('site.article', Controller.extend({ queryParams: ['q', 'z'], q: 'wat', z: 0 - }); + })); - App.SiteArticleCommentsController = Controller.extend({ + this.registerController('site.article.comments', Controller.extend({ queryParams: ['page'], page: 1 - }); + })); - registry.register('template:application', compile('{{#each allSitesAllArticles as |a|}} {{#link-to \'site.article\' a.site_id a.article_id id=a.id}}Article [{{a.site_id}}] [{{a.article_id}}]{{/link-to}} {{/each}} {{outlet}}')); - - this.boot = function() { - bootApplication(); - self.links = {}; - self.links['s-1-a-1'] = jQuery('#s-1-a-1'); - self.links['s-1-a-2'] = jQuery('#s-1-a-2'); - self.links['s-1-a-3'] = jQuery('#s-1-a-3'); - self.links['s-2-a-1'] = jQuery('#s-2-a-1'); - self.links['s-2-a-2'] = jQuery('#s-2-a-2'); - self.links['s-2-a-3'] = jQuery('#s-2-a-3'); - self.links['s-3-a-1'] = jQuery('#s-3-a-1'); - self.links['s-3-a-2'] = jQuery('#s-3-a-2'); - self.links['s-3-a-3'] = jQuery('#s-3-a-3'); - - equal(self.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); - equal(self.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); - equal(self.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); - equal(self.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); - equal(self.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); - equal(self.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(self.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); - equal(self.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(self.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - self.site_controller = container.lookup('controller:site'); - self.article_controller = container.lookup('controller:site.article'); - }; - }, + this.registerTemplate('application', '{{#each allSitesAllArticles as |a|}} {{#link-to \'site.article\' a.site_id a.article_id id=a.id}}Article [{{a.site_id}}] [{{a.article_id}}]{{/link-to}} {{/each}} {{outlet}}'); + } - teardown() { - sharedTeardown(); - ok(!this.expectedModelHookParams, 'there should be no pending expectation of expected model hook params'); + visitApplication() { + return this.visit('/').then(() => { + let assert = this.assert; + + this.links = {}; + this.links['s-1-a-1'] = jQuery('#s-1-a-1'); + this.links['s-1-a-2'] = jQuery('#s-1-a-2'); + this.links['s-1-a-3'] = jQuery('#s-1-a-3'); + this.links['s-2-a-1'] = jQuery('#s-2-a-1'); + this.links['s-2-a-2'] = jQuery('#s-2-a-2'); + this.links['s-2-a-3'] = jQuery('#s-2-a-3'); + this.links['s-3-a-1'] = jQuery('#s-3-a-1'); + this.links['s-3-a-2'] = jQuery('#s-3-a-2'); + this.links['s-3-a-3'] = jQuery('#s-3-a-3'); + + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + this.site_controller = this.getController('site'); + this.article_controller = this.getController('site.article'); + }); } -}); -QUnit.test('query params have \'model\' stickiness by default', function() { - this.boot(); - - run(this.links['s-1-a-1'], 'click'); - deepEqual(this.site_controller.get('model'), { id: 's-1' }); - deepEqual(this.article_controller.get('model'), { id: 'a-1' }); - equal(router.get('location.path'), '/site/s-1/a/a-1'); - - setAndFlush(this.article_controller, 'q', 'lol'); - - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - setAndFlush(this.site_controller, 'country', 'us'); - - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?country=us&q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?country=us'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?country=us'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - run(this.links['s-1-a-2'], 'click'); - - equal(this.site_controller.get('country'), 'us'); - equal(this.article_controller.get('q'), 'wat'); - equal(this.article_controller.get('z'), 0); - deepEqual(this.site_controller.get('model'), { id: 's-1' }); - deepEqual(this.article_controller.get('model'), { id: 'a-2' }); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?country=us&q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?country=us'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?country=us'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - run(this.links['s-2-a-2'], 'click'); - - equal(this.site_controller.get('country'), 'au'); - equal(this.article_controller.get('q'), 'wat'); - equal(this.article_controller.get('z'), 0); - deepEqual(this.site_controller.get('model'), { id: 's-2' }); - deepEqual(this.article_controller.get('model'), { id: 'a-2' }); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?country=us&q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?country=us'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?country=us'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); -}); + ['@test query params have \'model\' stickiness by default'](assert) { + assert.expect(59); // Insane. + + return this.boot().then(() => { + run(this.links['s-1-a-1'], 'click'); + assert.deepEqual(this.site_controller.get('model'), { id: 's-1' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-1' }); + this.assertCurrentPath('/site/s-1/a/a-1'); + + this.setAndFlush(this.article_controller, 'q', 'lol'); + + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + this.setAndFlush(this.site_controller, 'country', 'us'); + + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?country=us'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?country=us'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + run(this.links['s-1-a-2'], 'click'); + + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'wat'); + assert.equal(this.article_controller.get('z'), 0); + assert.deepEqual(this.site_controller.get('model'), { id: 's-1' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-2' }); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?country=us'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?country=us'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + run(this.links['s-2-a-2'], 'click'); + + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'wat'); + assert.equal(this.article_controller.get('z'), 0); + assert.deepEqual(this.site_controller.get('model'), { id: 's-2' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-2' }); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?country=us'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?country=us'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + }); + } -QUnit.test('query params have \'model\' stickiness by default (url changes)', function() { - this.boot(); - - this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; - this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'lol', z: 0 }; - handleURL('/site/s-1/a/a-1?q=lol'); - - deepEqual(this.site_controller.get('model'), { id: 's-1' }, 'site controller\'s model is s-1'); - deepEqual(this.article_controller.get('model'), { id: 'a-1' }, 'article controller\'s model is a-1'); - equal(this.site_controller.get('country'), 'au'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 0); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; - this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'lol', z: 0 }; - handleURL('/site/s-2/a/a-1?country=us&q=lol'); - - deepEqual(this.site_controller.get('model'), { id: 's-2' }, 'site controller\'s model is s-2'); - deepEqual(this.article_controller.get('model'), { id: 'a-1' }, 'article controller\'s model is a-1'); - equal(this.site_controller.get('country'), 'us'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 0); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; - this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 0 }; - handleURL('/site/s-2/a/a-2?country=us&q=lol'); - - deepEqual(this.site_controller.get('model'), { id: 's-2' }, 'site controller\'s model is s-2'); - deepEqual(this.article_controller.get('model'), { id: 'a-2' }, 'article controller\'s model is a-2'); - equal(this.site_controller.get('country'), 'us'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 0); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; - this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'lol', z: 123 }; - handleURL('/site/s-2/a/a-3?country=us&q=lol&z=123'); - - deepEqual(this.site_controller.get('model'), { id: 's-2' }, 'site controller\'s model is s-2'); - deepEqual(this.article_controller.get('model'), { id: 'a-3' }, 'article controller\'s model is a-3'); - equal(this.site_controller.get('country'), 'us'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 123); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=lol&z=123'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=lol&z=123'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=lol&z=123'); - - this.expectedSiteModelHookParams = { site_id: 's-3', country: 'nz' }; - this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'lol', z: 123 }; - handleURL('/site/s-3/a/a-3?country=nz&q=lol&z=123'); - - deepEqual(this.site_controller.get('model'), { id: 's-3' }, 'site controller\'s model is s-3'); - deepEqual(this.article_controller.get('model'), { id: 'a-3' }, 'article controller\'s model is a-3'); - equal(this.site_controller.get('country'), 'nz'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 123); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=lol&z=123'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=lol&z=123'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?country=nz&q=lol'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?country=nz&q=lol'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?country=nz&q=lol&z=123'); -}); + ['@test query params have \'model\' stickiness by default (url changes)'](assert) { + assert.expect(88); // INSANE. + + return this.boot().then(() => { + this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; + this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'lol', z: 0 }; + this.transitionTo('/site/s-1/a/a-1?q=lol'); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-1' }, 'site controller\'s model is s-1'); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-1' }, 'article controller\'s model is a-1'); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; + this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'lol', z: 0 }; + this.transitionTo('/site/s-2/a/a-1?country=us&q=lol'); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-2' }, 'site controller\'s model is s-2'); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-1' }, 'article controller\'s model is a-1'); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; + this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 0 }; + this.transitionTo('/site/s-2/a/a-2?country=us&q=lol'); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-2' }, 'site controller\'s model is s-2'); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-2' }, 'article controller\'s model is a-2'); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; + this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'lol', z: 123 }; + this.transitionTo('/site/s-2/a/a-3?country=us&q=lol&z=123'); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-2' }, 'site controller\'s model is s-2'); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-3' }, 'article controller\'s model is a-3'); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 123); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=lol&z=123'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=lol&z=123'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=lol&z=123'); + + this.expectedSiteModelHookParams = { site_id: 's-3', country: 'nz' }; + this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'lol', z: 123 }; + this.transitionTo('/site/s-3/a/a-3?country=nz&q=lol&z=123'); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-3' }, 'site controller\'s model is s-3'); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-3' }, 'article controller\'s model is a-3'); + assert.equal(this.site_controller.get('country'), 'nz'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 123); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=lol&z=123'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=lol&z=123'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?country=nz&q=lol'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?country=nz&q=lol'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?country=nz&q=lol&z=123'); + }); + } -QUnit.test('query params have \'model\' stickiness by default (params-based transitions)', function() { - this.boot(); - - this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; - this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'wat', z: 0 }; - run(router, 'transitionTo', 'site.article', 's-1', 'a-1'); - - deepEqual(this.site_controller.get('model'), { id: 's-1' }); - deepEqual(this.article_controller.get('model'), { id: 'a-1' }); - equal(this.site_controller.get('country'), 'au'); - equal(this.article_controller.get('q'), 'wat'); - equal(this.article_controller.get('z'), 0); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; - this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 0 }; - run(router, 'transitionTo', 'site.article', 's-1', 'a-2', { queryParams: { q: 'lol' } }); - - deepEqual(this.site_controller.get('model'), { id: 's-1' }); - deepEqual(this.article_controller.get('model'), { id: 'a-2' }); - equal(this.site_controller.get('country'), 'au'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 0); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?q=lol'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); - - this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; - this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'hay', z: 0 }; - run(router, 'transitionTo', 'site.article', 's-1', 'a-3', { queryParams: { q: 'hay' } }); - - deepEqual(this.site_controller.get('model'), { id: 's-1' }); - deepEqual(this.article_controller.get('model'), { id: 'a-3' }); - equal(this.site_controller.get('country'), 'au'); - equal(this.article_controller.get('q'), 'hay'); - equal(this.article_controller.get('z'), 0); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?q=lol'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?q=hay'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); - - this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; - this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 1 }; - run(router, 'transitionTo', 'site.article', 's-1', 'a-2', { queryParams: { z: 1 } }); - - deepEqual(this.site_controller.get('model'), { id: 's-1' }); - deepEqual(this.article_controller.get('model'), { id: 'a-2' }); - equal(this.site_controller.get('country'), 'au'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 1); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?q=lol&z=1'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?q=hay'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol&z=1'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); - - this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; - this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 1 }; - run(router, 'transitionTo', 'site.article', 's-2', 'a-2', { queryParams: { country: 'us' } }); - - deepEqual(this.site_controller.get('model'), { id: 's-2' }); - deepEqual(this.article_controller.get('model'), { id: 'a-2' }); - equal(this.site_controller.get('country'), 'us'); - equal(this.article_controller.get('q'), 'lol'); - equal(this.article_controller.get('z'), 1); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=hay'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol&z=1'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); - - this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; - this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'yeah', z: 0 }; - run(router, 'transitionTo', 'site.article', 's-2', 'a-1', { queryParams: { q: 'yeah' } }); - - deepEqual(this.site_controller.get('model'), { id: 's-2' }); - deepEqual(this.article_controller.get('model'), { id: 'a-1' }); - equal(this.site_controller.get('country'), 'us'); - equal(this.article_controller.get('q'), 'yeah'); - equal(this.article_controller.get('z'), 0); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=yeah'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=yeah'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=hay'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=yeah'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol&z=1'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); - - this.expectedSiteModelHookParams = { site_id: 's-3', country: 'nz' }; - this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'hay', z: 3 }; - run(router, 'transitionTo', 'site.article', 's-3', 'a-3', { queryParams: { country: 'nz', z: 3 } }); - - deepEqual(this.site_controller.get('model'), { id: 's-3' }); - deepEqual(this.article_controller.get('model'), { id: 'a-3' }); - equal(this.site_controller.get('country'), 'nz'); - equal(this.article_controller.get('q'), 'hay'); - equal(this.article_controller.get('z'), 3); - equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=yeah'); - equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); - equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay&z=3'); - equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=yeah'); - equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); - equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=hay&z=3'); - equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?country=nz&q=yeah'); - equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?country=nz&q=lol&z=1'); - equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?country=nz&q=hay&z=3'); + ['@test query params have \'model\' stickiness by default (params-based transitions)'](assert) { + assert.expect(118); // <-- INSANE! Like why is this even a thing? + + return this.boot().then(() => { + this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; + this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'wat', z: 0 }; + this.transitionTo('site.article', 's-1', 'a-1'); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-1' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-1' }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'wat'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; + this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 0 }; + this.transitionTo('site.article', 's-1', 'a-2', { queryParams: { q: 'lol' } }); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-1' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-2' }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?q=lol'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3'); + + this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; + this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'hay', z: 0 }; + this.transitionTo('site.article', 's-1', 'a-3', { queryParams: { q: 'hay' } }); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-1' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-3' }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'hay'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?q=lol'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?q=hay'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); + + this.expectedSiteModelHookParams = { site_id: 's-1', country: 'au' }; + this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 1 }; + this.transitionTo('site.article', 's-1', 'a-2', { queryParams: { z: 1 } }); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-1' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-2' }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 1); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?q=hay'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); + + this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; + this.expectedArticleModelHookParams = { article_id: 'a-2', q: 'lol', z: 1 }; + this.transitionTo('site.article', 's-2', 'a-2', { queryParams: { country: 'us' } }); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-2' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-2' }); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 1); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=hay'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); + + this.expectedSiteModelHookParams = { site_id: 's-2', country: 'us' }; + this.expectedArticleModelHookParams = { article_id: 'a-1', q: 'yeah', z: 0 }; + this.transitionTo('site.article', 's-2', 'a-1', { queryParams: { q: 'yeah' } }); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-2' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-1' }); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'yeah'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=yeah'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=yeah'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=hay'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?q=yeah'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?q=hay'); + + this.expectedSiteModelHookParams = { site_id: 's-3', country: 'nz' }; + this.expectedArticleModelHookParams = { article_id: 'a-3', q: 'hay', z: 3 }; + this.transitionTo('site.article', 's-3', 'a-3', { queryParams: { country: 'nz', z: 3 } }); + + assert.deepEqual(this.site_controller.get('model'), { id: 's-3' }); + assert.deepEqual(this.article_controller.get('model'), { id: 'a-3' }); + assert.equal(this.site_controller.get('country'), 'nz'); + assert.equal(this.article_controller.get('q'), 'hay'); + assert.equal(this.article_controller.get('z'), 3); + assert.equal(this.links['s-1-a-1'].attr('href'), '/site/s-1/a/a-1?q=yeah'); + assert.equal(this.links['s-1-a-2'].attr('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].attr('href'), '/site/s-1/a/a-3?q=hay&z=3'); + assert.equal(this.links['s-2-a-1'].attr('href'), '/site/s-2/a/a-1?country=us&q=yeah'); + assert.equal(this.links['s-2-a-2'].attr('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].attr('href'), '/site/s-2/a/a-3?country=us&q=hay&z=3'); + assert.equal(this.links['s-3-a-1'].attr('href'), '/site/s-3/a/a-1?country=nz&q=yeah'); + assert.equal(this.links['s-3-a-2'].attr('href'), '/site/s-3/a/a-2?country=nz&q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].attr('href'), '/site/s-3/a/a-3?country=nz&q=hay&z=3'); + }); + } }); diff --git a/packages/ember/tests/routing/query_params_test/overlapping_query_params_test.js b/packages/ember/tests/routing/query_params_test/overlapping_query_params_test.js index d3b50c25f84..08baca099ad 100644 --- a/packages/ember/tests/routing/query_params_test/overlapping_query_params_test.js +++ b/packages/ember/tests/routing/query_params_test/overlapping_query_params_test.js @@ -1,197 +1,107 @@ import { Controller } from 'ember-runtime'; -import { Route, NoneLocation } from 'ember-routing'; import { run, Mixin } from 'ember-metal'; -import { compile } from 'ember-template-compiler'; -import { Application } from 'ember-application'; -import { setTemplates, setTemplate } from 'ember-glimmer'; - -let App, router, registry, container; - -function bootApplication() { - router = container.lookup('router:main'); - run(App, 'advanceReadiness'); -} - -let startingURL = ''; -let expectedReplaceURL, expectedPushURL; - -function setAndFlush(obj, prop, value) { - run(obj, 'set', prop, value); -} - -const TestLocation = NoneLocation.extend({ - initState() { - this.set('path', startingURL); - }, - - setURL(path) { - if (expectedReplaceURL) { - ok(false, 'pushState occurred but a replaceState was expected'); - } - if (expectedPushURL) { - equal(path, expectedPushURL, 'an expected pushState occurred'); - expectedPushURL = null; - } - this.set('path', path); - }, - - replaceURL(path) { - if (expectedPushURL) { - ok(false, 'replaceState occurred but a pushState was expected'); - } - if (expectedReplaceURL) { - equal(path, expectedReplaceURL, 'an expected replaceState occurred'); - expectedReplaceURL = null; - } - this.set('path', path); - } -}); - -function sharedSetup() { - run(() => { - App = Application.create({ - name: 'App', - rootElement: '#qunit-fixture' - }); - - App.deferReadiness(); - - registry = App.__registry__; - container = App.__container__; - - registry.register('location:test', TestLocation); - - startingURL = expectedReplaceURL = expectedPushURL = ''; - - App.Router.reopen({ - location: 'test' - }); - - App.LoadingRoute = Route.extend({ - }); - - setTemplate('application', compile('{{outlet}}')); - setTemplate('home', compile('

Hours

')); - }); -} - -function sharedTeardown() { - run(() => { - App.destroy(); - App = null; - - setTemplates({}); - }); -} - +import { QueryParamTestCase, moduleFor } from 'internal-test-helpers'; -QUnit.module('Query Params - overlapping query param property names', { - setup() { - sharedSetup(); - - App.Router.map(function() { +moduleFor('Query Params - overlapping query param property names', class extends QueryParamTestCase { + setupBase() { + this.router.map(function() { this.route('parent', function() { this.route('child'); }); }); - this.boot = function() { - bootApplication(); - run(router, 'transitionTo', 'parent.child'); - }; - }, - - teardown() { - sharedTeardown(); + return this.visit('/parent/child'); } -}); - -QUnit.test('can remap same-named qp props', function() { - App.ParentController = Controller.extend({ - queryParams: { page: 'parentPage' }, - page: 1 - }); - App.ParentChildController = Controller.extend({ - queryParams: { page: 'childPage' }, - page: 1 - }); + ['@test can remap same-named qp props'](assert) { + this.registerController('parent', Controller.extend({ + queryParams: { page: 'parentPage' }, + page: 1 + })); - this.boot(); + this.registerController('parent.child', Controller.extend({ + queryParams: { page: 'childPage' }, + page: 1 + })); - equal(router.get('location.path'), '/parent/child'); + return this.setupBase().then(() => { + this.assertCurrentPath('/parent/child'); - let parentController = container.lookup('controller:parent'); - let parentChildController = container.lookup('controller:parent.child'); + let parentController = this.getController('parent'); + let parentChildController = this.getController('parent.child'); - setAndFlush(parentController, 'page', 2); - equal(router.get('location.path'), '/parent/child?parentPage=2'); - setAndFlush(parentController, 'page', 1); - equal(router.get('location.path'), '/parent/child'); + this.setAndFlush(parentController, 'page', 2); + this.assertCurrentPath('/parent/child?parentPage=2'); + this.setAndFlush(parentController, 'page', 1); + this.assertCurrentPath('/parent/child'); - setAndFlush(parentChildController, 'page', 2); - equal(router.get('location.path'), '/parent/child?childPage=2'); - setAndFlush(parentChildController, 'page', 1); - equal(router.get('location.path'), '/parent/child'); + this.setAndFlush(parentChildController, 'page', 2); + this.assertCurrentPath('/parent/child?childPage=2'); + this.setAndFlush(parentChildController, 'page', 1); + this.assertCurrentPath('/parent/child'); - run(() => { - parentController.set('page', 2); - parentChildController.set('page', 2); - }); - - equal(router.get('location.path'), '/parent/child?childPage=2&parentPage=2'); + run(() => { + parentController.set('page', 2); + parentChildController.set('page', 2); + }); - run(() => { - parentController.set('page', 1); - parentChildController.set('page', 1); - }); + this.assertCurrentPath('/parent/child?childPage=2&parentPage=2'); - equal(router.get('location.path'), '/parent/child'); -}); + run(() => { + parentController.set('page', 1); + parentChildController.set('page', 1); + }); -QUnit.test('query params in the same route hierarchy with the same url key get auto-scoped', function() { - App.ParentController = Controller.extend({ - queryParams: { foo: 'shared' }, - foo: 1 - }); - - App.ParentChildController = Controller.extend({ - queryParams: { bar: 'shared' }, - bar: 1 - }); - - let self = this; - expectAssertion(() => { - self.boot(); - }, 'You\'re not allowed to have more than one controller property map to the same query param key, but both `parent:foo` and `parent.child:bar` map to `shared`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `foo: { as: \'other-foo\' }`'); -}); + this.assertCurrentPath('/parent/child'); + }); + } -QUnit.test('Support shared but overridable mixin pattern', function() { - let HasPage = Mixin.create({ - queryParams: 'page', - page: 1 - }); + // FIXME: The error should throw without having to do `transitionTo`. + ['@test query params in the same route hierarchy with the same url key get auto-scoped'](assert) { + this.registerController('parent', Controller.extend({ + queryParams: { foo: 'shared' }, + foo: 1 + })); + + this.registerController('parent.child', Controller.extend({ + queryParams: { bar: 'shared' }, + bar: 1 + })); + + return this.setupBase().then((...args) => { + expectAssertion(() => { + this.transitionTo('parent.child'); + }, 'You\'re not allowed to have more than one controller property map to the same query param key, but both `parent:foo` and `parent.child:bar` map to `shared`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `foo: { as: \'other-foo\' }`'); + }); + } - App.ParentController = Controller.extend(HasPage, { - queryParams: { page: 'yespage' } - }); + ['@test Support shared but overridable mixin pattern'](assert) { + let HasPage = Mixin.create({ + queryParams: 'page', + page: 1 + }); - App.ParentChildController = Controller.extend(HasPage); + this.registerController('parent', Controller.extend(HasPage, { + queryParams: { page: 'yespage' } + })); - this.boot(); + this.registerController('parent.child', Controller.extend(HasPage)); - equal(router.get('location.path'), '/parent/child'); + return this.setupBase().then(() => { + this.assertCurrentPath('/parent/child'); - let parentController = container.lookup('controller:parent'); - let parentChildController = container.lookup('controller:parent.child'); + let parentController = this.getController('parent'); + let parentChildController = this.getController('parent.child'); - setAndFlush(parentChildController, 'page', 2); - equal(router.get('location.path'), '/parent/child?page=2'); - equal(parentController.get('page'), 1); - equal(parentChildController.get('page'), 2); + this.setAndFlush(parentChildController, 'page', 2); + this.assertCurrentPath('/parent/child?page=2'); + assert.equal(parentController.get('page'), 1); + assert.equal(parentChildController.get('page'), 2); - setAndFlush(parentController, 'page', 2); - equal(router.get('location.path'), '/parent/child?page=2&yespage=2'); - equal(parentController.get('page'), 2); - equal(parentChildController.get('page'), 2); + this.setAndFlush(parentController, 'page', 2); + this.assertCurrentPath('/parent/child?page=2&yespage=2'); + assert.equal(parentController.get('page'), 2); + assert.equal(parentChildController.get('page'), 2); + }); + } }); diff --git a/packages/ember/tests/routing/query_params_test/query_params_paramless_link_to_test.js b/packages/ember/tests/routing/query_params_test/query_params_paramless_link_to_test.js index 13513ee94c8..a016da73f47 100644 --- a/packages/ember/tests/routing/query_params_test/query_params_paramless_link_to_test.js +++ b/packages/ember/tests/routing/query_params_test/query_params_paramless_link_to_test.js @@ -1,113 +1,28 @@ -import { Controller, String as StringUtils } from 'ember-runtime'; -import { Route, NoneLocation } from 'ember-routing'; -import { run } from 'ember-metal'; -import { compile } from 'ember-template-compiler'; -import { Application } from 'ember-application'; +import { Controller } from 'ember-runtime'; import { jQuery } from 'ember-views'; -import { setTemplates, setTemplate } from 'ember-glimmer'; +import { QueryParamTestCase, moduleFor } from 'internal-test-helpers'; -let App, container, router, registry; -let expectedReplaceURL, expectedPushURL; +moduleFor('Query Params - paramless link-to', class extends QueryParamTestCase { + testParamlessLinks(assert, routeName) { + assert.expect(1); + this.registerTemplate(routeName, '{{link-to \'index\' \'index\' id=\'index-link\'}}'); -let TestLocation = NoneLocation.extend({ - initState() { - this.set('path', startingURL); - }, - - setURL(path) { - if (expectedReplaceURL) { - ok(false, 'pushState occurred but a replaceState was expected'); - } - if (expectedPushURL) { - equal(path, expectedPushURL, 'an expected pushState occurred'); - expectedPushURL = null; - } - this.set('path', path); - }, - - replaceURL(path) { - if (expectedPushURL) { - ok(false, 'replaceState occurred but a pushState was expected'); - } - if (expectedReplaceURL) { - equal(path, expectedReplaceURL, 'an expected replaceState occurred'); - expectedReplaceURL = null; - } - this.set('path', path); - } -}); - -function bootApplication() { - router = container.lookup('router:main'); - run(App, 'advanceReadiness'); -} - -function sharedSetup() { - run(() => { - App = Application.create({ - name: 'App', - rootElement: '#qunit-fixture' - }); - - App.deferReadiness(); - - registry = App.__registry__; - container = App.__container__; - - registry.register('location:test', TestLocation); - - startingURL = expectedReplaceURL = expectedPushURL = ''; - - App.Router.reopen({ - location: 'test' - }); + this.registerController(routeName, Controller.extend({ + queryParams: ['foo'], + foo: 'wat' + })); - App.LoadingRoute = Route.extend({ + return this.visit('/?foo=YEAH').then(() => { + assert.equal(jQuery('#index-link').attr('href'), '/?foo=YEAH'); }); + } - setTemplate('application', compile('{{outlet}}')); - setTemplate('home', compile('

Hours

')); - }); -} - -function sharedTeardown() { - run(() => { - App.destroy(); - App = null; - setTemplates({}); - }); -} - -QUnit.module('Routing with Query Params', { - setup() { - sharedSetup(); - }, + ['@test param-less links in an app booted with query params in the URL don\'t reset the query params: application'](assert) { + return this.testParamlessLinks(assert, 'application'); + } - teardown() { - sharedTeardown(); + ['@test param-less links in an app booted with query params in the URL don\'t reset the query params: index'](assert) { + return this.testParamlessLinks(assert, 'index'); } }); - -let startingURL = ''; - -function testParamlessLinks(routeName) { - QUnit.test('param-less links in an app booted with query params in the URL don\'t reset the query params: ' + routeName, function() { - expect(1); - - setTemplate(routeName, compile('{{link-to \'index\' \'index\' id=\'index-link\'}}')); - - App[StringUtils.capitalize(routeName) + 'Controller'] = Controller.extend({ - queryParams: ['foo'], - foo: 'wat' - }); - - startingURL = '/?foo=YEAH'; - bootApplication(); - - equal(jQuery('#index-link').attr('href'), '/?foo=YEAH'); - }); -} - -testParamlessLinks('application'); -testParamlessLinks('index'); diff --git a/packages/internal-test-helpers/lib/index.js b/packages/internal-test-helpers/lib/index.js index a268819e8d8..903eb511f35 100644 --- a/packages/internal-test-helpers/lib/index.js +++ b/packages/internal-test-helpers/lib/index.js @@ -24,5 +24,6 @@ export { export { default as AbstractTestCase } from './test-cases/abstract'; export { default as AbstractApplicationTestCase } from './test-cases/abstract-application'; export { default as ApplicationTestCase } from './test-cases/application'; +export { default as QueryParamTestCase } from './test-cases/query-param'; export { default as AbstractRenderingTestCase } from './test-cases/abstract-rendering'; export { default as RenderingTestCase } from './test-cases/rendering'; diff --git a/packages/internal-test-helpers/lib/test-cases/abstract-application.js b/packages/internal-test-helpers/lib/test-cases/abstract-application.js index 77749cca0d4..035d84d9b07 100644 --- a/packages/internal-test-helpers/lib/test-cases/abstract-application.js +++ b/packages/internal-test-helpers/lib/test-cases/abstract-application.js @@ -15,9 +15,7 @@ export default class AbstractApplicationTestCase extends AbstractTestCase { this.application = run(Application, 'create', this.applicationOptions); - this.router = this.application.Router = Router.extend({ - location: 'none' - }); + this.router = this.application.Router = Router.extend(this.routerOptions); this.applicationInstance = null; } @@ -29,6 +27,12 @@ export default class AbstractApplicationTestCase extends AbstractTestCase { }; } + get routerOptions() { + return { + location: 'none' + }; + } + teardown() { if (this.applicationInstance) { runDestroy(this.applicationInstance); diff --git a/packages/internal-test-helpers/lib/test-cases/query-param.js b/packages/internal-test-helpers/lib/test-cases/query-param.js new file mode 100644 index 00000000000..8eed98fe0f8 --- /dev/null +++ b/packages/internal-test-helpers/lib/test-cases/query-param.js @@ -0,0 +1,77 @@ +import { NoneLocation } from 'ember-routing'; +import { run } from 'ember-metal'; + +import ApplicationTestCase from './application'; + +export default class QueryParamTestCase extends ApplicationTestCase { + constructor() { + super(); + + let testCase = this; + testCase.expectedPushURL = null; + testCase.expectedReplaceURL = null; + this.application.register('location:test', NoneLocation.extend({ + setURL(path) { + if (testCase.expectedReplaceURL) { + testCase.assert.ok(false, 'pushState occurred but a replaceState was expected'); + } + + if (testCase.expectedPushURL) { + testCase.assert.equal(path, testCase.expectedPushURL, 'an expected pushState occurred'); + testCase.expectedPushURL = null; + } + + this.set('path', path); + }, + + replaceURL(path) { + if (testCase.expectedPushURL) { + testCase.assert.ok(false, 'replaceState occurred but a pushState was expected'); + } + + if (testCase.expectedReplaceURL) { + testCase.assert.equal(path, testCase.expectedReplaceURL, 'an expected replaceState occurred'); + testCase.expectedReplaceURL = null; + } + + this.set('path', path); + } + })); + } + + visitAndAssert(path) { + return this.visit(...arguments).then(() => { + this.assertCurrentPath(path); + }); + } + + getController(name) { + return this.applicationInstance.lookup(`controller:${name}`); + } + + getRoute(name) { + return this.applicationInstance.lookup(`route:${name}`); + } + + get appRouter() { + return this.applicationInstance.lookup('router:main'); + } + + get routerOptions() { + return { + location: 'test' + }; + } + + setAndFlush(obj, prop, value) { + return run(obj, 'set', prop, value); + } + + assertCurrentPath(path, message = `current path equals '${path}'`) { + this.assert.equal(this.appRouter.get('location.path'), path, message); + } + + transitionTo() { + return run(this.appRouter, 'transitionTo', ...arguments); + } +}