merge.test.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. 'use strict';
  2. const chai = require('chai');
  3. const { DataTypes } = require('@sequelize/core');
  4. const expect = chai.expect;
  5. const Support = require('../../support');
  6. describe(Support.getTestDialectTeaser('Model'), () => {
  7. describe('scope', () => {
  8. describe('simple merge', () => {
  9. beforeEach(async function () {
  10. this.Foo = this.sequelize.define('foo', { name: DataTypes.STRING }, { timestamps: false });
  11. this.Bar = this.sequelize.define('bar', { name: DataTypes.STRING }, { timestamps: false });
  12. this.Baz = this.sequelize.define('baz', { name: DataTypes.STRING }, { timestamps: false });
  13. this.Foo.belongsTo(this.Baz, { foreignKey: 'bazId' });
  14. this.Foo.hasOne(this.Bar, { foreignKey: 'fooId' });
  15. this.createEntries = async () => {
  16. const baz = await this.Baz.create({ name: 'The Baz' });
  17. const foo = await this.Foo.create({ name: 'The Foo', bazId: baz.id });
  18. return this.Bar.create({ name: 'The Bar', fooId: foo.id });
  19. };
  20. this.scopes = {
  21. includeBar: { include: this.Bar },
  22. includeBaz: { include: this.Baz },
  23. };
  24. this.Foo.addScope('includeBar', this.scopes.includeBar);
  25. this.Foo.addScope('includeBaz', this.scopes.includeBaz);
  26. await this.createEntries(await this.sequelize.sync({ force: true }));
  27. });
  28. it('should merge simple scopes correctly', async function () {
  29. const result = await this.Foo.withScope('includeBar', 'includeBaz').findOne();
  30. const json = result.toJSON();
  31. expect(json.bar).to.be.ok;
  32. expect(json.baz).to.be.ok;
  33. expect(json.bar.name).to.equal('The Bar');
  34. expect(json.baz.name).to.equal('The Baz');
  35. });
  36. });
  37. describe('complex merge', () => {
  38. beforeEach(async function () {
  39. this.Foo = this.sequelize.define('foo', { name: DataTypes.STRING }, { timestamps: false });
  40. this.Bar = this.sequelize.define('bar', { name: DataTypes.STRING }, { timestamps: false });
  41. this.Baz = this.sequelize.define('baz', { name: DataTypes.STRING }, { timestamps: false });
  42. this.Qux = this.sequelize.define('qux', { name: DataTypes.STRING }, { timestamps: false });
  43. this.Foo.hasMany(this.Bar, { foreignKey: 'fooId' });
  44. this.Bar.hasMany(this.Baz, { foreignKey: 'barId' });
  45. this.Baz.hasMany(this.Qux, { foreignKey: 'bazId' });
  46. this.createFooWithDescendants = () =>
  47. this.Foo.create(
  48. {
  49. name: 'foo1',
  50. bars: [
  51. {
  52. name: 'bar1',
  53. bazs: [
  54. {
  55. name: 'baz1',
  56. quxes: [{ name: 'qux1' }, { name: 'qux2' }],
  57. },
  58. {
  59. name: 'baz2',
  60. quxes: [{ name: 'qux3' }, { name: 'qux4' }],
  61. },
  62. ],
  63. },
  64. {
  65. name: 'bar2',
  66. bazs: [
  67. {
  68. name: 'baz3',
  69. quxes: [{ name: 'qux5' }, { name: 'qux6' }],
  70. },
  71. {
  72. name: 'baz4',
  73. quxes: [{ name: 'qux7' }, { name: 'qux8' }],
  74. },
  75. ],
  76. },
  77. ],
  78. },
  79. {
  80. include: [
  81. {
  82. model: this.Bar,
  83. include: [
  84. {
  85. model: this.Baz,
  86. include: [
  87. {
  88. model: this.Qux,
  89. },
  90. ],
  91. },
  92. ],
  93. },
  94. ],
  95. },
  96. );
  97. this.scopes = {
  98. includeEverything: {
  99. include: {
  100. model: this.Bar,
  101. include: [
  102. {
  103. model: this.Baz,
  104. include: this.Qux,
  105. },
  106. ],
  107. },
  108. },
  109. limitedBars: {
  110. include: [
  111. {
  112. model: this.Bar,
  113. limit: 2,
  114. },
  115. ],
  116. },
  117. limitedBazs: {
  118. include: [
  119. {
  120. model: this.Bar,
  121. include: [
  122. {
  123. model: this.Baz,
  124. limit: 2,
  125. },
  126. ],
  127. },
  128. ],
  129. },
  130. excludeBazName: {
  131. include: [
  132. {
  133. model: this.Bar,
  134. include: [
  135. {
  136. model: this.Baz,
  137. attributes: {
  138. exclude: ['name'],
  139. },
  140. },
  141. ],
  142. },
  143. ],
  144. },
  145. };
  146. this.Foo.addScope('includeEverything', this.scopes.includeEverything);
  147. this.Foo.addScope('limitedBars', this.scopes.limitedBars);
  148. this.Foo.addScope('limitedBazs', this.scopes.limitedBazs);
  149. this.Foo.addScope('excludeBazName', this.scopes.excludeBazName);
  150. this.scopePermutations = [
  151. ['includeEverything', 'limitedBars', 'limitedBazs', 'excludeBazName'],
  152. ['includeEverything', 'limitedBars', 'excludeBazName', 'limitedBazs'],
  153. ['includeEverything', 'limitedBazs', 'limitedBars', 'excludeBazName'],
  154. ['includeEverything', 'limitedBazs', 'excludeBazName', 'limitedBars'],
  155. ['includeEverything', 'excludeBazName', 'limitedBars', 'limitedBazs'],
  156. ['includeEverything', 'excludeBazName', 'limitedBazs', 'limitedBars'],
  157. ['limitedBars', 'includeEverything', 'limitedBazs', 'excludeBazName'],
  158. ['limitedBars', 'includeEverything', 'excludeBazName', 'limitedBazs'],
  159. ['limitedBars', 'limitedBazs', 'includeEverything', 'excludeBazName'],
  160. ['limitedBars', 'limitedBazs', 'excludeBazName', 'includeEverything'],
  161. ['limitedBars', 'excludeBazName', 'includeEverything', 'limitedBazs'],
  162. ['limitedBars', 'excludeBazName', 'limitedBazs', 'includeEverything'],
  163. ['limitedBazs', 'includeEverything', 'limitedBars', 'excludeBazName'],
  164. ['limitedBazs', 'includeEverything', 'excludeBazName', 'limitedBars'],
  165. ['limitedBazs', 'limitedBars', 'includeEverything', 'excludeBazName'],
  166. ['limitedBazs', 'limitedBars', 'excludeBazName', 'includeEverything'],
  167. ['limitedBazs', 'excludeBazName', 'includeEverything', 'limitedBars'],
  168. ['limitedBazs', 'excludeBazName', 'limitedBars', 'includeEverything'],
  169. ['excludeBazName', 'includeEverything', 'limitedBars', 'limitedBazs'],
  170. ['excludeBazName', 'includeEverything', 'limitedBazs', 'limitedBars'],
  171. ['excludeBazName', 'limitedBars', 'includeEverything', 'limitedBazs'],
  172. ['excludeBazName', 'limitedBars', 'limitedBazs', 'includeEverything'],
  173. ['excludeBazName', 'limitedBazs', 'includeEverything', 'limitedBars'],
  174. ['excludeBazName', 'limitedBazs', 'limitedBars', 'includeEverything'],
  175. ];
  176. await this.createFooWithDescendants(await this.sequelize.sync({ force: true }));
  177. });
  178. it('should merge complex scopes correctly regardless of their order', async function () {
  179. const results = await Promise.all(
  180. this.scopePermutations.map(scopes => this.Foo.withScope(...scopes).findOne()),
  181. );
  182. const first = results.shift().toJSON();
  183. for (const result of results) {
  184. expect(result.toJSON()).to.deep.equal(first);
  185. }
  186. });
  187. it('should merge complex scopes with findAll options correctly regardless of their order', async function () {
  188. const results = await Promise.all(
  189. this.scopePermutations.map(async ([a, b, c, d]) => {
  190. const x = await this.Foo.withScope(a, b, c).findAll(this.scopes[d]);
  191. return x[0];
  192. }),
  193. );
  194. const first = results.shift().toJSON();
  195. for (const result of results) {
  196. expect(result.toJSON()).to.deep.equal(first);
  197. }
  198. });
  199. it('should merge complex scopes with findOne options correctly regardless of their order', async function () {
  200. const results = await Promise.all(
  201. this.scopePermutations.map(([a, b, c, d]) =>
  202. this.Foo.withScope(a, b, c).findOne(this.scopes[d]),
  203. ),
  204. );
  205. const first = results.shift().toJSON();
  206. for (const result of results) {
  207. expect(result.toJSON()).to.deep.equal(first);
  208. }
  209. });
  210. });
  211. });
  212. });