<NME> hasManyThroughUpsert.test.js
<BEF> var request = require('supertest')
var loopback = require('loopback')
var expect = require('chai').expect
var loopback = require('loopback')
var expect = require('chai').expect
var JSONAPIComponent = require('../')
var RSVP = require('rsvp')

var app
var Movie, Category, MovieCategory

describe('hasManyThrough upsert', function () {
  beforeEach(function (done) {
    var ds = loopback.createDataSource('memory')
    // create models
    Movie = ds.createModel('movie', {
      id: {type: Number, id: true},
      name: String
    })

    Category = ds.createModel('category', {
      id: {type: Number, id: true},
      name: String
    })

    MovieCategoryAssoc = ds.createModel('movieCategoryAssoc', {
      id: {type: Number, id: true}
    })

    // add models

    // add models
    app.model(Movie)
    app.model(Category)
    app.model(MovieCategory)

    // set up relationships

    MovieCategoryAssoc.belongsTo(Movie)
    MovieCategoryAssoc.belongsTo(Category)
    makeData().then(function () {
      done()
    }).catch(function (err) {
      done(err)
    })
    app.use(loopback.rest())
    JSONAPIComponent(app, {restApiRoot: ''})
  })

  it('should make initial data', function (done) {

    request(app)
      .get('/movies/1/categories')
      .end(function (err, res) {
        expect(err).to.equal(null)
        expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(2)
        expect(res).to.have.deep.property('body.data[0]').and.have.property('attributes.name').and.equal('Crime')
        done(err)
      })
  })

  it('should handle POST', function (done) {

    agent
      .post('/movies')
      .send({
        'data': {
          'type': 'movies',
          'attributes': {
            'name': 'Ace Ventura: Pet Detective'
          },
          'relationships': {
            'categories': {
              'data': [
                {'type': 'categories', 'id': 4}
              ]
            }
          }
        }
      }).end(function () {
        agent.get('/movieCategoryAssocs').end(function (err, res) {
          expect(err).to.equal(null)
          expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(3)
          done()
        })
      })
        })
      })
  })

    agent
      .patch('/movies/1')
      .send({
        'data': {
          'id': 1,
          'type': 'movies',
          'attributes': {
            'name': 'The Shawshank Redemption'
          },
          'relationships': {
            'categories': {
              'data': [
                {'type': 'categories', 'id': 1},
                {'type': 'categories', 'id': 2},
                {'type': 'categories', 'id': 3}
              ]
            }
          }
        }
      }).end(function () {
        agent.get('/movieCategoryAssocs').end(function (err, res) {
          expect(err).to.equal(null)
          expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(3)
          done()
        })
      })
  })

  it('should handle string IDs', function(done){
    var agent = request(app)
    agent
      .patch('/movies/1')
      .send({
        "data": {
          "id": '1',
          "type": "movies",
          "attributes": {
            "name": "The Shawshank Redemption"
          },
          "relationships": {
            "categories": {
              "data": [
                {"type": "categories", "id": '1'},
                {"type": "categories", "id": '4'}
              ]
            }
          }
        }
      }).end(function(){
        agent.get('/movieCategoryAssocs/1').end(function(err, res){
          expect(err).to.equal(null)
          expect(res).to.have.deep.property('body.data').and.have.property('id').and.equal('1')
          done()
        })
      })
        expect(res.body.data[1].id).to.equal('4')
      })
    })
  })
    agent
      .patch('/movies/1')
      .send({
        'data': {
          'id': 1,
          'type': 'movies',
          'attributes': {
            'name': 'The Shawshank Redemption'
          },
          'relationships': {
            'categories': {
              'data': [
                {'type': 'categories', 'id': 1},
                {'type': 'categories', 'id': 4}
              ]
            }
          }
        }
      }).end(function (err, res) {
        expect(err).to.equal(null)
        agent.get('/movieCategoryAssocs').end(function (err, res) {
          expect(err).to.equal(null)
          expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(2)

          agent.get('/movies/1/categories').end(function (err, res) {
            expect(err).to.equal(null)
            expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(2)
            expect(res).to.have.deep.property('body.data[1].attributes.name').and.equal('Comedy')
            done()
          })
        })
            expect(err).to.equal(null)
            expect(res.body.data.length).to.equal(2)
            expect(res.body.data[1].attributes.name).to.equal('Comedy')
            done()
          })
        })
      })
  var createAssoc = denodeifyCreate(MovieCategoryAssoc)

  return RSVP.hash({
    movie: createMovie({name: 'The Shawshank Redemption'}),
    categories: RSVP.all([
      createCategory({ name: 'Crime' }),
      createCategory({ name: 'Drama' }),
      createCategory({ name: 'History' }),
      createCategory({ name: 'Comedy' })
    ])
  })
    .then(function (models) {
      return RSVP.all([
        createAssoc({ movieId: models.movie.id, categoryId: models.categories[0].id }),
        createAssoc({ movieId: models.movie.id, categoryId: models.categories[2].id })
      ])
    })

  function denodeifyCreate (Model) {
    return RSVP.denodeify(Model.create.bind(Model))
        createAssoc({
          movieId: models.movie.id,
          categoryId: models.categories[0].id
        }),
        createAssoc({
          movieId: models.movie.id,
          categoryId: models.categories[2].id
        })
      ])
    })

  function denodeifyCreate (Model) {
    return RSVP.denodeify(Model.create.bind(Model))
  }
}

<MSG> fix(tests): Fix broken tests after rebase

<DFF> @@ -1,3 +1,5 @@
+/* global describe, beforeEach, it */
+
 var request = require('supertest')
 var loopback = require('loopback')
 var expect = require('chai').expect
@@ -14,17 +16,17 @@ describe('hasManyThrough upsert', function () {
     var ds = loopback.createDataSource('memory')
     // create models
     Movie = ds.createModel('movie', {
-      id: {type: Number, id: true},
+      id: { type: Number, id: true },
       name: String
     })
 
     Category = ds.createModel('category', {
-      id: {type: Number, id: true},
+      id: { type: Number, id: true },
       name: String
     })
 
     MovieCategoryAssoc = ds.createModel('movieCategoryAssoc', {
-      id: {type: Number, id: true}
+      id: { type: Number, id: true }
     })
 
     // add models
@@ -38,25 +40,24 @@ describe('hasManyThrough upsert', function () {
 
     MovieCategoryAssoc.belongsTo(Movie)
     MovieCategoryAssoc.belongsTo(Category)
-    makeData().then(function () {
-      done()
-    }).catch(function (err) {
-      done(err)
-    })
+    makeData()
+      .then(function () {
+        done()
+      })
+      .catch(function (err) {
+        done(err)
+      })
     app.use(loopback.rest())
-    JSONAPIComponent(app, {restApiRoot: ''})
+    JSONAPIComponent(app, { restApiRoot: '' })
   })
 
   it('should make initial data', function (done) {
-
-    request(app)
-      .get('/movies/1/categories')
-      .end(function (err, res) {
-        expect(err).to.equal(null)
-        expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(2)
-        expect(res).to.have.deep.property('body.data[0]').and.have.property('attributes.name').and.equal('Crime')
-        done(err)
-      })
+    request(app).get('/movies/1/categories').end(function (err, res) {
+      expect(err).to.equal(null)
+      expect(res.body.data.length).to.equal(2)
+      expect(res.body.data[0].attributes.name).to.equal('Crime')
+      done(err)
+    })
   })
 
   it('should handle POST', function (done) {
@@ -64,23 +65,22 @@ describe('hasManyThrough upsert', function () {
     agent
       .post('/movies')
       .send({
-        'data': {
-          'type': 'movies',
-          'attributes': {
-            'name': 'Ace Ventura: Pet Detective'
+        data: {
+          type: 'movies',
+          attributes: {
+            name: 'Ace Ventura: Pet Detective'
           },
-          'relationships': {
-            'categories': {
-              'data': [
-                {'type': 'categories', 'id': 4}
-              ]
+          relationships: {
+            categories: {
+              data: [{ type: 'categories', id: 4 }]
             }
           }
         }
-      }).end(function () {
+      })
+      .end(function () {
         agent.get('/movieCategoryAssocs').end(function (err, res) {
           expect(err).to.equal(null)
-          expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(3)
+          expect(res.body.data.length).to.equal(3)
           done()
         })
       })
@@ -91,55 +91,54 @@ describe('hasManyThrough upsert', function () {
     agent
       .patch('/movies/1')
       .send({
-        'data': {
-          'id': 1,
-          'type': 'movies',
-          'attributes': {
-            'name': 'The Shawshank Redemption'
+        data: {
+          id: 1,
+          type: 'movies',
+          attributes: {
+            name: 'The Shawshank Redemption'
           },
-          'relationships': {
-            'categories': {
-              'data': [
-                {'type': 'categories', 'id': 1},
-                {'type': 'categories', 'id': 2},
-                {'type': 'categories', 'id': 3}
+          relationships: {
+            categories: {
+              data: [
+                { type: 'categories', id: 1 },
+                { type: 'categories', id: 2 },
+                { type: 'categories', id: 3 }
               ]
             }
           }
         }
-      }).end(function () {
+      })
+      .end(function () {
         agent.get('/movieCategoryAssocs').end(function (err, res) {
           expect(err).to.equal(null)
-          expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(3)
+          expect(res.body.data.length).to.equal(3)
           done()
         })
       })
   })
 
-  it('should handle string IDs', function(done){
+  it('should handle string IDs', function (done) {
     var agent = request(app)
     agent
       .patch('/movies/1')
       .send({
-        "data": {
-          "id": '1',
-          "type": "movies",
-          "attributes": {
-            "name": "The Shawshank Redemption"
+        data: {
+          id: '1',
+          type: 'movies',
+          attributes: {
+            name: 'The Shawshank Redemption'
           },
-          "relationships": {
-            "categories": {
-              "data": [
-                {"type": "categories", "id": '1'},
-                {"type": "categories", "id": '4'}
-              ]
+          relationships: {
+            categories: {
+              data: [{ type: 'categories', id: '1' }, { type: 'categories', id: '4' }]
             }
           }
         }
-      }).end(function(){
-        agent.get('/movieCategoryAssocs/1').end(function(err, res){
+      })
+      .end(function () {
+        agent.get('/movieCategoryAssocs/1').end(function (err, res) {
           expect(err).to.equal(null)
-          expect(res).to.have.deep.property('body.data').and.have.property('id').and.equal('1')
+          expect(res.body.data.id).to.equal('1')
           done()
         })
       })
@@ -150,31 +149,29 @@ describe('hasManyThrough upsert', function () {
     agent
       .patch('/movies/1')
       .send({
-        'data': {
-          'id': 1,
-          'type': 'movies',
-          'attributes': {
-            'name': 'The Shawshank Redemption'
+        data: {
+          id: 1,
+          type: 'movies',
+          attributes: {
+            name: 'The Shawshank Redemption'
           },
-          'relationships': {
-            'categories': {
-              'data': [
-                {'type': 'categories', 'id': 1},
-                {'type': 'categories', 'id': 4}
-              ]
+          relationships: {
+            categories: {
+              data: [{ type: 'categories', id: 1 }, { type: 'categories', id: 4 }]
             }
           }
         }
-      }).end(function (err, res) {
+      })
+      .end(function (err, res) {
         expect(err).to.equal(null)
         agent.get('/movieCategoryAssocs').end(function (err, res) {
           expect(err).to.equal(null)
-          expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(2)
+          expect(res.body.data.length).to.equal(2)
 
           agent.get('/movies/1/categories').end(function (err, res) {
             expect(err).to.equal(null)
-            expect(res).to.have.deep.property('body.data').and.have.property('length').and.equal(2)
-            expect(res).to.have.deep.property('body.data[1].attributes.name').and.equal('Comedy')
+            expect(res.body.data.length).to.equal(2)
+            expect(res.body.data[1].attributes.name).to.equal('Comedy')
             done()
           })
         })
@@ -188,20 +185,19 @@ function makeData () {
   var createAssoc = denodeifyCreate(MovieCategoryAssoc)
 
   return RSVP.hash({
-    movie: createMovie({name: 'The Shawshank Redemption'}),
+    movie: createMovie({ name: 'The Shawshank Redemption' }),
     categories: RSVP.all([
       createCategory({ name: 'Crime' }),
       createCategory({ name: 'Drama' }),
       createCategory({ name: 'History' }),
       createCategory({ name: 'Comedy' })
     ])
+  }).then(function (models) {
+    return RSVP.all([
+      createAssoc({ movieId: models.movie.id, categoryId: models.categories[0].id }),
+      createAssoc({ movieId: models.movie.id, categoryId: models.categories[2].id })
+    ])
   })
-    .then(function (models) {
-      return RSVP.all([
-        createAssoc({ movieId: models.movie.id, categoryId: models.categories[0].id }),
-        createAssoc({ movieId: models.movie.id, categoryId: models.categories[2].id })
-      ])
-    })
 
   function denodeifyCreate (Model) {
     return RSVP.denodeify(Model.create.bind(Model))

fix(tests): Fix broken tests after rebase