Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cast): remove empty conditions after strict applied #12898

Merged
merged 1 commit into from
Jan 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/cast.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,18 @@ module.exports = function cast(schema, obj, options, context) {
if (!Array.isArray(val)) {
throw new CastError('Array', val, path);
}
for (let k = 0; k < val.length; ++k) {
for (let k = val.length - 1; k >= 0; k--) {
if (val[k] == null || typeof val[k] !== 'object') {
throw new CastError('Object', val[k], path + '.' + k);
}
val[k] = cast(schema, val[k], options, context);
if (Object.keys(val[k]).length === 0) {
val.splice(k, 1);
}
}

if (val.length === 0) {
delete obj[path];
}
} else if (path === '$where') {
type = typeof val;
Expand Down
76 changes: 47 additions & 29 deletions test/docs/cast.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,40 +97,58 @@ describe('Cast Tutorial', function() {
await query.exec();
});

it('strictQuery true', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
describe('strictQuery', function() {
it('strictQuery true - simple object', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`
// acquit:ignore:start
assert.deepEqual(query.getFilter(), {});
// acquit:ignore:end
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });
it('strictQuery true - conditions', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
});
Character = mongoose.model('Character', schema);

await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`
// acquit:ignore:start
assert.deepEqual(query.getFilter(), {});
// acquit:ignore:end
});
const query = Character.findOne({ $or: [{ notInSchema: { $lt: 'not a number' } }], $and: [{ name: 'abc' }, { age: { $gt: 18 } }, { notInSchema: { $lt: 'not a number' } }] });

it('strictQuery throw', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: 'throw'
await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`
// acquit:ignore:start
assert.deepEqual(query.getFilter(), { $and: [{ name: 'abc' }, { age: { $gt: 18 } }] });
// acquit:ignore:end
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

const err = await query.exec().then(() => null, err => err);
err.name; // 'StrictModeError'
// Path "notInSchema" is not in schema and strictQuery is 'throw'.
err.message;
// acquit:ignore:start
assert.equal(err.name, 'StrictModeError');
assert.equal(err.message, 'Path "notInSchema" is not in schema and ' +
'strictQuery is \'throw\'.');
// acquit:ignore:end
it('strictQuery throw', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: 'throw'
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

const err = await query.exec().then(() => null, err => err);
err.name; // 'StrictModeError'
// Path "notInSchema" is not in schema and strictQuery is 'throw'.
err.message;
// acquit:ignore:start
assert.equal(err.name, 'StrictModeError');
assert.equal(err.message, 'Path "notInSchema" is not in schema and ' +
'strictQuery is \'throw\'.');
// acquit:ignore:end
});
});

it('implicit in', async function() {
Expand All @@ -150,4 +168,4 @@ describe('Cast Tutorial', function() {
});
// acquit:ignore:end
});
});
});