123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245 |
- 'use strict';
- const upperFirst = require('lodash/upperFirst');
- const chai = require('chai');
- const expect = chai.expect;
- const Support = require('../support');
- const { DataTypes, Op } = require('@sequelize/core');
- const dialect = Support.sequelize.dialect;
- const promiseProps = require('p-props');
- const sortById = function (a, b) {
- return a.id < b.id ? -1 : 1;
- };
- describe(Support.getTestDialectTeaser('Includes with schemas'), () => {
- if (!dialect.supports.schemas) {
- return;
- }
- describe('findAll', () => {
- beforeEach(async function () {
- this.fixtureA = async function () {
- await this.sequelize.dropSchema('account');
- await this.sequelize.createSchema('account');
- const AccUser = this.sequelize.define('AccUser', {}, { schema: 'account' });
- const Company = this.sequelize.define(
- 'Company',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Product = this.sequelize.define(
- 'Product',
- {
- title: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Tag = this.sequelize.define(
- 'Tag',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Price = this.sequelize.define(
- 'Price',
- {
- value: DataTypes.FLOAT,
- },
- { schema: 'account' },
- );
- const Customer = this.sequelize.define(
- 'Customer',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const GroupMember = this.sequelize.define('GroupMember', {}, { schema: 'account' });
- const Rank = this.sequelize.define(
- 'Rank',
- {
- name: DataTypes.STRING,
- canInvite: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- canRemove: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- canPost: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- },
- { schema: 'account' },
- );
- this.models = {
- AccUser,
- Company,
- Product,
- Tag,
- Price,
- Customer,
- Group,
- GroupMember,
- Rank,
- };
- AccUser.hasMany(Product);
- Product.belongsTo(AccUser);
- Product.belongsToMany(Tag, { through: 'product_tag' });
- Tag.belongsToMany(Product, { through: 'product_tag' });
- Product.belongsTo(Tag, { as: 'Category' });
- Product.belongsTo(Company);
- Product.hasMany(Price);
- Price.belongsTo(Product);
- AccUser.hasMany(GroupMember, { as: 'Memberships' });
- GroupMember.belongsTo(AccUser);
- GroupMember.belongsTo(Rank);
- GroupMember.belongsTo(Group);
- Group.hasMany(GroupMember, { as: 'Memberships' });
- await this.sequelize.sync({ force: true });
- const [groups, companies, ranks, tags] = await Promise.all([
- Group.bulkCreate([
- { name: 'Developers' },
- { name: 'Designers' },
- { name: 'Managers' },
- ]).then(() => Group.findAll()),
- Company.bulkCreate([
- { name: 'Sequelize' },
- { name: 'Coca Cola' },
- { name: 'Bonanza' },
- { name: 'NYSE' },
- { name: 'Coshopr' },
- ]).then(() => Company.findAll()),
- Rank.bulkCreate([
- { name: 'Admin', canInvite: 1, canRemove: 1, canPost: 1 },
- { name: 'Trustee', canInvite: 1, canRemove: 0, canPost: 1 },
- { name: 'Member', canInvite: 1, canRemove: 0, canPost: 0 },
- ]).then(() => Rank.findAll()),
- Tag.bulkCreate([
- { name: 'A' },
- { name: 'B' },
- { name: 'C' },
- { name: 'D' },
- { name: 'E' },
- ]).then(() => Tag.findAll()),
- ]);
- for (const i of [0, 1, 2, 3, 4]) {
- const [user, products] = await Promise.all([
- AccUser.create(),
- Product.bulkCreate([
- { title: 'Chair' },
- { title: 'Desk' },
- { title: 'Bed' },
- { title: 'Pen' },
- { title: 'Monitor' },
- ]).then(() => Product.findAll()),
- ]);
- const groupMembers = [
- { accUserId: user.id, GroupId: groups[0].id, rankId: ranks[0].id },
- { accUserId: user.id, GroupId: groups[1].id, rankId: ranks[2].id },
- ];
- if (i < 3) {
- groupMembers.push({ accUserId: user.id, GroupId: groups[2].id, rankId: ranks[1].id });
- }
- await Promise.all([
- GroupMember.bulkCreate(groupMembers),
- user.setProducts([products[i * 5 + 0], products[i * 5 + 1], products[i * 5 + 3]]),
- products[i * 5 + 0].setTags([tags[0], tags[2]]),
- products[i * 5 + 1].setTags([tags[1]]),
- products[i * 5 + 0].setCategory(tags[1]),
- products[i * 5 + 2].setTags([tags[0]]),
- products[i * 5 + 3].setTags([tags[0]]),
- products[i * 5 + 0].setCompany(companies[4]),
- products[i * 5 + 1].setCompany(companies[3]),
- products[i * 5 + 2].setCompany(companies[2]),
- products[i * 5 + 3].setCompany(companies[1]),
- products[i * 5 + 4].setCompany(companies[0]),
- Price.bulkCreate([
- { productId: products[i * 5 + 0].id, value: 5 },
- { productId: products[i * 5 + 0].id, value: 10 },
- { productId: products[i * 5 + 1].id, value: 5 },
- { productId: products[i * 5 + 1].id, value: 10 },
- { productId: products[i * 5 + 1].id, value: 15 },
- { productId: products[i * 5 + 1].id, value: 20 },
- { productId: products[i * 5 + 2].id, value: 20 },
- { productId: products[i * 5 + 3].id, value: 20 },
- ]),
- ]);
- }
- };
- await this.sequelize.createSchema('account');
- });
- it('should support an include with multiple different association types', async function () {
- await this.sequelize.dropSchema('account');
- await this.sequelize.createSchema('account');
- const AccUser = this.sequelize.define('AccUser', {}, { schema: 'account' });
- const Product = this.sequelize.define(
- 'Product',
- {
- title: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Tag = this.sequelize.define(
- 'Tag',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Price = this.sequelize.define(
- 'Price',
- {
- value: DataTypes.FLOAT,
- },
- { schema: 'account' },
- );
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const GroupMember = this.sequelize.define('GroupMember', {}, { schema: 'account' });
- const Rank = this.sequelize.define(
- 'Rank',
- {
- name: DataTypes.STRING,
- canInvite: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- canRemove: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- },
- { schema: 'account' },
- );
- AccUser.hasMany(Product);
- Product.belongsTo(AccUser);
- Product.belongsToMany(Tag, { through: 'product_tag' });
- Tag.belongsToMany(Product, { through: 'product_tag' });
- Product.belongsTo(Tag, { as: 'Category' });
- Product.hasMany(Price);
- Price.belongsTo(Product);
- AccUser.hasMany(GroupMember, { as: 'Memberships' });
- GroupMember.belongsTo(AccUser);
- GroupMember.belongsTo(Rank);
- GroupMember.belongsTo(Group);
- Group.hasMany(GroupMember, { as: 'Memberships' });
- await this.sequelize.sync({ force: true });
- const [groups, ranks, tags] = await Promise.all([
- Group.bulkCreate([{ name: 'Developers' }, { name: 'Designers' }]).then(() =>
- Group.findAll(),
- ),
- Rank.bulkCreate([
- { name: 'Admin', canInvite: 1, canRemove: 1 },
- { name: 'Member', canInvite: 1, canRemove: 0 },
- ]).then(() => Rank.findAll()),
- Tag.bulkCreate([{ name: 'A' }, { name: 'B' }, { name: 'C' }]).then(() => Tag.findAll()),
- ]);
- for (const i of [0, 1, 2, 3, 4]) {
- const [user, products] = await Promise.all([
- AccUser.create(),
- Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()),
- ]);
- await Promise.all([
- GroupMember.bulkCreate([
- { accUserId: user.id, groupId: groups[0].id, rankId: ranks[0].id },
- { accUserId: user.id, groupId: groups[1].id, rankId: ranks[1].id },
- ]),
- user.setProducts([products[i * 2 + 0], products[i * 2 + 1]]),
- products[i * 2 + 0].setTags([tags[0], tags[2]]),
- products[i * 2 + 1].setTags([tags[1]]),
- products[i * 2 + 0].setCategory(tags[1]),
- Price.bulkCreate([
- { productId: products[i * 2 + 0].id, value: 5 },
- { productId: products[i * 2 + 0].id, value: 10 },
- { productId: products[i * 2 + 1].id, value: 5 },
- { productId: products[i * 2 + 1].id, value: 10 },
- { productId: products[i * 2 + 1].id, value: 15 },
- { productId: products[i * 2 + 1].id, value: 20 },
- ]),
- ]);
- const users = await AccUser.findAll({
- include: [
- {
- model: GroupMember,
- as: 'Memberships',
- include: [Group, Rank],
- },
- {
- model: Product,
- include: ['tags', { model: Tag, as: 'Category' }, Price],
- },
- ],
- order: [[AccUser.getAttributes().id, 'ASC']],
- });
- for (const user of users) {
- expect(user.Memberships).to.be.ok;
- user.Memberships.sort(sortById);
- expect(user.Memberships.length).to.equal(2);
- expect(user.Memberships[0].group.name).to.equal('Developers');
- expect(user.Memberships[0].rank.canRemove).to.equal(1);
- expect(user.Memberships[1].group.name).to.equal('Designers');
- expect(user.Memberships[1].rank.canRemove).to.equal(0);
- user.products.sort(sortById);
- expect(user.products.length).to.equal(2);
- expect(user.products[0].tags.length).to.equal(2);
- expect(user.products[1].tags.length).to.equal(1);
- expect(user.products[0].Category).to.be.ok;
- expect(user.products[1].Category).not.to.be.ok;
- expect(user.products[0].prices.length).to.equal(2);
- expect(user.products[1].prices.length).to.equal(4);
- }
- }
- });
- it('should support many levels of belongsTo', async function () {
- const A = this.sequelize.define('a', {}, { schema: 'account' });
- const B = this.sequelize.define('b', {}, { schema: 'account' });
- const C = this.sequelize.define('c', {}, { schema: 'account' });
- const D = this.sequelize.define('d', {}, { schema: 'account' });
- const E = this.sequelize.define('e', {}, { schema: 'account' });
- const F = this.sequelize.define('f', {}, { schema: 'account' });
- const G = this.sequelize.define('g', {}, { schema: 'account' });
- const H = this.sequelize.define('h', {}, { schema: 'account' });
- A.belongsTo(B);
- B.belongsTo(C);
- C.belongsTo(D);
- D.belongsTo(E);
- E.belongsTo(F);
- F.belongsTo(G);
- G.belongsTo(H);
- let b;
- const singles = [B, C, D, E, F, G, H];
- await this.sequelize.sync();
- await A.bulkCreate([{}, {}, {}, {}, {}, {}, {}, {}]);
- let previousInstance;
- for (const model of singles) {
- const instance = await model.create({});
- if (previousInstance) {
- await previousInstance[`set${upperFirst(model.name)}`](instance);
- previousInstance = instance;
- continue;
- }
- previousInstance = b = instance;
- }
- let as = await A.findAll();
- await Promise.all(as.map(a => a.setB(b)));
- as = await A.findAll({
- include: [
- {
- model: B,
- include: [
- {
- model: C,
- include: [
- {
- model: D,
- include: [
- {
- model: E,
- include: [
- {
- model: F,
- include: [
- {
- model: G,
- include: [{ model: H }],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- });
- expect(as.length).to.be.ok;
- for (const a of as) {
- expect(a.b.c.d.e.f.g.h).to.be.ok;
- }
- });
- it('should support ordering with only belongsTo includes', async function () {
- const User = this.sequelize.define('SpecialUser', {}, { schema: 'account' });
- const Item = this.sequelize.define('Item', { test: DataTypes.STRING }, { schema: 'account' });
- const Order = this.sequelize.define(
- 'Order',
- { position: DataTypes.INTEGER },
- { schema: 'account' },
- );
- User.belongsTo(Item, { as: 'itemA', foreignKey: 'itemA_id' });
- User.belongsTo(Item, { as: 'itemB', foreignKey: 'itemB_id' });
- User.belongsTo(Order);
- await this.sequelize.sync();
- await Promise.all([
- User.bulkCreate([{}, {}, {}]),
- Item.bulkCreate([{ test: 'abc' }, { test: 'def' }, { test: 'ghi' }, { test: 'jkl' }]),
- Order.bulkCreate([{ position: 2 }, { position: 3 }, { position: 1 }]),
- ]);
- const [users, items, orders] = await Promise.all([
- User.findAll(),
- Item.findAll({ order: ['id'] }),
- Order.findAll({ order: ['id'] }),
- ]);
- await Promise.all([
- users[0].setItemA(items[0]),
- users[0].setItemB(items[1]),
- users[0].setOrder(orders[2]),
- users[1].setItemA(items[2]),
- users[1].setItemB(items[3]),
- users[1].setOrder(orders[1]),
- users[2].setItemA(items[0]),
- users[2].setItemB(items[3]),
- users[2].setOrder(orders[0]),
- ]);
- const as = await User.findAll({
- include: [
- { model: Item, as: 'itemA', where: { test: 'abc' } },
- { model: Item, as: 'itemB' },
- Order,
- ],
- order: [[Order, 'position']],
- });
- expect(as.length).to.eql(2);
- expect(as[0].itemA.test).to.eql('abc');
- expect(as[1].itemA.test).to.eql('abc');
- expect(as[0].order.position).to.eql(1);
- expect(as[1].order.position).to.eql(2);
- });
- it('should include attributes from through models', async function () {
- const Product = this.sequelize.define(
- 'Product',
- {
- title: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Tag = this.sequelize.define(
- 'Tag',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const ProductTag = this.sequelize.define(
- 'ProductTag',
- {
- priority: DataTypes.INTEGER,
- },
- { schema: 'account' },
- );
- Product.belongsToMany(Tag, { through: ProductTag });
- Tag.belongsToMany(Product, { through: ProductTag });
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }, { title: 'Dress' }]),
- Tag.bulkCreate([{ name: 'A' }, { name: 'B' }, { name: 'C' }]),
- ]);
- const [products0, tags] = await Promise.all([Product.findAll(), Tag.findAll()]);
- await Promise.all([
- products0[0].addTag(tags[0], { through: { priority: 1 } }),
- products0[0].addTag(tags[1], { through: { priority: 2 } }),
- products0[1].addTag(tags[1], { through: { priority: 1 } }),
- products0[2].addTag(tags[0], { through: { priority: 3 } }),
- products0[2].addTag(tags[1], { through: { priority: 1 } }),
- products0[2].addTag(tags[2], { through: { priority: 2 } }),
- ]);
- const products = await Product.findAll({
- include: [{ model: Tag }],
- order: [
- ['id', 'ASC'],
- [Tag, 'id', 'ASC'],
- ],
- });
- expect(products[0].tags[0].ProductTag.priority).to.equal(1);
- expect(products[0].tags[1].ProductTag.priority).to.equal(2);
- expect(products[1].tags[0].ProductTag.priority).to.equal(1);
- expect(products[2].tags[0].ProductTag.priority).to.equal(3);
- expect(products[2].tags[1].ProductTag.priority).to.equal(1);
- expect(products[2].tags[2].ProductTag.priority).to.equal(2);
- });
- it('should support a required belongsTo include', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Group = this.sequelize.define('Group', {}, { schema: 'account' });
- User.belongsTo(Group);
- await this.sequelize.sync({ force: true });
- await Promise.all([Group.bulkCreate([{}, {}]), User.bulkCreate([{}, {}, {}])]);
- const [groups, users0] = await Promise.all([Group.findAll(), User.findAll()]);
- await users0[2].setGroup(groups[1]);
- const users = await User.findAll({
- include: [{ model: Group, required: true }],
- });
- expect(users.length).to.equal(1);
- expect(users[0].group).to.be.ok;
- });
- it('should be possible to extend the on clause with a where option on a belongsTo include', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- User.belongsTo(Group);
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Group.bulkCreate([{ name: 'A' }, { name: 'B' }]),
- User.bulkCreate([{}, {}]),
- ]);
- const [groups, users0] = await Promise.all([Group.findAll(), User.findAll()]);
- await Promise.all([users0[0].setGroup(groups[1]), users0[1].setGroup(groups[0])]);
- const users = await User.findAll({
- include: [{ model: Group, where: { name: 'A' } }],
- });
- expect(users.length).to.equal(1);
- expect(users[0].group).to.be.ok;
- expect(users[0].group.name).to.equal('A');
- });
- it('should be possible to extend the on clause with a where option on a belongsTo include', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- User.belongsTo(Group);
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Group.bulkCreate([{ name: 'A' }, { name: 'B' }]),
- User.bulkCreate([{}, {}]),
- ]);
- const [groups, users0] = await Promise.all([Group.findAll(), User.findAll()]);
- await Promise.all([users0[0].setGroup(groups[1]), users0[1].setGroup(groups[0])]);
- const users = await User.findAll({
- include: [{ model: Group, required: true }],
- });
- for (const user of users) {
- expect(user.group).to.be.ok;
- }
- });
- it('should be possible to define a belongsTo include as required with child hasMany with limit', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Category = this.sequelize.define(
- 'Category',
- {
- category: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- User.belongsTo(Group);
- Group.hasMany(Category);
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Group.bulkCreate([{ name: 'A' }, { name: 'B' }]),
- User.bulkCreate([{}, {}]),
- Category.bulkCreate([{}, {}]),
- ]);
- const [groups, users0, categories] = await Promise.all([
- Group.findAll(),
- User.findAll(),
- Category.findAll(),
- ]);
- const promises = [users0[0].setGroup(groups[1]), users0[1].setGroup(groups[0])];
- for (const group of groups) {
- promises.push(group.setCategories(categories));
- }
- await Promise.all(promises);
- const users = await User.findAll({
- include: [
- {
- model: Group,
- required: true,
- include: [{ model: Category }],
- },
- ],
- limit: 1,
- });
- expect(users.length).to.equal(1);
- for (const user of users) {
- expect(user.group).to.be.ok;
- expect(user.group.categories).to.be.ok;
- }
- });
- it('should be possible to define a belongsTo include as required with child hasMany with limit and aliases', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Category = this.sequelize.define(
- 'Category',
- {
- category: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- User.belongsTo(Group, { as: 'Team' });
- Group.hasMany(Category, { as: 'Tags' });
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Group.bulkCreate([{ name: 'A' }, { name: 'B' }]),
- User.bulkCreate([{}, {}]),
- Category.bulkCreate([{}, {}]),
- ]);
- const [groups, users0, categories] = await Promise.all([
- Group.findAll(),
- User.findAll(),
- Category.findAll(),
- ]);
- const promises = [users0[0].setTeam(groups[1]), users0[1].setTeam(groups[0])];
- for (const group of groups) {
- promises.push(group.setTags(categories));
- }
- await Promise.all(promises);
- const users = await User.findAll({
- include: [
- {
- model: Group,
- required: true,
- as: 'Team',
- include: [{ model: Category, as: 'Tags' }],
- },
- ],
- limit: 1,
- });
- expect(users.length).to.equal(1);
- for (const user of users) {
- expect(user.Team).to.be.ok;
- expect(user.Team.Tags).to.be.ok;
- }
- });
- it('should be possible to define a belongsTo include as required with child hasMany which is not required with limit', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Category = this.sequelize.define(
- 'Category',
- {
- category: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- User.belongsTo(Group);
- Group.hasMany(Category);
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Group.bulkCreate([{ name: 'A' }, { name: 'B' }]),
- User.bulkCreate([{}, {}]),
- Category.bulkCreate([{}, {}]),
- ]);
- const [groups, users0, categories] = await Promise.all([
- Group.findAll(),
- User.findAll(),
- Category.findAll(),
- ]);
- const promises = [users0[0].setGroup(groups[1]), users0[1].setGroup(groups[0])];
- for (const group of groups) {
- promises.push(group.setCategories(categories));
- }
- await Promise.all(promises);
- const users = await User.findAll({
- include: [
- {
- model: Group,
- required: true,
- include: [{ model: Category, required: false }],
- },
- ],
- limit: 1,
- });
- expect(users.length).to.equal(1);
- for (const user of users) {
- expect(user.group).to.be.ok;
- expect(user.group.categories).to.be.ok;
- }
- });
- it('should be possible to extend the on clause with a where option on a hasOne include', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Project = this.sequelize.define(
- 'Project',
- {
- title: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- User.hasOne(Project, { as: 'LeaderOf' });
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Project.bulkCreate([{ title: 'Alpha' }, { title: 'Beta' }]),
- User.bulkCreate([{}, {}]),
- ]);
- const [projects, users0] = await Promise.all([Project.findAll(), User.findAll()]);
- await Promise.all([users0[1].setLeaderOf(projects[1]), users0[0].setLeaderOf(projects[0])]);
- const users = await User.findAll({
- include: [{ model: Project, as: 'LeaderOf', where: { title: 'Beta' } }],
- });
- expect(users.length).to.equal(1);
- expect(users[0].LeaderOf).to.be.ok;
- expect(users[0].LeaderOf.title).to.equal('Beta');
- });
- it('should be possible to extend the on clause with a where option on a hasMany include with a through model', async function () {
- const Product = this.sequelize.define(
- 'Product',
- {
- title: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Tag = this.sequelize.define(
- 'Tag',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const ProductTag = this.sequelize.define(
- 'ProductTag',
- {
- priority: DataTypes.INTEGER,
- },
- { schema: 'account' },
- );
- Product.belongsToMany(Tag, { through: ProductTag });
- Tag.belongsToMany(Product, { through: ProductTag });
- await this.sequelize.sync({ force: true });
- await Promise.all([
- Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }, { title: 'Dress' }]),
- Tag.bulkCreate([{ name: 'A' }, { name: 'B' }, { name: 'C' }]),
- ]);
- const [products0, tags] = await Promise.all([Product.findAll(), Tag.findAll()]);
- await Promise.all([
- products0[0].addTag(tags[0], { priority: 1 }),
- products0[0].addTag(tags[1], { priority: 2 }),
- products0[1].addTag(tags[1], { priority: 1 }),
- products0[2].addTag(tags[0], { priority: 3 }),
- products0[2].addTag(tags[1], { priority: 1 }),
- products0[2].addTag(tags[2], { priority: 2 }),
- ]);
- const products = await Product.findAll({
- include: [{ model: Tag, where: { name: 'C' } }],
- });
- expect(products.length).to.equal(1);
- expect(products[0].tags.length).to.equal(1);
- });
- it('should be possible to extend the on clause with a where option on nested includes', async function () {
- const User = this.sequelize.define(
- 'User',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Product = this.sequelize.define(
- 'Product',
- {
- title: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Tag = this.sequelize.define(
- 'Tag',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const Price = this.sequelize.define(
- 'Price',
- {
- value: DataTypes.FLOAT,
- },
- { schema: 'account' },
- );
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- const GroupMember = this.sequelize.define('GroupMember', {}, { schema: 'account' });
- const Rank = this.sequelize.define(
- 'Rank',
- {
- name: DataTypes.STRING,
- canInvite: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- canRemove: {
- type: DataTypes.INTEGER,
- defaultValue: 0,
- },
- },
- { schema: 'account' },
- );
- User.hasMany(Product);
- Product.belongsTo(User);
- Product.belongsToMany(Tag, { through: 'product_tag' });
- Tag.belongsToMany(Product, { through: 'product_tag' });
- Product.belongsTo(Tag, { as: 'Category' });
- Product.hasMany(Price);
- Price.belongsTo(Product);
- User.hasMany(GroupMember, { as: 'Memberships' });
- GroupMember.belongsTo(User);
- GroupMember.belongsTo(Rank);
- GroupMember.belongsTo(Group);
- Group.hasMany(GroupMember, { as: 'Memberships' });
- await this.sequelize.sync({ force: true });
- const [groups, ranks, tags] = await Promise.all([
- Group.bulkCreate([{ name: 'Developers' }, { name: 'Designers' }]).then(() =>
- Group.findAll(),
- ),
- Rank.bulkCreate([
- { name: 'Admin', canInvite: 1, canRemove: 1 },
- { name: 'Member', canInvite: 1, canRemove: 0 },
- ]).then(() => Rank.findAll()),
- Tag.bulkCreate([{ name: 'A' }, { name: 'B' }, { name: 'C' }]).then(() => Tag.findAll()),
- ]);
- for (const i of [0, 1, 2, 3, 4]) {
- const [user, products] = await Promise.all([
- User.create({ name: 'FooBarzz' }),
- Product.bulkCreate([{ title: 'Chair' }, { title: 'Desk' }]).then(() => Product.findAll()),
- ]);
- await Promise.all([
- GroupMember.bulkCreate([
- { userId: user.id, groupId: groups[0].id, rankId: ranks[0].id },
- { userId: user.id, groupId: groups[1].id, rankId: ranks[1].id },
- ]),
- user.setProducts([products[i * 2 + 0], products[i * 2 + 1]]),
- products[i * 2 + 0].setTags([tags[0], tags[2]]),
- products[i * 2 + 1].setTags([tags[1]]),
- products[i * 2 + 0].setCategory(tags[1]),
- Price.bulkCreate([
- { productId: products[i * 2 + 0].id, value: 5 },
- { productId: products[i * 2 + 0].id, value: 10 },
- { productId: products[i * 2 + 1].id, value: 5 },
- { productId: products[i * 2 + 1].id, value: 10 },
- { productId: products[i * 2 + 1].id, value: 15 },
- { productId: products[i * 2 + 1].id, value: 20 },
- ]),
- ]);
- const users = await User.findAll({
- include: [
- {
- model: GroupMember,
- as: 'Memberships',
- include: [Group, { model: Rank, where: { name: 'Admin' } }],
- },
- {
- model: Product,
- include: [
- 'tags',
- { model: Tag, as: 'Category' },
- {
- model: Price,
- where: {
- value: {
- [Op.gt]: 15,
- },
- },
- },
- ],
- },
- ],
- order: [['id', 'ASC']],
- });
- for (const user of users) {
- expect(user.Memberships.length).to.equal(1);
- expect(user.Memberships[0].rank.name).to.equal('Admin');
- expect(user.products.length).to.equal(1);
- expect(user.products[0].prices.length).to.equal(1);
- }
- }
- });
- it('should be possible to use limit and a where with a belongsTo include', async function () {
- const User = this.sequelize.define('User', {}, { schema: 'account' });
- const Group = this.sequelize.define(
- 'Group',
- {
- name: DataTypes.STRING,
- },
- { schema: 'account' },
- );
- User.belongsTo(Group);
- await this.sequelize.sync({ force: true });
- const results = await promiseProps({
- groups: Group.bulkCreate([{ name: 'A' }, { name: 'B' }]).then(() => {
- return Group.findAll();
- }),
- users: User.bulkCreate([{}, {}, {}, {}]).then(() => {
- return User.findAll();
- }),
- });
- await Promise.all([
- results.users[1].setGroup(results.groups[0]),
- results.users[2].setGroup(results.groups[0]),
- results.users[3].setGroup(results.groups[1]),
- results.users[0].setGroup(results.groups[0]),
- ]);
- const users = await User.findAll({
- include: [{ model: Group, where: { name: 'A' } }],
- limit: 2,
- });
- expect(users.length).to.equal(2);
- for (const user of users) {
- expect(user.group.name).to.equal('A');
- }
- });
- it('should be possible use limit, attributes and a where on a belongsTo with additional hasMany includes', async function () {
- await this.fixtureA();
- const products = await this.models.Product.findAll({
- attributes: ['title'],
- include: [
- { model: this.models.Company, where: { name: 'NYSE' } },
- { model: this.models.Tag, as: 'tags' },
- { model: this.models.Price },
- ],
- limit: 3,
- order: [['id', 'ASC']],
- });
- expect(products.length).to.equal(3);
- for (const product of products) {
- expect(product.company.name).to.equal('NYSE');
- expect(product.tags.length).to.be.ok;
- expect(product.prices.length).to.be.ok;
- }
- });
- it('should be possible to use limit and a where on a hasMany with additional includes', async function () {
- await this.fixtureA();
- const products = await this.models.Product.findAll({
- include: [
- { model: this.models.Company },
- { model: this.models.Tag, as: 'tags' },
- {
- model: this.models.Price,
- where: {
- value: { [Op.gt]: 5 },
- },
- },
- ],
- limit: 6,
- order: [['id', 'ASC']],
- });
- expect(products.length).to.equal(6);
- for (const product of products) {
- expect(product.tags.length).to.be.ok;
- expect(product.prices.length).to.be.ok;
- for (const price of product.prices) {
- expect(price.value).to.be.above(5);
- }
- }
- });
- it('should be possible to use limit and a where on a hasMany with a through model with additional includes', async function () {
- await this.fixtureA();
- const products = await this.models.Product.findAll({
- include: [
- { model: this.models.Company },
- { model: this.models.Tag, as: 'tags', where: { name: ['A', 'B', 'C'] } },
- { model: this.models.Price },
- ],
- limit: 10,
- order: [['id', 'ASC']],
- });
- expect(products.length).to.equal(10);
- for (const product of products) {
- expect(product.tags.length).to.be.ok;
- expect(product.prices.length).to.be.ok;
- for (const tag of product.tags) {
- expect(['A', 'B', 'C']).to.include(tag.name);
- }
- }
- });
- it('should support including date fields, with the correct timezone', async function () {
- const User = this.sequelize.define(
- 'user',
- {
- dateField: DataTypes.DATE,
- },
- { timestamps: false, schema: 'account' },
- );
- const Group = this.sequelize.define(
- 'group',
- {
- dateField: DataTypes.DATE,
- },
- { timestamps: false, schema: 'account' },
- );
- User.belongsToMany(Group, { through: 'group_user' });
- Group.belongsToMany(User, { through: 'group_user' });
- await this.sequelize.sync();
- const user = await User.create({ dateField: Date.UTC(2014, 1, 20) });
- const group = await Group.create({ dateField: Date.UTC(2014, 1, 20) });
- await user.addGroup(group);
- const users = await User.findAll({
- where: {
- id: user.id,
- },
- include: [Group],
- });
- expect(users[0].dateField.getTime()).to.equal(Date.UTC(2014, 1, 20));
- expect(users[0].groups[0].dateField.getTime()).to.equal(Date.UTC(2014, 1, 20));
- });
- });
- describe('findOne', () => {
- it('should work with schemas', async function () {
- const UserModel = this.sequelize.define(
- 'User',
- {
- Id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- },
- Name: DataTypes.STRING,
- UserType: DataTypes.INTEGER,
- Email: DataTypes.STRING,
- PasswordHash: DataTypes.STRING,
- Enabled: {
- type: DataTypes.BOOLEAN,
- },
- CreatedDatetime: DataTypes.DATE,
- UpdatedDatetime: DataTypes.DATE,
- },
- {
- schema: 'hero',
- tableName: 'User',
- timestamps: false,
- },
- );
- const UserIdColumn = { type: DataTypes.INTEGER, references: { model: UserModel, key: 'Id' } };
- const ResumeModel = this.sequelize.define(
- 'Resume',
- {
- Id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- },
- UserId: UserIdColumn,
- Name: DataTypes.STRING,
- Contact: DataTypes.STRING,
- School: DataTypes.STRING,
- WorkingAge: DataTypes.STRING,
- Description: DataTypes.STRING,
- PostType: DataTypes.INTEGER,
- RefreshDatetime: DataTypes.DATE,
- CreatedDatetime: DataTypes.DATE,
- },
- {
- schema: 'hero',
- tableName: 'resume',
- timestamps: false,
- },
- );
- UserModel.hasOne(ResumeModel, {
- foreignKey: 'UserId',
- as: 'Resume',
- });
- ResumeModel.belongsTo(UserModel, {
- foreignKey: 'UserId',
- });
- await this.sequelize.createSchema('hero');
- await this.sequelize.sync({ force: true });
- await UserModel.findOne({
- where: {
- Id: 1,
- },
- include: [
- {
- model: ResumeModel,
- as: 'Resume',
- },
- ],
- });
- });
- });
- });
|