find-all.test.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. 'use strict';
  2. const chai = require('chai');
  3. const expect = chai.expect;
  4. const Support = require('../../support');
  5. const current = Support.sequelize;
  6. const sinon = require('sinon');
  7. const { DataTypes, QueryError } = require('@sequelize/core');
  8. const { Logger } = require('@sequelize/core/_non-semver-use-at-your-own-risk_/utils/logger.js');
  9. const { beforeAll2 } = require('../../support');
  10. describe(Support.getTestDialectTeaser('Model'), () => {
  11. describe('_warnOnInvalidOptions', () => {
  12. beforeEach(function () {
  13. this.loggerSpy = sinon.spy(Logger.prototype, 'warn');
  14. });
  15. afterEach(function () {
  16. this.loggerSpy.restore();
  17. });
  18. it('Warns the user if they use a model attribute without a where clause', function () {
  19. const User = current.define('User', { firstName: 'string' });
  20. User._warnOnInvalidOptions({ firstName: 12, order: [] }, ['firstName']);
  21. const expectedError =
  22. 'Model attributes (firstName) passed into finder method options of model User, but the options.where object is empty. Did you forget to use options.where?';
  23. expect(this.loggerSpy.calledWith(expectedError)).to.equal(true);
  24. });
  25. it('Does not warn the user if they use a model attribute without a where clause that shares its name with a query option', function () {
  26. const User = current.define('User', { order: 'string' });
  27. User._warnOnInvalidOptions({ order: [] }, ['order']);
  28. expect(this.loggerSpy.called).to.equal(false);
  29. });
  30. it('Does not warn the user if they use valid query options', function () {
  31. const User = current.define('User', { order: 'string' });
  32. User._warnOnInvalidOptions({ where: { order: 1 }, order: [] });
  33. expect(this.loggerSpy.called).to.equal(false);
  34. });
  35. });
  36. describe('method findAll', () => {
  37. const vars = beforeAll2(() => {
  38. const MyModel = current.define(
  39. 'MyModel',
  40. {
  41. name: DataTypes.STRING,
  42. },
  43. { timestamps: false },
  44. );
  45. return { MyModel };
  46. });
  47. before(function () {
  48. const { MyModel } = vars;
  49. this.stub = sinon.stub(current.queryInterface, 'select').callsFake(() => MyModel.build({}));
  50. this._warnOnInvalidOptionsStub = sinon.stub(MyModel, '_warnOnInvalidOptions');
  51. });
  52. beforeEach(function () {
  53. this.stub.resetHistory();
  54. this._warnOnInvalidOptionsStub.resetHistory();
  55. });
  56. after(function () {
  57. this.stub.restore();
  58. this._warnOnInvalidOptionsStub.restore();
  59. });
  60. describe('handles input validation', () => {
  61. it('calls _warnOnInvalidOptions', function () {
  62. const { MyModel } = vars;
  63. MyModel.findAll();
  64. expect(this._warnOnInvalidOptionsStub.calledOnce).to.equal(true);
  65. });
  66. it('Throws an error when the attributes option is formatted incorrectly', async () => {
  67. const { MyModel } = vars;
  68. await expect(MyModel.findAll({ attributes: 'name' })).to.be.rejectedWith(QueryError);
  69. });
  70. });
  71. describe('attributes include / exclude', () => {
  72. it('allows me to include additional attributes', async function () {
  73. const { MyModel } = vars;
  74. await MyModel.findAll({
  75. attributes: {
  76. include: ['foobar'],
  77. },
  78. });
  79. expect(this.stub.getCall(0).args[2].attributes).to.deep.equal(['id', 'name', 'foobar']);
  80. });
  81. it('allows me to exclude attributes', async function () {
  82. const { MyModel } = vars;
  83. await MyModel.findAll({
  84. attributes: {
  85. exclude: ['name'],
  86. },
  87. });
  88. expect(this.stub.getCall(0).args[2].attributes).to.deep.equal(['id']);
  89. });
  90. it('include takes precendence over exclude', async function () {
  91. const { MyModel } = vars;
  92. await MyModel.findAll({
  93. attributes: {
  94. exclude: ['name'],
  95. include: ['name'],
  96. },
  97. });
  98. expect(this.stub.getCall(0).args[2].attributes).to.deep.equal(['id', 'name']);
  99. });
  100. it('works for models without PK #4607', async function () {
  101. const MyModel = current.define('model', {}, { timestamps: false });
  102. const Foo = current.define('foo');
  103. MyModel.hasOne(Foo);
  104. MyModel.removeAttribute('id');
  105. await MyModel.findAll({
  106. attributes: {
  107. include: ['name'],
  108. },
  109. include: [Foo],
  110. });
  111. expect(this.stub.getCall(0).args[2].attributes).to.deep.equal(['name']);
  112. });
  113. });
  114. });
  115. });