From f697ee106a95a4ea9577c976f5db872157ee432a Mon Sep 17 00:00:00 2001 From: malikj2000 <67246038+malikj2000@users.noreply.github.com> Date: Fri, 14 Jul 2023 13:11:36 -0400 Subject: [PATCH] refactor(NODE-5392): refactor cursor operations to use async/await (#3767) --- src/operations/collections.ts | 38 ++--- src/operations/execute_operation.ts | 18 +-- src/operations/find.ts | 39 +++-- src/operations/get_more.ts | 27 +--- src/operations/indexes.ts | 19 ++- src/operations/kill_cursors.ts | 32 ++-- src/operations/list_collections.ts | 23 ++- src/operations/list_databases.ts | 22 ++- src/operations/operation.ts | 1 + .../collection-management/collection.test.ts | 143 +++--------------- .../collection_db_management.test.ts | 104 +++++-------- test/unit/operations/get_more.test.ts | 11 +- 12 files changed, 160 insertions(+), 317 deletions(-) diff --git a/src/operations/collections.ts b/src/operations/collections.ts index 3047e84535..e799135736 100644 --- a/src/operations/collections.ts +++ b/src/operations/collections.ts @@ -2,15 +2,14 @@ import { Collection } from '../collection'; import type { Db } from '../db'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; -import type { Callback } from '../utils'; -import { AbstractCallbackOperation, type OperationOptions } from './operation'; +import { AbstractOperation, type OperationOptions } from './operation'; export interface CollectionsOptions extends OperationOptions { nameOnly?: boolean; } /** @internal */ -export class CollectionsOperation extends AbstractCallbackOperation { +export class CollectionsOperation extends AbstractOperation { override options: CollectionsOptions; db: Db; @@ -20,31 +19,22 @@ export class CollectionsOperation extends AbstractCallbackOperation - ): void { + async execute(server: Server, session: ClientSession | undefined): Promise { // Let's get the collection names - this.db + const documents = await this.db .listCollections( {}, { ...this.options, nameOnly: true, readPreference: this.readPreference, session } ) - .toArray() - .then( - documents => { - const collections = []; - for (const { name } of documents) { - if (!name.includes('$')) { - // Filter collections removing any illegal ones - collections.push(new Collection(this.db, name, this.db.s.options)); - } - } - // Return the collection objects - callback(undefined, collections); - }, - error => callback(error) - ); + .toArray(); + const collections: Collection[] = []; + for (const { name } of documents) { + if (!name.includes('$')) { + // Filter collections removing any illegal ones + collections.push(new Collection(this.db, name, this.db.s.options)); + } + } + // Return the collection objects + return collections; } } diff --git a/src/operations/execute_operation.ts b/src/operations/execute_operation.ts index bfaf0bb406..50f77648f9 100644 --- a/src/operations/execute_operation.ts +++ b/src/operations/execute_operation.ts @@ -25,13 +25,13 @@ import { import type { Topology } from '../sdam/topology'; import type { ClientSession } from '../sessions'; import { type Callback, maybeCallback, supportsRetryableWrites } from '../utils'; -import { AbstractCallbackOperation, Aspect } from './operation'; +import { AbstractOperation, Aspect } from './operation'; const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES.IllegalOperation; const MMAPv1_RETRY_WRITES_ERROR_MESSAGE = 'This MongoDB deployment does not support retryable writes. Please add retryWrites=false to your connection string.'; -type ResultTypeFromOperation = TOperation extends AbstractCallbackOperation +type ResultTypeFromOperation = TOperation extends AbstractOperation ? K : never; @@ -61,29 +61,29 @@ export interface ExecutionResult { * @param callback - The command result callback */ export function executeOperation< - T extends AbstractCallbackOperation, + T extends AbstractOperation, TResult = ResultTypeFromOperation >(client: MongoClient, operation: T): Promise; export function executeOperation< - T extends AbstractCallbackOperation, + T extends AbstractOperation, TResult = ResultTypeFromOperation >(client: MongoClient, operation: T, callback: Callback): void; export function executeOperation< - T extends AbstractCallbackOperation, + T extends AbstractOperation, TResult = ResultTypeFromOperation >(client: MongoClient, operation: T, callback?: Callback): Promise | void; export function executeOperation< - T extends AbstractCallbackOperation, + T extends AbstractOperation, TResult = ResultTypeFromOperation >(client: MongoClient, operation: T, callback?: Callback): Promise | void { return maybeCallback(() => executeOperationAsync(client, operation), callback); } async function executeOperationAsync< - T extends AbstractCallbackOperation, + T extends AbstractOperation, TResult = ResultTypeFromOperation >(client: MongoClient, operation: T): Promise { - if (!(operation instanceof AbstractCallbackOperation)) { + if (!(operation instanceof AbstractOperation)) { // TODO(NODE-3483): Extend MongoRuntimeError throw new MongoRuntimeError('This method requires a valid operation instance'); } @@ -209,7 +209,7 @@ type RetryOptions = { }; async function retryOperation< - T extends AbstractCallbackOperation, + T extends AbstractOperation, TResult = ResultTypeFromOperation >( operation: T, diff --git a/src/operations/find.ts b/src/operations/find.ts index fd3d41e8c8..731c661c29 100644 --- a/src/operations/find.ts +++ b/src/operations/find.ts @@ -11,11 +11,7 @@ import { type MongoDBNamespace, normalizeHintField } from '../utils'; -import { - type CollationOptions, - CommandCallbackOperation, - type CommandOperationOptions -} from './command'; +import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects, type Hint } from './operation'; /** @@ -75,7 +71,7 @@ export interface FindOptions } /** @internal */ -export class FindOperation extends CommandCallbackOperation { +export class FindOperation extends CommandOperation { /** * @remarks WriteConcern can still be present on the options because * we inherit options from the client/db/collection. The @@ -106,11 +102,7 @@ export class FindOperation extends CommandCallbackOperation { this.filter = filter != null && filter._bsontype === 'ObjectId' ? { _id: filter } : filter; } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + override async execute(server: Server, session: ClientSession | undefined): Promise { this.server = server; const options = this.options; @@ -120,17 +112,20 @@ export class FindOperation extends CommandCallbackOperation { findCommand = decorateWithExplain(findCommand, this.explain); } - server.command( - this.ns, - findCommand, - { - ...this.options, - ...this.bsonOptions, - documentsReturnedIn: 'firstBatch', - session - }, - callback - ); + return server.commandAsync(this.ns, findCommand, { + ...this.options, + ...this.bsonOptions, + documentsReturnedIn: 'firstBatch', + session + }); + } + + protected executeCallback( + _server: Server, + _session: ClientSession | undefined, + _callback: Callback + ): void { + throw new Error('Method not implemented.'); } } diff --git a/src/operations/get_more.ts b/src/operations/get_more.ts index 0169e0a67f..e2e6f86f32 100644 --- a/src/operations/get_more.ts +++ b/src/operations/get_more.ts @@ -2,13 +2,8 @@ import type { Document, Long } from '../bson'; import { MongoRuntimeError } from '../error'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; -import { type Callback, maxWireVersion, type MongoDBNamespace } from '../utils'; -import { - AbstractCallbackOperation, - Aspect, - defineAspects, - type OperationOptions -} from './operation'; +import { maxWireVersion, type MongoDBNamespace } from '../utils'; +import { AbstractOperation, Aspect, defineAspects, type OperationOptions } from './operation'; /** @internal */ export interface GetMoreOptions extends OperationOptions { @@ -40,7 +35,7 @@ export interface GetMoreCommand { } /** @internal */ -export class GetMoreOperation extends AbstractCallbackOperation { +export class GetMoreOperation extends AbstractOperation { cursorId: Long; override options: GetMoreOptions; @@ -57,26 +52,20 @@ export class GetMoreOperation extends AbstractCallbackOperation { * Although there is a server already associated with the get more operation, the signature * for execute passes a server so we will just use that one. */ - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + async execute(server: Server, _session: ClientSession | undefined): Promise { if (server !== this.server) { - return callback( - new MongoRuntimeError('Getmore must run on the same server operation began on') - ); + throw new MongoRuntimeError('Getmore must run on the same server operation began on'); } if (this.cursorId == null || this.cursorId.isZero()) { - return callback(new MongoRuntimeError('Unable to iterate cursor with no id')); + throw new MongoRuntimeError('Unable to iterate cursor with no id'); } const collection = this.ns.collection; if (collection == null) { // Cursors should have adopted the namespace returned by MongoDB // which should always defined a collection name (even a pseudo one, ex. db.aggregate()) - return callback(new MongoRuntimeError('A collection name must be determined before getMore')); + throw new MongoRuntimeError('A collection name must be determined before getMore'); } const getMoreCmd: GetMoreCommand = { @@ -104,7 +93,7 @@ export class GetMoreOperation extends AbstractCallbackOperation { ...this.options }; - server.command(this.ns, getMoreCmd, commandOptions, callback); + return server.commandAsync(this.ns, getMoreCmd, commandOptions); } } diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index 93b68f0718..481cdda7f4 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -10,6 +10,7 @@ import { type Callback, isObject, maxWireVersion, type MongoDBNamespace } from ' import { type CollationOptions, CommandCallbackOperation, + CommandOperation, type CommandOperationOptions, type OperationParent } from './command'; @@ -396,7 +397,7 @@ export interface ListIndexesOptions extends Omit { +export class ListIndexesOperation extends CommandOperation { /** * @remarks WriteConcern can still be present on the options because * we inherit options from the client/db/collection. The @@ -415,11 +416,7 @@ export class ListIndexesOperation extends CommandCallbackOperation { this.collectionNamespace = collection.s.namespace; } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + override async execute(server: Server, session: ClientSession | undefined): Promise { const serverWireVersion = maxWireVersion(server); const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {}; @@ -432,7 +429,15 @@ export class ListIndexesOperation extends CommandCallbackOperation { command.comment = this.options.comment; } - super.executeCommandCallback(server, session, command, callback); + return super.executeCommand(server, session, command); + } + + protected executeCallback( + _server: Server, + _session: ClientSession | undefined, + _callback: Callback + ): void { + throw new Error('Method not implemented.'); } } diff --git a/src/operations/kill_cursors.ts b/src/operations/kill_cursors.ts index 2527bf2004..34f2d2211f 100644 --- a/src/operations/kill_cursors.ts +++ b/src/operations/kill_cursors.ts @@ -2,13 +2,8 @@ import type { Long } from '../bson'; import { MongoRuntimeError } from '../error'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; -import type { Callback, MongoDBNamespace } from '../utils'; -import { - AbstractCallbackOperation, - Aspect, - defineAspects, - type OperationOptions -} from './operation'; +import type { MongoDBNamespace } from '../utils'; +import { AbstractOperation, Aspect, defineAspects, type OperationOptions } from './operation'; /** * https://www.mongodb.com/docs/manual/reference/command/killCursors/ @@ -20,7 +15,7 @@ interface KillCursorsCommand { comment?: unknown; } -export class KillCursorsOperation extends AbstractCallbackOperation { +export class KillCursorsOperation extends AbstractOperation { cursorId: Long; constructor(cursorId: Long, ns: MongoDBNamespace, server: Server, options: OperationOptions) { @@ -30,32 +25,27 @@ export class KillCursorsOperation extends AbstractCallbackOperation { this.server = server; } - executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback - ): void { + async execute(server: Server, session: ClientSession | undefined): Promise { if (server !== this.server) { - return callback( - new MongoRuntimeError('Killcursor must run on the same server operation began on') - ); + throw new MongoRuntimeError('Killcursor must run on the same server operation began on'); } const killCursors = this.ns.collection; if (killCursors == null) { // Cursors should have adopted the namespace returned by MongoDB // which should always defined a collection name (even a pseudo one, ex. db.aggregate()) - return callback( - new MongoRuntimeError('A collection name must be determined before killCursors') - ); + throw new MongoRuntimeError('A collection name must be determined before killCursors'); } const killCursorsCommand: KillCursorsCommand = { killCursors, cursors: [this.cursorId] }; - - server.command(this.ns, killCursorsCommand, { session }, () => callback()); + try { + await server.commandAsync(this.ns, killCursorsCommand, { session }); + } catch { + // The driver should never emit errors from killCursors, this is spec-ed behavior + } } } diff --git a/src/operations/list_collections.ts b/src/operations/list_collections.ts index dddd4db274..871fd6c768 100644 --- a/src/operations/list_collections.ts +++ b/src/operations/list_collections.ts @@ -3,7 +3,7 @@ import type { Db } from '../db'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, maxWireVersion } from '../utils'; -import { CommandCallbackOperation, type CommandOperationOptions } from './command'; +import { CommandOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -17,7 +17,7 @@ export interface ListCollectionsOptions extends Omit { +export class ListCollectionsOperation extends CommandOperation { /** * @remarks WriteConcern can still be present on the options because * we inherit options from the client/db/collection. The @@ -47,17 +47,16 @@ export class ListCollectionsOperation extends CommandCallbackOperation } } - override executeCallback( - server: Server, - session: ClientSession | undefined, - callback: Callback + override async execute(server: Server, session: ClientSession | undefined): Promise { + return super.executeCommand(server, session, this.generateCommand(maxWireVersion(server))); + } + + protected executeCallback( + _server: Server, + _session: ClientSession | undefined, + _callback: Callback ): void { - return super.executeCommandCallback( - server, - session, - this.generateCommand(maxWireVersion(server)), - callback - ); + throw new Error('Method not implemented.'); } /* This is here for the purpose of unit testing the final command that gets sent. */ diff --git a/src/operations/list_databases.ts b/src/operations/list_databases.ts index 8605e0661a..b6c6288223 100644 --- a/src/operations/list_databases.ts +++ b/src/operations/list_databases.ts @@ -1,9 +1,10 @@ import type { Document } from '../bson'; import type { Db } from '../db'; +import { type TODO_NODE_3286 } from '../mongo_types'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; import { type Callback, maxWireVersion, MongoDBNamespace } from '../utils'; -import { CommandCallbackOperation, type CommandOperationOptions } from './command'; +import { CommandOperation, type CommandOperationOptions } from './command'; import { Aspect, defineAspects } from './operation'; /** @public */ @@ -25,7 +26,7 @@ export interface ListDatabasesOptions extends CommandOperationOptions { } /** @internal */ -export class ListDatabasesOperation extends CommandCallbackOperation { +export class ListDatabasesOperation extends CommandOperation { override options: ListDatabasesOptions; constructor(db: Db, options?: ListDatabasesOptions) { @@ -34,11 +35,10 @@ export class ListDatabasesOperation extends CommandCallbackOperation - ): void { + session: ClientSession | undefined + ): Promise { const cmd: Document = { listDatabases: 1 }; if (typeof this.options.nameOnly === 'boolean') { @@ -59,7 +59,15 @@ export class ListDatabasesOperation extends CommandCallbackOperation + ): void { + throw new Error('Method not implemented.'); } } diff --git a/src/operations/operation.ts b/src/operations/operation.ts index deb53bd7f4..43d84c2cdc 100644 --- a/src/operations/operation.ts +++ b/src/operations/operation.ts @@ -123,6 +123,7 @@ export abstract class AbstractCallbackOperation extends AbstractO callback: Callback ): void; } + export function defineAspects( operation: OperationConstructor, aspects: symbol | symbol[] | Set diff --git a/test/integration/collection-management/collection.test.ts b/test/integration/collection-management/collection.test.ts index 47a1e40d30..0a9d240110 100644 --- a/test/integration/collection-management/collection.test.ts +++ b/test/integration/collection-management/collection.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { type Collection, type Db, isHello, type MongoClient } from '../../mongodb'; +import { Collection, type Db, isHello, type MongoClient } from '../../mongodb'; import * as mock from '../../tools/mongodb-mock/index'; import { setupDatabase } from '../shared'; @@ -12,8 +12,8 @@ describe('Collection', function () { }); describe('standard collection tests', function () { - let client; - let db; + let client: MongoClient; + let db: Db; beforeEach(function () { client = configuration.newClient(configuration.writeConcernMax(), { maxPoolSize: 1 @@ -26,90 +26,16 @@ describe('Collection', function () { await client.close(); }); - it('should correctly execute basic collection methods', function (done) { - db.createCollection('test_collection_methods', (err, collection) => { - // Verify that all the result are correct coming back (should contain the value ok) - expect(collection.collectionName).to.equal('test_collection_methods'); - // Let's check that the collection was created correctly - db.listCollections().toArray((err, documents) => { - expect(err).to.not.exist; - let found = false; - documents.forEach(doc => { - if (doc.name === 'test_collection_methods') found = true; - }); - expect(found).to.be.true; - // Rename the collection and check that it's gone - db.renameCollection('test_collection_methods', 'test_collection_methods2', err => { - expect(err).to.not.exist; - // Drop the collection and check that it's gone - db.dropCollection('test_collection_methods2', (err, result) => { - expect(result).to.be.true; - }); - - db.createCollection('test_collection_methods3', (err, collection) => { - // Verify that all the result are correct coming back (should contain the value ok) - expect(collection.collectionName).to.equal('test_collection_methods3'); - - db.createCollection('test_collection_methods4', (err, collection) => { - // Verify that all the result are correct coming back (should contain the value ok) - expect(collection.collectionName).to.equal('test_collection_methods4'); - // Rename the collection and with the dropTarget boolean, and check to make sure only onen exists. - db.renameCollection( - 'test_collection_methods4', - 'test_collection_methods3', - { dropTarget: true }, - err => { - expect(err).to.not.exist; - - db.dropCollection('test_collection_methods3', (err, result) => { - expect(result).to.be.true; - done(); - }); - } - ); - }); - }); - }); - }); - }); - }); - - it('should correctly access collection names', function (done) { + it('should be able to access collections by name from db.collections() array after creating two collections', async function () { // Create two collections - db.createCollection('test.spiderman', () => { - db.createCollection('test.mario', () => { - // Insert test documents (creates collections) - const spiderman_collection = db.collection('test.spiderman'); - spiderman_collection.insertOne({ foo: 5 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - const mario_collection = db.collection('test.mario'); - mario_collection.insertOne({ bar: 0 }, configuration.writeConcernMax(), err => { - expect(err).to.not.exist; - // Assert collections - db.collections((err, collections) => { - expect(err).to.not.exist; - - let found_spiderman = false; - let found_mario = false; - let found_does_not_exist = false; - - collections.forEach(collection => { - if (collection.collectionName === 'test.spiderman') { - found_spiderman = true; - } - if (collection.collectionName === 'test.mario') found_mario = true; - if (collection.collectionName === 'does_not_exist') found_does_not_exist = true; - }); - - expect(found_spiderman).to.be.true; - expect(found_mario).to.be.true; - expect(found_does_not_exist).to.be.false; - done(); - }); - }); - }); - }); - }); + await db.createCollection('test.spiderman'); + await db.createCollection('test.mario'); + const collections = await db.collections(); + const nameArray = collections.map(col => col.collectionName); + expect(nameArray).to.include('test.spiderman'); + expect(nameArray).to.include('test.mario'); + expect(collections[0]).to.be.instanceOf(Collection); + expect(collections[1]).to.be.instanceOf(Collection); }); it('should correctly retrieve listCollections', function (done) { @@ -404,40 +330,19 @@ describe('Collection', function () { }); }); - it('should correctly handle namespace when using collections method', function (done) { + it('should create and access collection given the name and namespace as specified, including dots', async function () { const emptyDb = client.db('listCollectionsDb2'); - emptyDb.createCollection('test1', err => { - expect(err).to.not.exist; - - emptyDb.createCollection('test.test', err => { - expect(err).to.not.exist; - - emptyDb.createCollection('test3', err => { - expect(err).to.not.exist; - - emptyDb.collections((err, collections) => { - collections = collections.map(collection => { - return { - collectionName: collection.collectionName, - namespace: collection.namespace - }; - }); - - let foundCollection = false; - collections.forEach(x => { - if ( - x.namespace === 'listCollectionsDb2.test.test' && - x.collectionName === 'test.test' - ) { - foundCollection = true; - } - }); - - expect(foundCollection).to.be.true; - done(); - }); - }); - }); + await emptyDb.createCollection('test.test'); + const collections = await emptyDb.collections(); + const collection_rename = collections.map(collection => { + return { + collectionName: collection.collectionName, + namespace: collection.namespace + }; + }); + expect(collection_rename).to.deep.include({ + collectionName: 'test.test', + namespace: 'listCollectionsDb2.test.test' }); }); diff --git a/test/integration/collection-management/collection_db_management.test.ts b/test/integration/collection-management/collection_db_management.test.ts index fc1057fbfd..f5c4c55cf0 100644 --- a/test/integration/collection-management/collection_db_management.test.ts +++ b/test/integration/collection-management/collection_db_management.test.ts @@ -1,83 +1,47 @@ -import { assert as test, setupDatabase } from '../shared'; +import { expect } from 'chai'; -describe('Collection Management and Db Management', function () { - before(function () { - return setupDatabase(this.configuration); - }); +import { Collection, type Db, type MongoClient } from '../../mongodb'; - it('Should correctly createCollection using Promise', function (done) { - const configuration = this.configuration; - const client = configuration.newClient({}, { maxPoolSize: 5 }); - - client - .db(configuration.db) - .createCollection('promiseCollection') - .then(function (col) { - test.ok(col != null); +describe('Collection Management and Db Management', function () { + let client: MongoClient; + let db: Db; - client.close(done); - }) - .catch(function (err) { - test.ok(err != null); - }); + beforeEach(function () { + client = this.configuration.newClient(); + db = client.db(); }); - it('Should correctly rename and drop collection using Promise', function (done) { - const configuration = this.configuration; - const client = configuration.newClient({}, { maxPoolSize: 5 }); - - const db = client.db(configuration.db); - - db.createCollection('promiseCollection1').then(function (col) { - test.ok(col != null); - const db = client.db(configuration.db); - - db.renameCollection('promiseCollection1', 'promiseCollection2').then(function (col) { - test.ok(col != null); - - db.dropCollection('promiseCollection2').then(function (r) { - test.ok(r); - - client.close(done); - }); - }); - }); + afterEach(async function () { + await client.close(); }); - it('Should correctly drop database using Promise', function (done) { - const configuration = this.configuration; - const client = configuration.newClient({}, { maxPoolSize: 5 }); - - client - .db(configuration.db) - .dropDatabase() - .then(function (r) { - test.ok(r); - - client.close(done); - }) - .catch(function (e) { - test.ok(e != null); - }); + it('returns a collection object after calling createCollection', async function () { + const collection = await db.createCollection('collection'); + expect(collection).to.be.instanceOf(Collection); }); - it('Should correctly createCollections and call collections with Promise', function (done) { - const configuration = this.configuration; - const client = configuration.newClient({}, { maxPoolSize: 5 }); - const db = client.db(configuration.db); - - db.createCollection('promiseCollectionCollections1').then(function (col) { - test.ok(col != null); - - db.createCollection('promiseCollectionCollections2').then(function (col) { - test.ok(col != null); + it('creates a collection named collection1, renames collection1 to collection2, and returns true after calling dropCollection on collection2', async function () { + const createCollection = await db.createCollection('collection1'); + expect(createCollection).to.be.instanceOf(Collection); + const renameCollection = await db.renameCollection('collection1', 'collection2'); + expect(renameCollection).to.be.instanceOf(Collection); + expect(renameCollection).to.have.nested.property('s.namespace.collection').equal('collection2'); + const dropCollection = await db.dropCollection('collection2'); + expect(dropCollection).to.be.true; + }); - db.collections().then(function (r) { - test.ok(Array.isArray(r)); + it('returns true after calling dropDatabase', async function () { + const dropCollection = await db.dropDatabase(); + expect(dropCollection).to.be.true; + }); - client.close(done); - }); - }); - }); + it('creates two collections, and returns an array of length 2 after calling db.collections()', async function () { + const collection1 = await db.createCollection('promiseCollectionCollections1'); + expect(collection1).to.be.instanceOf(Collection); + const collection2 = await db.createCollection('promiseCollectionCollections2'); + expect(collection2).to.be.instanceOf(Collection); + const collectionArray = await db.collections(); + expect(collectionArray).to.be.an('array'); + expect(collectionArray).to.have.length(2); }); }); diff --git a/test/unit/operations/get_more.test.ts b/test/unit/operations/get_more.test.ts index 3abb798bc0..6385ba71c6 100644 --- a/test/unit/operations/get_more.test.ts +++ b/test/unit/operations/get_more.test.ts @@ -73,7 +73,7 @@ describe('GetMoreOperation', function () { }); context('when the server is not the same as the instance', function () { - it('errors in the callback', function (done) { + it('errors in the callback', async function () { const server1 = new Server( topologyWithPlaceholderClient([], {} as any), new ServerDescription('a:1'), @@ -87,12 +87,9 @@ describe('GetMoreOperation', function () { const session = sinon.createStubInstance(ClientSession); const opts = { ...options, session }; const operation = new GetMoreOperation(namespace, cursorId, server1, opts); - const callback = error => { - expect(error).to.be.instanceOf(MongoRuntimeError); - expect(error.message).to.equal('Getmore must run on the same server operation began on'); - done(); - }; - operation.executeCallback(server2, session, callback); + const error = await operation.execute(server2, session).catch(error => error); + expect(error).to.be.instanceOf(MongoRuntimeError); + expect(error.message).to.equal('Getmore must run on the same server operation began on'); }); });