From ff35ee78bfac058afb7a715a5dfc5760218cc05c Mon Sep 17 00:00:00 2001 From: Amiel Martin Date: Mon, 23 Mar 2015 20:56:42 -0700 Subject: [PATCH] Pass requestType to buildURL This is another step toward emberjs/rfcs#4. Once url-templates lands, most users extending BuildURLMixin will not need to handle requestType explicitly, as it will be possible to define a template for each request type. Also move buildURL specific RESTAdapter tests to a new file --- .../lib/adapters/build-url-mixin.js | 5 +- .../ember-data/lib/adapters/rest-adapter.js | 31 +- .../adapter/build-url-mixin-test.js | 293 ++++++++++++ .../integration/adapter/rest-adapter-test.js | 418 ++++++++---------- .../path-for-type-test.js | 7 +- 5 files changed, 498 insertions(+), 256 deletions(-) create mode 100644 packages/ember-data/tests/integration/adapter/build-url-mixin-test.js rename packages/ember-data/tests/unit/adapters/{rest-adapter => build-url-mixin}/path-for-type-test.js (74%) diff --git a/packages/ember-data/lib/adapters/build-url-mixin.js b/packages/ember-data/lib/adapters/build-url-mixin.js index c2a289cc25c..5fe51135919 100644 --- a/packages/ember-data/lib/adapters/build-url-mixin.js +++ b/packages/ember-data/lib/adapters/build-url-mixin.js @@ -14,7 +14,7 @@ var get = Ember.get; ```javascript export default DS.Adapter.extend(BuildURLMixin, { find: function(store, type, id, snapshot) { - var url = this.buildURL(type.typeKey, id, snapshot); + var url = this.buildURL(type.typeKey, id, snapshot, 'find'); return this.ajax(url, 'GET'); } }); @@ -45,9 +45,10 @@ export default Ember.Mixin.create({ @param {String} type @param {String|Array} id single id or array of ids @param {DS.Snapshot|Array} snapshot single snapshot or array of snapshots + @param {String} requestType @return {String} url */ - buildURL: function(type, id, snapshot) { + buildURL: function(type, id, snapshot, requestType) { var url = []; var host = get(this, 'host'); var prefix = this.urlPrefix(); diff --git a/packages/ember-data/lib/adapters/rest-adapter.js b/packages/ember-data/lib/adapters/rest-adapter.js index c27e8568470..ca7e3312033 100644 --- a/packages/ember-data/lib/adapters/rest-adapter.js +++ b/packages/ember-data/lib/adapters/rest-adapter.js @@ -344,7 +344,7 @@ export default Adapter.extend(BuildURLMixin, { @return {Promise} promise */ find: function(store, type, id, snapshot) { - return this.ajax(this.buildURL(type.typeKey, id, snapshot), 'GET'); + return this.ajax(this.buildURL(type.typeKey, id, snapshot, 'find'), 'GET'); }, /** @@ -362,13 +362,15 @@ export default Adapter.extend(BuildURLMixin, { @return {Promise} promise */ findAll: function(store, type, sinceToken) { - var query; + var query, url; if (sinceToken) { query = { since: sinceToken }; } - return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query }); + url = this.buildURL(type.typeKey, null, null, 'findAll'); + + return this.ajax(url, 'GET', { data: query }); }, /** @@ -389,10 +391,13 @@ export default Adapter.extend(BuildURLMixin, { @return {Promise} promise */ findQuery: function(store, type, query) { + var url = this.buildURL(type.typeKey, null, null, 'findQuery'); + if (this.sortQueryParams) { query = this.sortQueryParams(query); } - return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query }); + + return this.ajax(url, 'GET', { data: query }); }, /** @@ -429,7 +434,8 @@ export default Adapter.extend(BuildURLMixin, { @return {Promise} promise */ findMany: function(store, type, ids, snapshots) { - return this.ajax(this.buildURL(type.typeKey, ids, snapshots), 'GET', { data: { ids: ids } }); + var url = this.buildURL(type.typeKey, ids, snapshots, 'findMany'); + return this.ajax(url, 'GET', { data: { ids: ids } }); }, /** @@ -470,7 +476,9 @@ export default Adapter.extend(BuildURLMixin, { url = host + url; } - return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET'); + url = this.urlPrefix(url, this.buildURL(type, id, null, 'findHasMany')); + + return this.ajax(url, 'GET'); }, /** @@ -504,7 +512,8 @@ export default Adapter.extend(BuildURLMixin, { var id = snapshot.id; var type = snapshot.typeKey; - return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET'); + url = this.urlPrefix(url, this.buildURL(type, id, null, 'findBelongsTo')); + return this.ajax(url, 'GET'); }, /** @@ -526,10 +535,11 @@ export default Adapter.extend(BuildURLMixin, { createRecord: function(store, type, snapshot) { var data = {}; var serializer = store.serializerFor(type.typeKey); + var url = this.buildURL(type.typeKey, null, snapshot, 'createRecord'); serializer.serializeIntoHash(data, type, snapshot, { includeId: true }); - return this.ajax(this.buildURL(type.typeKey, null, snapshot), "POST", { data: data }); + return this.ajax(url, "POST", { data: data }); }, /** @@ -555,8 +565,9 @@ export default Adapter.extend(BuildURLMixin, { serializer.serializeIntoHash(data, type, snapshot); var id = snapshot.id; + var url = this.buildURL(type.typeKey, id, snapshot, 'updateRecord'); - return this.ajax(this.buildURL(type.typeKey, id, snapshot), "PUT", { data: data }); + return this.ajax(url, "PUT", { data: data }); }, /** @@ -573,7 +584,7 @@ export default Adapter.extend(BuildURLMixin, { deleteRecord: function(store, type, snapshot) { var id = snapshot.id; - return this.ajax(this.buildURL(type.typeKey, id, snapshot), "DELETE"); + return this.ajax(this.buildURL(type.typeKey, id, snapshot, 'deleteRecord'), "DELETE"); }, _stripIDFromURL: function(store, snapshot) { diff --git a/packages/ember-data/tests/integration/adapter/build-url-mixin-test.js b/packages/ember-data/tests/integration/adapter/build-url-mixin-test.js new file mode 100644 index 00000000000..63906a03640 --- /dev/null +++ b/packages/ember-data/tests/integration/adapter/build-url-mixin-test.js @@ -0,0 +1,293 @@ +var env, store, adapter, Post, Comment, SuperUser; +var passedUrl; +var run = Ember.run; + +module("integration/adapter/build-url-mixin - BuildURLMixin with RESTAdapter", { + setup: function() { + Post = DS.Model.extend({ + name: DS.attr("string") + }); + + Post.toString = function() { + return "Post"; + }; + + Comment = DS.Model.extend({ + name: DS.attr("string") + }); + + SuperUser = DS.Model.extend(); + + env = setupStore({ + post: Post, + comment: Comment, + superUser: SuperUser, + adapter: DS.RESTAdapter + }); + + store = env.store; + adapter = env.adapter; + + passedUrl = null; + } +}); + +function ajaxResponse(value) { + adapter.ajax = function(url, verb, hash) { + passedUrl = url; + + return run(Ember.RSVP, 'resolve', value); + }; +} + + +test('buildURL - with host and namespace', function() { + run(function() { + adapter.setProperties({ + host: 'http://example.com', + namespace: 'api/v1' + }); + }); + + ajaxResponse({ posts: [{ id: 1 }] }); + + run(store, 'find', 'post', 1).then(async(function(post) { + equal(passedUrl, "http://example.com/api/v1/posts/1"); + })); +}); + +test('buildURL - with relative paths in links', function() { + run(function() { + adapter.setProperties({ + host: 'http://example.com', + namespace: 'api/v1' + }); + }); + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); + Comment.reopen({ post: DS.belongsTo('post') }); + + ajaxResponse({ posts: [{ id: 1, links: { comments: 'comments' } }] }); + + run(store, 'find', 'post', '1').then(async(function(post) { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + })).then(async(function (comments) { + equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); + })); +}); + +test('buildURL - with absolute paths in links', function() { + run(function() { + adapter.setProperties({ + host: 'http://example.com', + namespace: 'api/v1' + }); + }); + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); + Comment.reopen({ post: DS.belongsTo('post') }); + + ajaxResponse({ posts: [{ id: 1, links: { comments: '/api/v1/posts/1/comments' } }] }); + + run(store, 'find', 'post', 1).then(async(function(post) { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + })).then(async(function (comments) { + equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); + })); +}); + + +test('buildURL - with absolute paths in links and protocol relative host', function() { + run(function() { + adapter.setProperties({ + host: '//example.com', + namespace: 'api/v1' + }); + }); + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); + Comment.reopen({ post: DS.belongsTo('post') }); + + ajaxResponse({ posts: [{ id: 1, links: { comments: '/api/v1/posts/1/comments' } }] }); + + run(store, 'find', 'post', 1).then(async(function(post) { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + })).then(async(function (comments) { + equal(passedUrl, "//example.com/api/v1/posts/1/comments"); + })); +}); + +test('buildURL - with full URLs in links', function() { + adapter.setProperties({ + host: 'http://example.com', + namespace: 'api/v1' + }); + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); + Comment.reopen({ post: DS.belongsTo('post') }); + + ajaxResponse({ + posts: [ + { id: 1, + links: { comments: 'http://example.com/api/v1/posts/1/comments' } + } + ] + }); + + run(function() { + store.find('post', 1).then(async(function(post) { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + })).then(async(function (comments) { + equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); + })); + }); +}); + +test('buildURL - with camelized names', function() { + adapter.setProperties({ + pathForType: function(type) { + var decamelized = Ember.String.decamelize(type); + return Ember.String.pluralize(decamelized); + } + }); + + ajaxResponse({ superUsers: [{ id: 1 }] }); + + run(function() { + store.find('superUser', 1).then(async(function(post) { + equal(passedUrl, "/super_users/1"); + })); + }); +}); + +test('buildURL - buildURL takes a record from find', function() { + Comment.reopen({ post: DS.belongsTo('post') }); + adapter.buildURL = function(type, id, snapshot) { + return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; + }; + + ajaxResponse({ comments: [{ id: 1 }] }); + + var post; + run(function() { + post = store.push('post', { id: 2 }); + }); + + run(function() { + store.find('comment', 1, { post: post }).then(async(function(post) { + equal(passedUrl, "/posts/2/comments/1"); + })); + }); +}); + +test('buildURL - buildURL takes the records from findMany', function() { + Comment.reopen({ post: DS.belongsTo('post') }); + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); + + adapter.buildURL = function(type, ids, snapshots) { + if (Ember.isArray(snapshots)) { + return "/posts/" + snapshots.get('firstObject').belongsTo('post', { id: true }) + '/comments/'; + } + return ""; + }; + adapter.coalesceFindRequests = true; + + ajaxResponse({ comments: [{ id: 1 }, { id: 2 }, { id: 3 }] }); + var post; + + run(function() { + post = store.push('post', { id: 2, comments: [1,2,3] }); + post.get('comments').then(async(function(post) { + equal(passedUrl, "/posts/2/comments/"); + })); + }); +}); + +test('buildURL - buildURL takes a record from create', function() { + Comment.reopen({ post: DS.belongsTo('post') }); + adapter.buildURL = function(type, id, snapshot) { + return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/'; + }; + + ajaxResponse({ comments: [{ id: 1 }] }); + + run(function() { + var post = store.push('post', { id: 2 }); + var comment = store.createRecord('comment'); + comment.set('post', post); + comment.save().then(async(function(post) { + equal(passedUrl, "/posts/2/comments/"); + })); + }); +}); + +test('buildURL - buildURL takes a record from create to query a resolved async belongsTo relationship', function() { + Comment.reopen({ post: DS.belongsTo('post', { async: true }) }); + + ajaxResponse({ posts: [{ id: 2 }] }); + + run(function() { + store.find('post', 2).then(async(function(post) { + equal(post.get('id'), 2); + + adapter.buildURL = function(type, id, snapshot) { + return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/'; + }; + + ajaxResponse({ comments: [{ id: 1 }] }); + + var comment = store.createRecord('comment'); + comment.set('post', post); + comment.save().then(async(function(post) { + equal(passedUrl, "/posts/2/comments/"); + })); + + })); + }); +}); + +test('buildURL - buildURL takes a record from update', function() { + Comment.reopen({ post: DS.belongsTo('post') }); + adapter.buildURL = function(type, id, snapshot) { + return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; + }; + + ajaxResponse({ comments: [{ id: 1 }] }); + + var post, comment; + run(function() { + post = store.push('post', { id: 2 }); + comment = store.push('comment', { id: 1 }); + comment.set('post', post); + }); + run(function() { + comment.save().then(async(function(post) { + equal(passedUrl, "/posts/2/comments/1"); + })); + }); +}); + +test('buildURL - buildURL takes a record from delete', function() { + Comment.reopen({ post: DS.belongsTo('post') }); + Post.reopen({ comments: DS.hasMany('comment') }); + adapter.buildURL = function(type, id, snapshot) { + return 'posts/' + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; + }; + + ajaxResponse({ comments: [{ id: 1 }] }); + + var post, comment; + run(function() { + post = store.push('post', { id: 2 }); + comment = store.push('comment', { id: 1 }); + + comment.set('post', post); + comment.deleteRecord(); + }); + run(function() { + comment.save().then(async(function(post) { + equal(passedUrl, "posts/2/comments/1"); + })); + }); +}); + diff --git a/packages/ember-data/tests/integration/adapter/rest-adapter-test.js b/packages/ember-data/tests/integration/adapter/rest-adapter-test.js index 2640deda4b3..063ee2c559c 100644 --- a/packages/ember-data/tests/integration/adapter/rest-adapter-test.js +++ b/packages/ember-data/tests/integration/adapter/rest-adapter-test.js @@ -55,6 +55,20 @@ test("find - basic payload", function() { })); }); + +test("find - passes buildURL a requestType", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + return "/" + requestType + "/post/" + id; + }; + + ajaxResponse({ posts: [{ id: 1, name: "Rails is omakase" }] }); + + + run(store, 'find', 'post', 1).then(async(function(post) { + equal(passedUrl, "/find/post/1"); + })); +}); + test("find - basic payload (with legacy singular name)", function() { ajaxResponse({ post: { id: 1, name: "Rails is omakase" } }); @@ -67,6 +81,7 @@ test("find - basic payload (with legacy singular name)", function() { equal(post.get('name'), "Rails is omakase"); })); }); + test("find - payload with sideloaded records of the same type", function() { ajaxResponse({ posts: [ @@ -169,6 +184,22 @@ test("create - an empty payload is a basic success if an id was specified", func }); }); +test("create - passes buildURL the requestType", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + return "/post/" + requestType; + }; + + ajaxResponse(); + var post; + + run(function() { + post = store.createRecord('post', { id: "some-uuid", name: "The Parley Letter" }); + post.save().then(async(function(post) { + equal(passedUrl, "/post/createRecord"); + })); + }); +}); + test("create - a payload with a new ID and data applies the updates", function() { ajaxResponse({ posts: [{ id: "1", name: "Dat Parley Letter" }] }); run(function() { @@ -511,6 +542,25 @@ test("update - an empty payload is a basic success", function() { })); }); +test("update - passes the requestType to buildURL", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + return "/posts/" + id + "/" + requestType; + }; + + run(function() { + store.push('post', { id: 1, name: "Rails is omakase" }); + }); + + store.find('post', 1).then(async(function(post) { + ajaxResponse(); + + post.set('name', "The Parley Letter"); + return post.save(); + })).then(async(function(post) { + equal(passedUrl, "/posts/1/updateRecord"); + })); +}); + test("update - a payload with updates applies the updates", function() { run(function() { store.push('post', { id: 1, name: "Rails is omakase" }); @@ -673,6 +723,25 @@ test("delete - an empty payload is a basic success", function() { })); }); +test("delete - passes the requestType to buildURL", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + return "/posts/" + id + "/" + requestType; + }; + + run(function() { + store.push('post', { id: 1, name: "Rails is omakase" }); + }); + + store.find('post', 1).then(async(function(post) { + ajaxResponse(); + + post.deleteRecord(); + return post.save(); + })).then(async(function(post) { + equal(passedUrl, "/posts/1/deleteRecord"); + })); +}); + test("delete - a payload with sideloaded updates pushes the updates", function() { run(function() { store.push('post', { id: 1, name: "Rails is omakase" }); @@ -776,6 +845,24 @@ test("findAll - returning an array populates the array", function() { })); }); + +test("findAll - passes buildURL the requestType", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + return "/" + requestType + "/posts"; + }; + + ajaxResponse({ + posts: [ + { id: 1, name: "Rails is omakase" }, + { id: 2, name: "The Parley Letter" } + ] + }); + + store.findAll('post').then(async(function(posts) { + equal(passedUrl, "/findAll/posts"); + })); +}); + test("findAll - returning sideloaded data loads the data", function() { ajaxResponse({ posts: [ @@ -879,6 +966,22 @@ test("findQuery - if `sortQueryParams` option is not provided, query params are })); }); +test("findQuery - passes buildURL the requestType", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + return "/" + requestType + "/posts"; + }; + + adapter.ajax = function(url, verb, hash) { + equal(url, '/findQuery/posts'); + + return run(Ember.RSVP, 'resolve', { posts: [{ id: 1, name: "Rails is very expensive sushi" }] }); + }; + + store.findQuery('post', { "params": 1, "in": 2, "wrong": 3, "order": 4 }).then(async(function() { + // NOOP + })); +}); + test("findQuery - if `sortQueryParams` is falsey, query params are not sorted at all", function() { adapter.ajax = function(url, verb, hash) { passedUrl = url; @@ -1074,6 +1177,31 @@ test("findMany - findMany uses a correct URL to access the records", function() })); }); +test("findMany - passes buildURL the requestType", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + return "/" + requestType + "/" + type; + }; + + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); + adapter.coalesceFindRequests = true; + + run(function() { + store.push('post', { id: 1, name: "Rails is omakase", comments: [1, 2, 3] }); + }); + + var post = store.getById('post', 1); + ajaxResponse({ + comments: [ + { id: 1, name: "FIRST" }, + { id: 2, name: "Rails is unagi" }, + { id: 3, name: "What is omakase?" } + ] + }); + run(post, 'get', 'comments').then(async(function(comments) { + equal(passedUrl, "/findMany/comment"); + })); +}); + test("findMany - findMany does not coalesce by default", function() { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -1250,6 +1378,41 @@ test("findHasMany - returning an array populates the array", function() { })); }); +test("findHasMany - passes buildURL the requestType", function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + equal(requestType, 'findHasMany'); + }; + + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); + + run(function() { + store.push( + 'post', + { + id: 1, + name: "Rails is omakase", + links: { comments: '/posts/1/comments' } + } + ); + }); + + run(store, 'find', 'post', '1').then(async(function(post) { + ajaxResponse({ + comments: [ + { id: 1, name: "FIRST" }, + { id: 2, name: "Rails is unagi" }, + { id: 3, name: "What is omakase?" } + ] + }); + + return post.get('comments'); + })).then(async(function(comments) { + // NOOP + })); +}); + + + test("findMany - returning sideloaded data loads the data", function() { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); adapter.coalesceFindRequests = true; @@ -1334,169 +1497,28 @@ test("findMany - a custom serializer is used if present", function() { })); }); -test('buildURL - with host and namespace', function() { - run(function() { - adapter.setProperties({ - host: 'http://example.com', - namespace: 'api/v1' - }); - }); - - ajaxResponse({ posts: [{ id: 1 }] }); - - run(store, 'find', 'post', 1).then(async(function(post) { - equal(passedUrl, "http://example.com/api/v1/posts/1"); - })); -}); - -test('buildURL - with relative paths in links', function() { - run(function() { - adapter.setProperties({ - host: 'http://example.com', - namespace: 'api/v1' - }); - }); - Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); - Comment.reopen({ post: DS.belongsTo('post') }); - - ajaxResponse({ posts: [{ id: 1, links: { comments: 'comments' } }] }); - - run(store, 'find', 'post', '1').then(async(function(post) { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - })).then(async(function (comments) { - equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); - })); -}); - -test('buildURL - with absolute paths in links', function() { - run(function() { - adapter.setProperties({ - host: 'http://example.com', - namespace: 'api/v1' - }); - }); - Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); - Comment.reopen({ post: DS.belongsTo('post') }); - - ajaxResponse({ posts: [{ id: 1, links: { comments: '/api/v1/posts/1/comments' } }] }); - - run(store, 'find', 'post', 1).then(async(function(post) { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - })).then(async(function (comments) { - equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); - })); -}); +test('findBelongsTo - passes buildURL the requestType', function() { + adapter.buildURL = function(type, id, snapshot, requestType) { + equal(requestType, 'findBelongsTo'); + }; + Comment.reopen({ post: DS.belongsTo('post', { async: true }) }); -test('buildURL - with absolute paths in links and protocol relative host', function() { run(function() { - adapter.setProperties({ - host: '//example.com', - namespace: 'api/v1' + store.push('comment', { + id: 1, name: "FIRST", + links: { post: '/posts/1' } }); }); - Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); - Comment.reopen({ post: DS.belongsTo('post') }); - ajaxResponse({ posts: [{ id: 1, links: { comments: '/api/v1/posts/1/comments' } }] }); - - run(store, 'find', 'post', 1).then(async(function(post) { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - })).then(async(function (comments) { - equal(passedUrl, "//example.com/api/v1/posts/1/comments"); + run(store, 'find', 'comment', 1).then(async(function(comment) { + ajaxResponse({ post: { id: 1, name: 'Rails is omakase' } }); + return comment.get('post'); + })).then(async(function(post) { + // NOOP })); }); -test('buildURL - with full URLs in links', function() { - adapter.setProperties({ - host: 'http://example.com', - namespace: 'api/v1' - }); - Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); - Comment.reopen({ post: DS.belongsTo('post') }); - - ajaxResponse({ - posts: [ - { id: 1, - links: { comments: 'http://example.com/api/v1/posts/1/comments' } - } - ] - }); - - run(function() { - store.find('post', 1).then(async(function(post) { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - })).then(async(function (comments) { - equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); - })); - }); -}); - -test('buildURL - with camelized names', function() { - adapter.setProperties({ - pathForType: function(type) { - var decamelized = Ember.String.decamelize(type); - return Ember.String.pluralize(decamelized); - } - }); - - ajaxResponse({ superUsers: [{ id: 1 }] }); - - run(function() { - store.find('superUser', 1).then(async(function(post) { - equal(passedUrl, "/super_users/1"); - })); - }); -}); - -test('buildURL - buildURL takes a record from find', function() { - Comment.reopen({ post: DS.belongsTo('post') }); - adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; - }; - - ajaxResponse({ comments: [{ id: 1 }] }); - - var post; - run(function() { - post = store.push('post', { id: 2 }); - }); - - run(function() { - store.find('comment', 1, { post: post }).then(async(function(post) { - equal(passedUrl, "/posts/2/comments/1"); - })); - }); -}); - -test('buildURL - buildURL takes the records from findMany', function() { - Comment.reopen({ post: DS.belongsTo('post') }); - Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); - - adapter.buildURL = function(type, ids, snapshots) { - if (Ember.isArray(snapshots)) { - return "/posts/" + snapshots.get('firstObject').belongsTo('post', { id: true }) + '/comments/'; - } - return ""; - }; - adapter.coalesceFindRequests = true; - - ajaxResponse({ comments: [{ id: 1 }, { id: 2 }, { id: 3 }] }); - var post; - - run(function() { - post = store.push('post', { id: 2, comments: [1,2,3] }); - post.get('comments').then(async(function(post) { - equal(passedUrl, "/posts/2/comments/"); - })); - }); -}); - - test('coalesceFindRequests warns if the expected records are not returned in the coalesced request', function() { Comment.reopen({ post: DS.belongsTo('post') }); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -1514,94 +1536,6 @@ test('coalesceFindRequests warns if the expected records are not returned in the }, /expected to find records with the following ids in the adapter response but they were missing: \[2,3\]/); }); -test('buildURL - buildURL takes a record from create', function() { - Comment.reopen({ post: DS.belongsTo('post') }); - adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/'; - }; - - ajaxResponse({ comments: [{ id: 1 }] }); - - run(function() { - var post = store.push('post', { id: 2 }); - var comment = store.createRecord('comment'); - comment.set('post', post); - comment.save().then(async(function(post) { - equal(passedUrl, "/posts/2/comments/"); - })); - }); -}); - -test('buildURL - buildURL takes a record from create to query a resolved async belongsTo relationship', function() { - Comment.reopen({ post: DS.belongsTo('post', { async: true }) }); - - ajaxResponse({ posts: [{ id: 2 }] }); - - run(function() { - store.find('post', 2).then(async(function(post) { - equal(post.get('id'), 2); - - adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/'; - }; - - ajaxResponse({ comments: [{ id: 1 }] }); - - var comment = store.createRecord('comment'); - comment.set('post', post); - comment.save().then(async(function(post) { - equal(passedUrl, "/posts/2/comments/"); - })); - - })); - }); -}); - -test('buildURL - buildURL takes a record from update', function() { - Comment.reopen({ post: DS.belongsTo('post') }); - adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; - }; - - ajaxResponse({ comments: [{ id: 1 }] }); - - var post, comment; - run(function() { - post = store.push('post', { id: 2 }); - comment = store.push('comment', { id: 1 }); - comment.set('post', post); - }); - run(function() { - comment.save().then(async(function(post) { - equal(passedUrl, "/posts/2/comments/1"); - })); - }); -}); - -test('buildURL - buildURL takes a record from delete', function() { - Comment.reopen({ post: DS.belongsTo('post') }); - Post.reopen({ comments: DS.hasMany('comment') }); - adapter.buildURL = function(type, id, snapshot) { - return 'posts/' + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; - }; - - ajaxResponse({ comments: [{ id: 1 }] }); - - var post, comment; - run(function() { - post = store.push('post', { id: 2 }); - comment = store.push('comment', { id: 1 }); - - comment.set('post', post); - comment.deleteRecord(); - }); - run(function() { - comment.save().then(async(function(post) { - equal(passedUrl, "posts/2/comments/1"); - })); - }); -}); - test('groupRecordsForFindMany groups records based on their url', function() { Comment.reopen({ post: DS.belongsTo('post') }); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); diff --git a/packages/ember-data/tests/unit/adapters/rest-adapter/path-for-type-test.js b/packages/ember-data/tests/unit/adapters/build-url-mixin/path-for-type-test.js similarity index 74% rename from packages/ember-data/tests/unit/adapters/rest-adapter/path-for-type-test.js rename to packages/ember-data/tests/unit/adapters/build-url-mixin/path-for-type-test.js index 092f12738c4..c2239fe5582 100644 --- a/packages/ember-data/tests/unit/adapters/rest-adapter/path-for-type-test.js +++ b/packages/ember-data/tests/unit/adapters/build-url-mixin/path-for-type-test.js @@ -1,8 +1,11 @@ var env, adapter; -module("unit/adapters/rest_adapter/path_for_type - DS.RESTAdapter#pathForType", { + +module("unit/adapters/build-url-mixin/path-for-type - DS.BuildURLMixin#pathForType", { setup: function() { + var Adapter = DS.Adapter.extend(DS.BuildURLMixin); + env = setupStore({ - adapter: DS.RESTAdapter + adapter: Adapter }); adapter = env.adapter;