set.test.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. 'use strict';
  2. const { expect } = require('chai');
  3. const { beforeAll2, sequelize } = require('../../support');
  4. const { DataTypes } = require('@sequelize/core');
  5. const sinon = require('sinon');
  6. const dialect = sequelize.dialect;
  7. describe('Model#set', () => {
  8. if (dialect.supports.dataTypes.JSONB) {
  9. it('sets nested keys in JSON objects', () => {
  10. const User = sequelize.define('User', {
  11. meta: DataTypes.JSONB,
  12. });
  13. const user = User.build(
  14. {
  15. meta: {
  16. location: 'Stockhollm',
  17. },
  18. },
  19. {
  20. isNewRecord: false,
  21. raw: true,
  22. },
  23. );
  24. const meta = user.get('meta');
  25. user.set('meta.location', 'Copenhagen');
  26. expect(user.dataValues['meta.location']).not.to.be.ok;
  27. expect(user.get('meta').location).to.equal('Copenhagen');
  28. expect(user.get('meta') === meta).to.equal(true);
  29. expect(user.get('meta') === meta).to.equal(true);
  30. });
  31. it('doesnt mutate the JSONB defaultValue', () => {
  32. const User = sequelize.define('User', {
  33. meta: {
  34. type: DataTypes.JSONB,
  35. allowNull: false,
  36. defaultValue: {},
  37. },
  38. });
  39. const user1 = User.build({});
  40. user1.set('meta.location', 'Stockhollm');
  41. const user2 = User.build({});
  42. expect(user2.get('meta')).to.deep.equal({});
  43. });
  44. }
  45. it('sets the date "1970-01-01" to previously null field', () => {
  46. const User = sequelize.define('User', {
  47. date: {
  48. type: DataTypes.DATE,
  49. allowNull: true,
  50. },
  51. });
  52. const user1 = User.build({
  53. date: null,
  54. });
  55. user1.set('date', '1970-01-01');
  56. expect(user1.get('date')).to.be.ok;
  57. expect(user1.get('date').getTime()).to.equal(new Date('1970-01-01').getTime());
  58. });
  59. it('overwrites non-date originalValue with date', () => {
  60. const User = sequelize.define('User', {
  61. date: DataTypes.DATE,
  62. });
  63. const user = User.build(
  64. {
  65. date: ' ',
  66. },
  67. {
  68. isNewRecord: false,
  69. raw: true,
  70. },
  71. );
  72. user.set('date', new Date());
  73. expect(user.get('date')).to.be.an.instanceof(Date);
  74. expect(user.get('date')).not.to.be.NaN;
  75. });
  76. describe('custom setter', () => {
  77. const vars = beforeAll2(() => {
  78. const stubCreate = sinon
  79. .stub(sequelize.queryInterface, 'insert')
  80. .callsFake(async instance => [instance, 1]);
  81. const stubGetNextPrimaryKeyValue = sinon
  82. .stub(sequelize.queryInterface, 'getNextPrimaryKeyValue')
  83. .callsFake(async () => undefined);
  84. const User = sequelize.define('User', {
  85. phoneNumber: {
  86. type: DataTypes.STRING,
  87. set(val) {
  88. if (typeof val === 'object' && val !== null) {
  89. val = `00${val.country}${val.area}${val.local}`;
  90. }
  91. if (typeof val === 'string') {
  92. // Canonicalize phone number
  93. val = val.replace(/^\+/, '00').replaceAll(/\(0\)|[\s()+./-]/g, '');
  94. }
  95. this.setDataValue('phoneNumber', val);
  96. },
  97. },
  98. });
  99. return { stubCreate, stubGetNextPrimaryKeyValue, User };
  100. });
  101. after(() => {
  102. vars.stubCreate.restore();
  103. vars.stubGetNextPrimaryKeyValue.restore();
  104. });
  105. it('does not set field to changed if field is set to the same value with custom setter using primitive value', async () => {
  106. const user = vars.User.build({
  107. phoneNumber: '+1 234 567',
  108. });
  109. await user.save();
  110. expect(user.changed('phoneNumber')).to.be.false;
  111. user.set('phoneNumber', '+1 (0) 234567'); // Canonical equivalent of existing phone number
  112. expect(user.changed('phoneNumber')).to.be.false;
  113. });
  114. it('sets field to changed if field is set to the another value with custom setter using primitive value', async () => {
  115. const user = vars.User.build({
  116. phoneNumber: '+1 234 567',
  117. });
  118. await user.save();
  119. expect(user.changed('phoneNumber')).to.be.false;
  120. user.set('phoneNumber', '+1 (0) 765432'); // Canonical non-equivalent of existing phone number
  121. expect(user.changed('phoneNumber')).to.be.true;
  122. });
  123. it('does not set field to changed if field is set to the same value with custom setter using object', async () => {
  124. const user = vars.User.build({
  125. phoneNumber: '+1 234 567',
  126. });
  127. await user.save();
  128. expect(user.changed('phoneNumber')).to.be.false;
  129. user.set('phoneNumber', { country: '1', area: '234', local: '567' }); // Canonical equivalent of existing phone number
  130. expect(user.changed('phoneNumber')).to.be.false;
  131. });
  132. it('sets field to changed if field is set to the another value with custom setter using object', async () => {
  133. const user = vars.User.build({
  134. phoneNumber: '+1 234 567',
  135. });
  136. await user.save();
  137. expect(user.changed('phoneNumber')).to.be.false;
  138. user.set('phoneNumber', { country: '1', area: '765', local: '432' }); // Canonical non-equivalent of existing phone number
  139. expect(user.changed('phoneNumber')).to.be.true;
  140. });
  141. });
  142. });