Skip to content

docs(NODE-6765): sync types for findOneAndUpdate #4423

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

Merged
Prev Previous commit
Next Next commit
test(NODE-6765): findOneAndUpdate with aggregation pipeline integration
  • Loading branch information
forivall committed Feb 19, 2025
commit ac151f35b7e9317ae26f7bb594bb64fd2485b197
184 changes: 184 additions & 0 deletions test/integration/crud/find_and_modify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,190 @@ describe('Collection (#findOneAnd...)', function () {
});
});
});

context('when updating with an aggregation pipeline', function () {
context('when passing includeResultMetadata: true', function () {
let client;
let collection;

beforeEach(async function () {
client = this.configuration.newClient({}, { maxPoolSize: 1 });
collection = client.db('test').collection('findAndModifyTest');
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
});

afterEach(async function () {
await collection.drop();
await client?.close();
});

it('returns the raw result', async function () {
const result = await collection.findOneAndUpdate(
{ a: 1 },
[{ $set: { a: { $add: [0, '$a'] } } }],
{ includeResultMetadata: true }
);
expect(result.value.b).to.equal(1);
});
});

context('when no options are passed', function () {
let client;
let collection;

beforeEach(async function () {
client = this.configuration.newClient({}, { maxPoolSize: 1 });
collection = client.db('test').collection('findAndModifyTest');
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
});

afterEach(async function () {
await collection.drop();
await client?.close();
});

context('when there is a match', function () {
it('returns the modified document', async function () {
const result = await collection.findOneAndUpdate({ a: 1 }, [
{ $set: { a: { $add: [0, '$a'] } } }
]);
expect(result.b).to.equal(1);
});
});

context('when there is no match', function () {
it('returns null', async function () {
const result = await collection.findOneAndUpdate({ a: 2 }, [
{ $set: { a: { $add: [0, '$a'] } } }
]);
expect(result).to.equal(null);
});
});
});

context('when passing an object id filter', function () {
let client;
let collection;
const started: CommandStartedEvent[] = [];

beforeEach(async function () {
client = this.configuration.newClient({}, { maxPoolSize: 1, monitorCommands: true });
client.on('commandStarted', function (event) {
if (event.commandName === 'findAndModify') started.push(event);
});
collection = client.db('test').collection('findAndModifyTest');
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
});

afterEach(async function () {
await collection.drop();
await client?.close();
});

it('does not support object ids as a query predicate', async function () {
const oid = new ObjectId();
const error = await collection
.findOneAndUpdate(oid, [{ $set: { a: { $add: [0, '$a'] } } }])
.catch(error => error);
expect(error).to.be.instanceOf(MongoServerError);
expect(started).to.have.lengthOf(1);
expect(started[0].command).to.have.property('query', oid);
});
});

context('when passing in a non-primary read preference', {
metadata: {
requires: { topology: ['replicaset'] }
},
test: function () {
let client;
let collection;

beforeEach(async function () {
client = this.configuration.newClient(
{ readPreference: 'secondary' },
{ maxPoolSize: 1 }
);
collection = client.db('test').collection('findAndModifyTest');
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
});

afterEach(async function () {
await collection.drop();
await client?.close();
});

it('returns the raw result', async function () {
const result = await collection.findOneAndUpdate(
{ a: 1 },
[{ $set: { a: { $add: [0, '$a'] } } }],
{ includeResultMetadata: true }
);
expect(result.value.b).to.equal(1);
});
}
});

context('when passing in writeConcern', function () {
let client;
let collection;
const started: CommandStartedEvent[] = [];

beforeEach(async function () {
client = this.configuration.newClient({}, { maxPoolSize: 1, monitorCommands: true });
client.on('commandStarted', function (event) {
if (event.commandName === 'findAndModify') started.push(event);
});
});

afterEach(async function () {
await collection.drop();
await client?.close();
});

context('when provided at the operation level', function () {
beforeEach(async function () {
collection = client.db('test').collection('findAndModifyTest');
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
});

it('passes through the writeConcern', async function () {
await collection.findOneAndUpdate({}, [{ $set: { a: { $add: [0, '$a'] } } }], {
writeConcern: { j: 1 }
});
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
});
});

context('when provided at the collection level', function () {
beforeEach(async function () {
collection = client
.db('test')
.collection('findAndModifyTest', { writeConcern: { j: 1 } });
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
});

it('passes through the writeConcern', async function () {
await collection.findOneAndUpdate({}, [{ $set: { a: { $add: [0, '$a'] } } }]);
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
});
});

context('when provided at the db level', function () {
beforeEach(async function () {
collection = client
.db('test', { writeConcern: { j: 1 } })
.collection('findAndModifyTest');
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
});

it('passes through the writeConcern', async function () {
await collection.findOneAndUpdate({}, [{ $set: { a: { $add: [0, '$a'] } } }]);
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
});
});
});
});
});

describe('#findOneAndReplace', function () {
Expand Down