increment.test.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. 'use strict';
  2. const chai = require('chai');
  3. const expect = chai.expect;
  4. const Support = require('../support');
  5. const { DataTypes } = require('@sequelize/core');
  6. const sinon = require('sinon');
  7. describe(Support.getTestDialectTeaser('Model'), () => {
  8. before(function () {
  9. this.clock = sinon.useFakeTimers();
  10. });
  11. after(function () {
  12. this.clock.restore();
  13. });
  14. beforeEach(async function () {
  15. this.User = this.sequelize.define('User', {
  16. id: { type: DataTypes.INTEGER, primaryKey: true },
  17. aNumber: { type: DataTypes.INTEGER },
  18. bNumber: { type: DataTypes.INTEGER },
  19. cNumber: { type: DataTypes.INTEGER, field: 'c_number' },
  20. });
  21. await this.User.sync({ force: true });
  22. await this.User.bulkCreate([
  23. {
  24. id: 1,
  25. aNumber: 0,
  26. bNumber: 0,
  27. },
  28. {
  29. id: 2,
  30. aNumber: 0,
  31. bNumber: 0,
  32. },
  33. {
  34. id: 3,
  35. aNumber: 0,
  36. bNumber: 0,
  37. },
  38. {
  39. id: 4,
  40. aNumber: 0,
  41. bNumber: 0,
  42. cNumber: 0,
  43. },
  44. ]);
  45. });
  46. for (const method of ['increment', 'decrement']) {
  47. describe(method, () => {
  48. before(function () {
  49. this.assert = (increment, decrement) => {
  50. return method === 'increment' ? increment : decrement;
  51. };
  52. });
  53. it('supports where conditions', async function () {
  54. await this.User.findByPk(1);
  55. await this.User[method](['aNumber'], { by: 2, where: { id: 1 } });
  56. const user3 = await this.User.findByPk(2);
  57. expect(user3.aNumber).to.equal(this.assert(0, 0));
  58. });
  59. it('uses correct column names for where conditions', async function () {
  60. await this.User[method](['aNumber'], { by: 2, where: { cNumber: 0 } });
  61. const user4 = await this.User.findByPk(4);
  62. expect(user4.aNumber).to.equal(this.assert(2, -2));
  63. });
  64. it('should still work right with other concurrent increments', async function () {
  65. const aUsers = await this.User.findAll();
  66. await Promise.all([
  67. this.User[method](['aNumber'], { by: 2, where: {} }),
  68. this.User[method](['aNumber'], { by: 2, where: {} }),
  69. this.User[method](['aNumber'], { by: 2, where: {} }),
  70. ]);
  71. const bUsers = await this.User.findAll();
  72. for (const [i, bUser] of bUsers.entries()) {
  73. expect(bUser.aNumber).to.equal(this.assert(aUsers[i].aNumber + 6, aUsers[i].aNumber - 6));
  74. }
  75. });
  76. it('with array', async function () {
  77. const aUsers = await this.User.findAll();
  78. await this.User[method](['aNumber'], { by: 2, where: {} });
  79. const bUsers = await this.User.findAll();
  80. for (const [i, bUser] of bUsers.entries()) {
  81. expect(bUser.aNumber).to.equal(this.assert(aUsers[i].aNumber + 2, aUsers[i].aNumber - 2));
  82. }
  83. });
  84. it('with single field', async function () {
  85. const aUsers = await this.User.findAll();
  86. await this.User[method]('aNumber', { by: 2, where: {} });
  87. const bUsers = await this.User.findAll();
  88. for (const [i, bUser] of bUsers.entries()) {
  89. expect(bUser.aNumber).to.equal(this.assert(aUsers[i].aNumber + 2, aUsers[i].aNumber - 2));
  90. }
  91. });
  92. it('with single field and no value', async function () {
  93. const aUsers = await this.User.findAll();
  94. await this.User[method]('aNumber', { where: {} });
  95. const bUsers = await this.User.findAll();
  96. for (const [i, bUser] of bUsers.entries()) {
  97. expect(bUser.aNumber).to.equal(this.assert(aUsers[i].aNumber + 1, aUsers[i].aNumber - 1));
  98. }
  99. });
  100. it('with key value pair', async function () {
  101. const aUsers = await this.User.findAll();
  102. await this.User[method]({ aNumber: 1, bNumber: 2 }, { where: {} });
  103. const bUsers = await this.User.findAll();
  104. for (const [i, bUser] of bUsers.entries()) {
  105. expect(bUser.aNumber).to.equal(this.assert(aUsers[i].aNumber + 1, aUsers[i].aNumber - 1));
  106. expect(bUser.bNumber).to.equal(this.assert(aUsers[i].bNumber + 2, aUsers[i].bNumber - 2));
  107. }
  108. });
  109. it('should still work right with other concurrent updates', async function () {
  110. const aUsers = await this.User.findAll();
  111. await this.User.update({ aNumber: 2 }, { where: {} });
  112. await this.User[method](['aNumber'], { by: 2, where: {} });
  113. const bUsers = await this.User.findAll();
  114. for (const [i, bUser] of bUsers.entries()) {
  115. // for decrement 2 - 2 = 0
  116. expect(bUser.aNumber).to.equal(this.assert(aUsers[i].aNumber + 4, aUsers[i].aNumber));
  117. }
  118. });
  119. it('with timestamps set to true', async function () {
  120. const User = this.sequelize.define(
  121. 'IncrementUser',
  122. {
  123. aNumber: DataTypes.INTEGER,
  124. },
  125. { timestamps: true },
  126. );
  127. await User.sync({ force: true });
  128. const user = await User.create({ aNumber: 1 });
  129. const oldDate = user.updatedAt;
  130. this.clock.tick(1000);
  131. await User[method]('aNumber', { by: 1, where: {} });
  132. await expect(User.findByPk(1)).to.eventually.have.property('updatedAt').afterTime(oldDate);
  133. });
  134. it('with timestamps set to true and options.silent set to true', async function () {
  135. const User = this.sequelize.define(
  136. 'IncrementUser',
  137. {
  138. aNumber: DataTypes.INTEGER,
  139. },
  140. { timestamps: true },
  141. );
  142. await User.sync({ force: true });
  143. const user = await User.create({ aNumber: 1 });
  144. const oldDate = user.updatedAt;
  145. expect(oldDate).to.be.instanceOf(Date, 'Date from User.create is not a Date');
  146. this.clock.tick(1000);
  147. await User[method]('aNumber', { by: 1, silent: true, where: {} });
  148. const updatedUser = await User.findByPk(1);
  149. await expect(updatedUser.updatedAt).to.equalTime(oldDate);
  150. });
  151. it('should work with scopes', async function () {
  152. const User = this.sequelize.define(
  153. 'User',
  154. {
  155. aNumber: DataTypes.INTEGER,
  156. name: DataTypes.STRING,
  157. },
  158. {
  159. scopes: {
  160. jeff: {
  161. where: {
  162. name: 'Jeff',
  163. },
  164. },
  165. },
  166. },
  167. );
  168. await User.sync({ force: true });
  169. await User.bulkCreate([
  170. {
  171. aNumber: 1,
  172. name: 'Jeff',
  173. },
  174. {
  175. aNumber: 3,
  176. name: 'Not Jeff',
  177. },
  178. ]);
  179. await User.withScope('jeff')[method]('aNumber', {});
  180. const jeff = await User.withScope('jeff').findOne();
  181. expect(jeff.aNumber).to.equal(this.assert(2, 0));
  182. const notJeff = await User.findOne({
  183. where: {
  184. name: 'Not Jeff',
  185. },
  186. });
  187. expect(notJeff.aNumber).to.equal(this.assert(3, 3));
  188. });
  189. it('should not care for attributes in the instance scope', async function () {
  190. this.User.addScope('test', {
  191. attributes: ['foo', 'bar'],
  192. });
  193. const createdUser = await this.User.withScope('test').create({ id: 5, aNumber: 5 });
  194. await createdUser[method]('aNumber', { by: 2 });
  195. const user = await this.User.findByPk(5);
  196. expect(user.aNumber).to.equal(this.assert(7, 3));
  197. });
  198. it('should not care for exclude-attributes in the instance scope', async function () {
  199. this.User.addScope('test', {
  200. attributes: { exclude: ['foo', 'bar'] },
  201. });
  202. const createdUser = await this.User.withScope('test').create({ id: 5, aNumber: 5 });
  203. await createdUser[method]('aNumber', { by: 2 });
  204. const user = await this.User.findByPk(5);
  205. expect(user.aNumber).to.equal(this.assert(7, 3));
  206. });
  207. it('should not care for include-attributes in the instance scope', async function () {
  208. this.User.addScope('test', {
  209. attributes: { include: ['foo', 'bar'] },
  210. });
  211. const createdUser = await this.User.withScope('test').create({ id: 5, aNumber: 5 });
  212. await createdUser[method]('aNumber', { by: 2 });
  213. const user = await this.User.findByPk(5);
  214. expect(user.aNumber).to.equal(this.assert(7, 3));
  215. });
  216. });
  217. }
  218. });