waterline-schema
Version:
The core schema builder used in the Waterline ORM.
353 lines (307 loc) • 11.3 kB
JavaScript
var assert = require('assert');
var _ = require('@sailshq/lodash');
var SchemaBuilder = require('../lib/waterline-schema/schema');
var ForeignKeyMapper = require('../lib/waterline-schema/foreignKeys');
var JoinTableMapper = require('../lib/waterline-schema/joinTables');
describe('Join Table Mapper :: ', function() {
describe('Auto mapping of foreign keys', function() {
var schema;
before(function() {
var fixtures = [
{
identity: 'foo',
primaryKey: 'id',
connection: 'bar',
attributes: {
id: {
type: 'number'
},
bars: {
collection: 'bar',
via: 'foos',
dominant: true
}
}
},
{
identity: 'bar',
primaryKey: 'id',
connection: 'bar',
attributes: {
id: {
type: 'number'
},
foos: {
collection: 'foo',
via: 'bars'
}
}
}
];
var collections = _.map(fixtures, function(obj) {
var collection = function() {};
collection.prototype = obj;
return collection;
});
// Build the schema
schema = SchemaBuilder(collections);
ForeignKeyMapper(schema);
JoinTableMapper(schema);
});
it('should add a junction table for a many to many relationship', function() {
assert(schema.bar_foos__foo_bars);
assert.equal(schema.bar_foos__foo_bars.identity, 'bar_foos__foo_bars');
assert.equal(schema.bar_foos__foo_bars.junctionTable, true);
assert(schema.bar_foos__foo_bars.schema.foo_bars);
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.type, 'number');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.columnName, 'foo_bars');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.foreignKey, true);
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.references, 'foo');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.on, 'id');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.groupKey, 'foo');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.model, 'foo');
assert(schema.bar_foos__foo_bars.schema.bar_foos);
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.type, 'number');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.columnName, 'bar_foos');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.foreignKey, true);
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.references, 'bar');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.on, 'id');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.groupKey, 'bar');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.model, 'bar');
});
it('should update the parent collection to point to the join table', function() {
assert(schema.foo.schema.bars.references === 'bar_foos__foo_bars');
assert(schema.foo.schema.bars.on === 'foo_bars');
assert(schema.bar.schema.foos.references === 'bar_foos__foo_bars');
assert(schema.bar.schema.foos.on === 'bar_foos');
});
});
describe('mapping of custom foreign keys', function() {
var schema;
before(function() {
var fixtures = [
{
identity: 'foo',
connection: 'bar',
primaryKey: 'uuid',
attributes: {
uuid: {
type: 'string',
},
bars: {
collection: 'bar',
via: 'foos'
}
}
},
{
identity: 'bar',
connection: 'bar',
primaryKey: 'area',
attributes: {
area: {
type: 'number'
},
foos: {
collection: 'foo',
via: 'bars',
dominant: true
}
}
}
];
var collections = _.map(fixtures, function(obj) {
var collection = function() {};
collection.prototype = obj;
return collection;
});
// Build the schema
schema = SchemaBuilder(collections);
ForeignKeyMapper(schema);
JoinTableMapper(schema);
});
it('should add a junction table for a many to many relationship', function() {
assert(schema.bar_foos__foo_bars);
assert.equal(schema.bar_foos__foo_bars.identity, 'bar_foos__foo_bars');
assert.equal(schema.bar_foos__foo_bars.junctionTable, true);
assert(schema.bar_foos__foo_bars.schema.foo_bars);
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.type, 'string');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.columnName, 'foo_bars');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.foreignKey, true);
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.references, 'foo');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.on, 'uuid');
assert.equal(schema.bar_foos__foo_bars.schema.foo_bars.groupKey, 'foo');
assert(schema.bar_foos__foo_bars.schema.bar_foos);
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.type, 'number');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.columnName, 'bar_foos');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.foreignKey, true);
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.references, 'bar');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.on, 'area');
assert.equal(schema.bar_foos__foo_bars.schema.bar_foos.groupKey, 'bar');
});
});
describe('mapping of custom foreign keys with the wrong `via` value', function() {
var schema;
before(function() {
var fixtures = [
{
identity: 'foo',
connection: 'bar',
primaryKey: 'uuid',
attributes: {
uuid: {
type: 'string'
},
bars: {
collection: 'bar',
via: 'foos'
}
}
},
{
identity: 'bar',
connection: 'bar',
primaryKey: 'area',
attributes: {
area: {
type: 'number'
},
foos: {
collection: 'foo',
via: 'fake',
dominant: true
}
}
}
];
var collections = _.map(fixtures, function(obj) {
var collection = function() {};
collection.prototype = obj;
return collection;
});
// Build the schema
schema = SchemaBuilder(collections);
ForeignKeyMapper(schema);
});
it('should throw an exception message', function() {
assert.throws(function() {
JoinTableMapper(schema);
});
});
});
describe('self-referencing associations', function() {
var schema;
before(function() {
var fixtures = [
{
identity: 'foo',
connection: 'bar',
primaryKey: 'id',
attributes: {
id: {
type: 'number'
},
isFollowing: {
collection: 'foo',
via: 'followedBy'
},
followedBy: {
collection: 'foo',
via: 'isFollowing'
}
}
}
];
var collections = _.map(fixtures, function(obj) {
var collection = function() {};
collection.prototype = obj;
return collection;
});
// Build the schema
schema = SchemaBuilder(collections);
ForeignKeyMapper(schema);
JoinTableMapper(schema);
});
it('should add a junction table for the self referencing attributes', function() {
// Validate only a single join table gets setup
assert(schema.foo_followedby__foo_isfollowing);
assert(!schema.foo_isfollowing__foo_followeby);
assert(schema.foo_followedby__foo_isfollowing.schema.foo_isFollowing);
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_isFollowing.type, 'number');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_isFollowing.columnName, 'foo_isFollowing');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_isFollowing.foreignKey, true);
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_isFollowing.references, 'foo');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_isFollowing.on, 'id');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_isFollowing.groupKey, 'foo');
assert(schema.foo_followedby__foo_isfollowing.schema.foo_followedBy);
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_followedBy.type, 'number');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_followedBy.columnName, 'foo_followedBy');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_followedBy.foreignKey, true);
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_followedBy.references, 'foo');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_followedBy.on, 'id');
assert.equal(schema.foo_followedby__foo_isfollowing.schema.foo_followedBy.groupKey, 'foo');
assert.equal(schema.foo.schema.isFollowing.references, 'foo_followedBy__foo_isFollowing');
assert.equal(schema.foo.schema.isFollowing.on, 'foo_isFollowing');
assert.equal(schema.foo.schema.followedBy.references, 'foo_followedBy__foo_isFollowing');
assert.equal(schema.foo.schema.followedBy.on, 'foo_followedBy');
});
});
describe('junction table between the same model', function() {
var schema;
before(function() {
var fixtures = [
{
identity: 'foo',
connection: 'foo',
primaryKey: 'id',
attributes: {
id: {
type: 'number'
},
follows: {
collection: 'foo',
through: 'bar',
via: 'to'
},
followers: {
collection: 'foo',
through: 'bar',
via: 'from'
}
}
},
{
identity: 'bar',
connection: 'foo',
primaryKey: 'id',
attributes: {
id: {
type: 'number'
},
to: {
model: 'foo'
},
from: {
model: 'foo'
}
}
}
];
var collections = _.map(fixtures, function(obj) {
var collection = function() {};
collection.prototype = obj;
return collection;
});
// Build the schema
schema = SchemaBuilder(collections);
ForeignKeyMapper(schema);
JoinTableMapper(schema);
});
it('should expand the attributes on `bar`', function() {
assert.equal(schema.foo.schema.follows.onKey, 'to');
assert.equal(schema.foo.schema.follows.on, 'to');
assert.equal(schema.foo.schema.followers.onKey, 'from');
assert.equal(schema.foo.schema.followers.on, 'from');
});
});
});