From b0aee37f549ff600d04a8d150ecc171d444d70e9 Mon Sep 17 00:00:00 2001 From: Hugh Francis Date: Mon, 22 Jun 2015 17:08:01 -0400 Subject: [PATCH] Update for Ember Data 1.13.x, closes #32 --- .travis.yml | 2 + Brocfile.js | 23 ---- addon/mixins/route.js | 37 +++++-- bower.json | 19 ++-- config/ember-try.js | 25 +++-- index.js | 8 +- package.json | 22 ++-- tests/.jshintrc | 5 +- .../infinity-route-without-meta-test.js | 2 +- tests/dummy/app/adapters/application.js | 5 + tests/dummy/app/app.js | 4 +- tests/dummy/app/routes/demo.js | 1 - tests/dummy/app/templates/demo.hbs | 4 +- tests/helpers/start-app.js | 3 +- tests/unit/components/infinity-loader-test.js | 8 +- tests/unit/mixins/route-test.js | 100 ++++++++++++++++-- 16 files changed, 181 insertions(+), 87 deletions(-) delete mode 100644 Brocfile.js create mode 100644 tests/dummy/app/adapters/application.js diff --git a/.travis.yml b/.travis.yml index e8630cad..4cf67870 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: - EMBER_TRY_SCENARIO=ember-1.10 - EMBER_TRY_SCENARIO=ember-1.11 - EMBER_TRY_SCENARIO=ember-1.12 + - EMBER_TRY_SCENARIO=ember-1.13 - EMBER_TRY_SCENARIO=ember-release - EMBER_TRY_SCENARIO=ember-beta - EMBER_TRY_SCENARIO=ember-canary @@ -20,6 +21,7 @@ env: matrix: fast_finish: true allow_failures: + - env: EMBER_TRY_SCENARIO=ember-release - env: EMBER_TRY_SCENARIO=ember-beta - env: EMBER_TRY_SCENARIO=ember-canary diff --git a/Brocfile.js b/Brocfile.js deleted file mode 100644 index 87a43945..00000000 --- a/Brocfile.js +++ /dev/null @@ -1,23 +0,0 @@ -/* jshint node: true */ -/* global require, module */ - -var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); - -var app = new EmberAddon(); - -app.import('bower_components/babel-polyfill/browser-polyfill.js'); - -// Use `app.import` to add additional libraries to the generated -// output files. -// -// If you need to use different assets in different -// environments, specify an object as the first parameter. That -// object's keys should be the environment name and the values -// should be the asset to use in that environment. -// -// If the library that you are including contains AMD or ES6 -// modules that you would like to import into your application -// please specify an object with the list of modules as keys -// along with the exports of each module as its value. - -module.exports = app.toTree(); diff --git a/addon/mixins/route.js b/addon/mixins/route.js index 1e0b7ad3..db5bb53f 100644 --- a/addon/mixins/route.js +++ b/addon/mixins/route.js @@ -1,7 +1,7 @@ import Ember from 'ember'; +import { emberDataVersionIs } from 'ember-version-is'; -const { get } = Ember; - +const keys = Object.keys ? Object.keys : Ember.keys; /** The Ember Infinity Route Mixin enables an application route to load paginated records for the route `model` as triggered by the controller (or Infinity Loader @@ -98,9 +98,18 @@ export default Ember.Mixin.create({ * Path of the "total pages" param in * the HTTP response * @type {String} - * @default "meta.total_pages" + * @default "meta.total_pages" */ totalPagesParam: 'meta.total_pages', + + /** + * The supported findMethod name for + * the developers Ember Data version. + * Provided here for backwards compat. + * @type {String} + * @default "query" + */ + _storeFindMethod: 'query', /** @private @@ -126,7 +135,15 @@ export default Ember.Mixin.create({ */ infinityModel(modelName, options, boundParams) { - if (Ember.isEmpty(get(this, 'store')) || Ember.isEmpty(get(this, 'store').find)){ + if (emberDataVersionIs('greaterThan', '1.0.0-beta.19.2') && emberDataVersionIs('lessThan', '1.13.4')) { + throw new Ember.Error("Ember Infinity: You are using an unsupported version of Ember Data. Please upgrade to at least 1.13.4 or downgrade to 1.0.0-beta.19.2"); + } + + if (emberDataVersionIs('lessThan', '1.13.0')) { + this.set('_storeFindMethod', 'find'); + } + + if (Ember.isEmpty(this.store) || Ember.isEmpty(this.store[this._storeFindMethod])){ throw new Ember.Error("Ember Data store is not available to infinityModel"); } else if (modelName === undefined) { throw new Ember.Error("You must pass a Model Name to infinityModel"); @@ -157,7 +174,7 @@ export default Ember.Mixin.create({ } var params = Ember.merge(requestPayloadBase, options); - var promise = get(this, 'store').find(modelName, params); + let promise = this.store[this._storeFindMethod](modelName, params); promise.then( infinityModel => { @@ -201,9 +218,9 @@ export default Ember.Mixin.create({ requestPayloadBase[this.get('pageParam')] = nextPage; options = this._includeBoundParams(options, boundParams); - - var params = Ember.merge(requestPayloadBase, options); - var promise = get(this, 'store').find(modelName, params); + var params = Ember.merge(requestPayloadBase, this.get('_extraParams')); + + let promise = this.store[this._storeFindMethod](modelName, params); promise.then( newObjects => { @@ -245,8 +262,8 @@ export default Ember.Mixin.create({ @return {Object} */ _includeBoundParams: function(options, boundParams) { - if (Ember.keys(boundParams).length > 0) { - Ember.keys(boundParams).forEach( (key) => { + if (keys(boundParams).length > 0) { + keys(boundParams).forEach( (key) => { options[key] = this.get(boundParams[key]); }); } diff --git a/bower.json b/bower.json index a4a08b70..1ae0504b 100644 --- a/bower.json +++ b/bower.json @@ -1,19 +1,22 @@ { "name": "ember-infinity", "dependencies": { - "ember": "1.10.0", + "ember": "1.13.7", "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3", "ember-cli-test-loader": "ember-cli-test-loader#0.1.3", - "ember-data": "1.0.0-beta.19.1", + "ember-data": "1.13.8", "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5", - "ember-qunit": "0.4.1", + "ember-qunit": "0.4.9", "ember-qunit-notifications": "0.0.7", "ember-resolver": "~0.1.18", - "jquery": "^1.11.1", - "loader.js": "ember-cli/loader.js#3.2.0", - "pretender": "0.6.0", - "qunit": "~1.17.1", - "Faker": "~2.1.3", + "jquery": "^1.11.3", + "loader.js": "ember-cli/loader.js#3.2.1", + "qunit": "~1.18.0", + "pretender": "^0.9.0", + "Faker": "~3.0.1", "babel-polyfill": "~0.0.1" + }, + "resolutions": { + "FakeXMLHttpRequest": "~1.2.0" } } diff --git a/config/ember-try.js b/config/ember-try.js index 91ece79f..9fab8b98 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -7,46 +7,53 @@ module.exports = { { name: 'ember-1.10', dependencies: { - 'ember': '~1.10.0' + ember: '~1.10.0' } }, { name: 'ember-1.11', dependencies: { - 'ember': '~1.11.3' + ember: '~1.11.3' } }, { name: 'ember-1.12', dependencies: { - 'ember': '~1.12.0' + ember: '~1.12.0' + } + }, + { + name: 'ember-1.13', + dependencies: { + ember: '~1.13.0' } }, { name: 'ember-release', dependencies: { - 'ember': 'components/ember#release' + ember: 'components/ember#release' + }, resolutions: { - 'ember': 'release' + ember: 'release' } }, { name: 'ember-beta', dependencies: { - 'ember': 'components/ember#beta' + ember: 'components/ember#beta' }, resolutions: { - 'ember': 'beta' + ember: 'beta' } }, { name: 'ember-canary', dependencies: { - 'ember': 'components/ember#canary' + ember: 'components/ember#canary' }, resolutions: { - 'ember': 'canary' + ember: 'canary' } } ] diff --git a/index.js b/index.js index 2f2c3e11..07a8e3a6 100644 --- a/index.js +++ b/index.js @@ -12,9 +12,9 @@ module.exports = { included: function(app) { this.addons.forEach(function(addon){ - if (addon.name === "ember-version-is") { - addon.included.apply(addon, [app]); - } - }); + if (addon.name === "ember-version-is") { + addon.included.apply(addon, [app]); + } + }); } }; diff --git a/package.json b/package.json index 03b171a0..f67a9208 100644 --- a/package.json +++ b/package.json @@ -18,18 +18,18 @@ "author": "Hugh Francis", "license": "MIT", "devDependencies": { - "broccoli-asset-rev": "^2.0.2", - "ember-cli": "1.13.1", - "ember-cli-app-version": "~0.3.5", + "broccoli-asset-rev": "^2.1.2", + "ember-cli": "1.13.8", + "ember-cli-app-version": "0.5.0", "ember-cli-content-security-policy": "0.4.0", - "ember-cli-dependency-checker": "^1.0.0", + "ember-cli-dependency-checker": "^1.0.1", "ember-cli-github-pages": "0.0.6", "ember-cli-ic-ajax": "0.2.1", - "ember-cli-inject-live-reload": "^1.3.0", + "ember-cli-inject-live-reload": "^1.3.1", "ember-cli-pretender": "0.3.2", - "ember-cli-qunit": "0.3.15", - "ember-cli-uglify": "^1.0.1", - "ember-data": "1.0.0-beta.19.1", + "ember-cli-qunit": "^1.0.0", + "ember-cli-uglify": "^1.2.0", + "ember-data": "1.13.8", "ember-disable-prototype-extensions": "^1.0.0", "ember-disable-proxy-controllers": "^1.0.0", "ember-export-application-global": "^1.0.2", @@ -40,10 +40,10 @@ "ember-addon" ], "dependencies": { - "ember-cli-babel": "^5.0.0", + "ember-version-is": "0.0.3", + "ember-cli-babel": "^5.1.3", "ember-cli-htmlbars": "0.7.9", - "ember-cli-version-checker": "^1.0.2", - "ember-version-is": "0.0.3" + "ember-cli-version-checker": "^1.0.2" }, "ember-addon": { "configPath": "tests/dummy/config", diff --git a/tests/.jshintrc b/tests/.jshintrc index ea8b88f6..6ec0b7c1 100644 --- a/tests/.jshintrc +++ b/tests/.jshintrc @@ -26,7 +26,7 @@ "node": false, "browser": false, "boss": true, - "curly": false, + "curly": true, "debug": false, "devel": false, "eqeqeq": true, @@ -47,5 +47,6 @@ "strict": false, "white": false, "eqnull": true, - "esnext": true + "esnext": true, + "unused": true } diff --git a/tests/acceptance/infinity-route-without-meta-test.js b/tests/acceptance/infinity-route-without-meta-test.js index 91e68ad3..b8a1958e 100644 --- a/tests/acceptance/infinity-route-without-meta-test.js +++ b/tests/acceptance/infinity-route-without-meta-test.js @@ -9,7 +9,7 @@ module('Acceptance: Infinity Route', { setup() { App = startApp(); server = new Pretender(function() { - this.get('/posts', request => { + this.get('/posts', () => { var posts = [ { id: 1, name: "Squarepusher" }, { id: 2, name: "Aphex Twin" } diff --git a/tests/dummy/app/adapters/application.js b/tests/dummy/app/adapters/application.js new file mode 100644 index 00000000..02145242 --- /dev/null +++ b/tests/dummy/app/adapters/application.js @@ -0,0 +1,5 @@ +import DS from 'ember-data'; + +export default DS.RESTAdapter.extend({ + shouldBackgroundReloadRecord: function() { return false; } +}); diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js index 757df389..8d66b958 100644 --- a/tests/dummy/app/app.js +++ b/tests/dummy/app/app.js @@ -3,9 +3,11 @@ import Resolver from 'ember/resolver'; import loadInitializers from 'ember/load-initializers'; import config from './config/environment'; +var App; + Ember.MODEL_FACTORY_INJECTIONS = true; -var App = Ember.Application.extend({ +App = Ember.Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, Resolver: Resolver diff --git a/tests/dummy/app/routes/demo.js b/tests/dummy/app/routes/demo.js index 380c8ba2..100f5d6f 100644 --- a/tests/dummy/app/routes/demo.js +++ b/tests/dummy/app/routes/demo.js @@ -19,7 +19,6 @@ export default Ember.Route.extend(InfinityRoute, { var fakeData = generateFakeData(104); this.set('pretender', new Pretender()); this.get('pretender').get('/posts', request => { - var queryParams = request.queryParams; var fd = fakeData; var page = parseInt(request.queryParams.page, 10); var per = parseInt(request.queryParams.per_page, 10); diff --git a/tests/dummy/app/templates/demo.hbs b/tests/dummy/app/templates/demo.hbs index f8403fbb..8678181c 100644 --- a/tests/dummy/app/templates/demo.hbs +++ b/tests/dummy/app/templates/demo.hbs @@ -5,7 +5,7 @@

ember-infinity

- \ No newline at end of file + diff --git a/tests/helpers/start-app.js b/tests/helpers/start-app.js index e08b02d1..0f7aab1a 100644 --- a/tests/helpers/start-app.js +++ b/tests/helpers/start-app.js @@ -1,6 +1,5 @@ import Ember from 'ember'; import Application from '../../app'; -import Router from '../../router'; import config from '../../config/environment'; export default function startApp(attrs) { @@ -9,7 +8,7 @@ export default function startApp(attrs) { var attributes = Ember.merge({}, config.APP); attributes = Ember.merge(attributes, attrs); // use defaults, but you can override; - Ember.run(() => { + Ember.run(function() { application = Application.create(attributes); application.setupForTesting(); application.injectTestHelpers(); diff --git a/tests/unit/components/infinity-loader-test.js b/tests/unit/components/infinity-loader-test.js index 35697066..a02767e8 100644 --- a/tests/unit/components/infinity-loader-test.js +++ b/tests/unit/components/infinity-loader-test.js @@ -6,7 +6,9 @@ import { import Ember from 'ember'; import $ from 'jquery'; -moduleForComponent('infinity-loader'); +moduleForComponent('infinity-loader', { + unit: true +}); test('it renders', function(assert) { assert.expect(2); @@ -85,7 +87,7 @@ test('it uses the provided scrollable element', function(assert) { test('it throws error when scrollable element is not found', function(assert) { assert.expect(1); - var component = this.subject({scrollable: "#notfound"}); + assert.throws(function() { this.render(); }, Error, "Should raise error"); @@ -94,7 +96,7 @@ test('it throws error when scrollable element is not found', function(assert) { test('it throws error when multiple scrollable elements are found', function(assert) { assert.expect(1); $(document.body).append("
"); - var component = this.subject({scrollable: "div"}); + assert.throws(function() { this.render(); }, Error, "Should raise error"); diff --git a/tests/unit/mixins/route-test.js b/tests/unit/mixins/route-test.js index 52b9c3b6..c32ca1ea 100644 --- a/tests/unit/mixins/route-test.js +++ b/tests/unit/mixins/route-test.js @@ -38,7 +38,7 @@ test('it can not use infinityModel without a Model Name', assert => { }); var route = RouteObject.create(); route.store = { - find() {} + query() {} }; var infinityError; @@ -47,7 +47,7 @@ test('it can not use infinityModel without a Model Name', assert => { } catch(error) { infinityError = error; } - + assert.ok(infinityError instanceof Error); assert.equal(infinityError.message, "You must pass a Model Name to infinityModel"); }); @@ -62,7 +62,7 @@ test('it sets state before it reaches the end', assert => { var route = RouteObject.create(); var dummyStore = { - find() { + query() { return new Ember.RSVP.Promise(resolve => { Ember.run(this, resolve, Ember.Object.create({ items: [{id: 1, name: 'Test'}], @@ -101,7 +101,7 @@ test('it allows customizations of request params', assert => { var route = RouteObject.create(); var dummyStore = { - find(modelType, findQuery) { + query(modelType, findQuery) { assert.deepEqual(findQuery, {per: 25, p: 1}); return new Ember.RSVP.Promise(resolve => { Ember.run(this, resolve, Ember.Object.create({ @@ -131,7 +131,7 @@ test('it allows customizations of meta parsing params', assert => { var route = RouteObject.create(); var dummyStore = { - find(modelType, findQuery) { + query() { return new Ember.RSVP.Promise(resolve => { Ember.run(this, resolve, Ember.Object.create({ items: [{id: 1, name: 'Walter White'}], @@ -165,7 +165,7 @@ test('it sets state when it reaches the end', assert => { var route = RouteObject.create(); var dummyStore = { - find() { + query() { return new Ember.RSVP.Promise(resolve => { Ember.run(this, resolve, Ember.Object.create({ items: [{id: 1, name: 'Test'}], @@ -205,7 +205,7 @@ test('it uses extra params when loading more data', assert => { var route = RouteObject.create(); var dummyStore = { - find(name, params) { + query(name, params) { assert.equal('param', params.extra); return new Ember.RSVP.Promise(resolve => { Ember.run(this, resolve, Ember.Object.create({ @@ -266,7 +266,7 @@ test('it uses overridden params when loading more data', assert => { var route = RouteObject.create(); var dummyStore = { - find(name, params) { + query(name, params) { assert.equal(1, params.testPerPage); assert.ok(params.testPage); return new Ember.RSVP.Promise(resolve => { @@ -325,7 +325,7 @@ test('it uses bound params when loading more data', assert => { var route = RouteObject.create(); var dummyStore = { - find(name, params) { + query(name, params) { assert.equal(route.get('test'), params.category, 'dynamic param is equal to the value of the computed property'); return new Ember.RSVP.Promise(resolve => { Ember.run(this, resolve, Ember.Object.create({ @@ -391,7 +391,7 @@ test('it allows overrides/manual invocations of updateInfinityModel', assert => ]; var dummyStore = { - find(modelType, findQuery) { + query(modelType, findQuery) { var item = items[findQuery.page-1]; return new Ember.RSVP.Promise(resolve => { Ember.run(this, resolve, Ember.ArrayProxy.create({ @@ -440,3 +440,83 @@ test('it allows overrides/manual invocations of updateInfinityModel', assert => assert.equal(model.get('content.length'), 3); assert.equal(model.get('content.lastObject.title'), 'Tender Is the Night', 'updateInfinityModel can be invoked manually'); }); + +/* + * Compatibility Tests + */ +var dummyStore = { + _dummyFetch(modelType, findQuery) { + var items = [ + { id: 1, title: 'The Great Gatsby' }, + { id: 2, title: 'The Last Tycoon' } + ]; + var item = items[findQuery.page-1]; + return new Ember.RSVP.Promise(resolve => { + Ember.run(this, resolve, Ember.ArrayProxy.create({ + content: Ember.A([item]), + meta: { total_pages: 2 } + })); + }); + }, + query(modelType, findQuery) { + return this._dummyFetch(modelType, findQuery); + }, + find(modelType, findQuery) { + return this._dummyFetch(modelType, findQuery); + } +}; + +test('It uses Query for ED >= 1.13.4', assert => { + + var RouteObject = Ember.Route.extend(RouteMixin, { + store: dummyStore, + model() { + return this.infinityModel('item', { perPage: 1 }); + } + }); + + var route = RouteObject.create(); + + DS.VERSION = "1.13.4"; + return route.model().then(function() { + assert.equal(route.get('_storeFindMethod'), 'query'); + }); +}); + +test('It uses Find for ED <= 1.0.0-beta.19.2', assert => { + var RouteObject = Ember.Route.extend(RouteMixin, { + store: dummyStore, + model() { + return this.infinityModel('item', { perPage: 1 }); + } + }); + + var route = RouteObject.create(); + + DS.VERSION = "1.0.0-beta.19.2"; + return route.model().then(function() { + assert.equal(route.get('_storeFindMethod'), 'find'); + }); +}); + +test('It explodes when using an unsupported ED', assert => { + var RouteObject = Ember.Route.extend(RouteMixin, { + store: dummyStore, + model() { + return this.infinityModel('item', { perPage: 1 }); + } + }); + + var route = RouteObject.create(); + + DS.VERSION = "1.0.0-beta.19.3"; + + var infinityError; + try { + route.model(); + } catch(error) { + infinityError = error; + } + + assert.equal(infinityError.message, "Ember Infinity: You are using an unsupported version of Ember Data. Please upgrade to at least 1.13.4 or downgrade to 1.0.0-beta.19.2"); +});