diff --git a/test/relations.integration.js b/test/relations.integration.js index 8c0766af..70f1ae12 100644 --- a/test/relations.integration.js +++ b/test/relations.integration.js @@ -27,6 +27,108 @@ describe('relations - integration', function() { this.app.models.widget.destroyAll(done); }); + describe('polymorphicHasMany', function() { + + before(function defineProductAndCategoryModels() { + var Team = app.model( + 'Team', + { properties: { name: 'string' }, + dataSource: 'db' + } + ); + var Reader = app.model( + 'Reader', + { properties: { name: 'string' }, + dataSource: 'db' + } + ); + var Picture = app.model( + 'Picture', + { properties: { name: 'string', imageableId: 'number', imageableType: 'string'}, + dataSource: 'db' + } + ); + + Reader.hasMany(Picture, { polymorphic: { // alternative syntax + as: 'imageable', // if not set, default to: reference + foreignKey: 'imageableId', // defaults to 'as + Id' + discriminator: 'imageableType' // defaults to 'as + Type' + } }); + + Picture.belongsTo('imageable', { polymorphic: { + foreignKey: 'imageableId', + discriminator: 'imageableType' + } }); + + Reader.belongsTo(Team); + }); + + before(function createEvent(done) { + var test = this; + app.models.Team.create({ name: 'Team 1' }, + function(err, team) { + if (err) return done(err); + test.team = team; + app.models.Reader.create({ name: 'Reader 1' }, + function(err, reader) { + if (err) return done(err); + test.reader = reader; + reader.pictures.create({ name: 'Picture 1' }); + reader.pictures.create({ name: 'Picture 2' }); + reader.team(test.team); + reader.save(done); + }); + } + ); + }); + + after(function(done) { + this.app.models.Reader.destroyAll(done); + }); + + it('includes the related child model', function(done) { + var url = '/api/readers/' + this.reader.id; + this.get(url) + .query({'filter': {'include' : 'pictures'}}) + .expect(200, function(err, res) { + // console.log(res.body); + expect(res.body.name).to.be.equal('Reader 1'); + expect(res.body.pictures).to.be.eql([ + { name: 'Picture 1', id: 1, imageableId: 1, imageableType: 'Reader'}, + { name: 'Picture 2', id: 2, imageableId: 1, imageableType: 'Reader'}, + ]); + done(); + }); + }); + + it('includes the related parent model', function(done) { + var url = '/api/pictures'; + this.get(url) + .query({'filter': {'include' : 'imageable'}}) + .expect(200, function(err, res) { + // console.log(res.body); + expect(res.body[0].name).to.be.equal('Picture 1'); + expect(res.body[1].name).to.be.equal('Picture 2'); + expect(res.body[0].imageable).to.be.eql({ name: 'Reader 1', id: 1, teamId: 1}); + done(); + }); + }); + + it('includes related models scoped to the related parent model', function(done) { + var url = '/api/pictures'; + this.get(url) + .query({'filter': {'include' : {'relation': 'imageable', 'scope': { 'include' : 'team'}}}}) + .expect(200, function(err, res) { + expect(res.body[0].name).to.be.equal('Picture 1'); + expect(res.body[1].name).to.be.equal('Picture 2'); + expect(res.body[0].imageable.name).to.be.eql('Reader 1'); + expect(res.body[0].imageable.team).to.be.eql({ name: 'Team 1', id: 1}); + done(); + }); + }); + + }); + describe('/store/superStores', function() { it('should invoke scoped methods remotely', function(done) { this.get('/api/stores/superStores')