overwriting-builtins.test.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import type {
  2. CreationOptional,
  3. InferAttributes,
  4. InferCreationAttributes,
  5. NonAttribute,
  6. } from '@sequelize/core';
  7. import { DataTypes, Model } from '@sequelize/core';
  8. import { expect } from 'chai';
  9. import { sequelize } from '../../support';
  10. describe('Model', () => {
  11. // TODO [>=8]: throw if an attribute has the same name as a built-in Model method.
  12. it('does not let attributes shadow built-in model method & properties', () => {
  13. const User = sequelize.define('OverWrittenKeys', {
  14. set: DataTypes.STRING,
  15. });
  16. const user = User.build({ set: 'A' });
  17. expect(user.get('set')).to.equal('A');
  18. user.set('set', 'B');
  19. expect(user.get('set')).to.equal('B');
  20. });
  21. it('makes attributes take priority over class properties defined on the model', () => {
  22. // Issue description: https://github.com/sequelize/sequelize/issues/14300
  23. // Sequelize models add getter & setters on the model prototype for all attributes defined on the model.
  24. // Class properties, which are usually used when using TypeScript or decorators, are added on the model instance,
  25. // and therefore take priority over the prototype getters & setters.
  26. // This test ensures that the attributes are not shadowed by the class properties.
  27. class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
  28. id: CreationOptional<number> = 10;
  29. firstName: string = 'abc';
  30. nonAttribute: NonAttribute<string> = 'def';
  31. }
  32. User.init(
  33. {
  34. id: {
  35. type: DataTypes.INTEGER,
  36. primaryKey: true,
  37. autoIncrement: true,
  38. },
  39. firstName: {
  40. type: DataTypes.STRING,
  41. allowNull: false,
  42. },
  43. },
  44. { sequelize },
  45. );
  46. const user = User.build({ firstName: 'Zoe' });
  47. expect(user.id).to.eq(null); // autoIncrement
  48. expect(user.firstName).to.eq('Zoe');
  49. expect(user.nonAttribute).to.eq('def');
  50. });
  51. it('makes associations take priority over class properties defined on the model', () => {
  52. // This is the same issue as above, but for associations
  53. class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
  54. profile?: Profile;
  55. }
  56. class Profile extends Model<InferAttributes<Profile>, InferCreationAttributes<Profile>> {
  57. userId: number = 10;
  58. }
  59. User.init({}, { sequelize });
  60. Profile.init({}, { sequelize });
  61. User.hasOne(Profile, { as: 'profile', foreignKey: 'userId' });
  62. // @ts-expect-error -- TODO: add typing for creating associations in build/create
  63. const user = User.build({ profile: {} }, { include: ['profile'] });
  64. expect(user.profile).to.be.instanceof(Profile);
  65. });
  66. });