From f8d9c7cf698cda3d41181313b3d2ecfcf153eb4e Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Fri, 29 Mar 2024 12:34:35 -0600 Subject: [PATCH 1/8] fix: share aws credential fetching logic with aws KMS and only return expected fields --- src/client-side-encryption/providers/aws.ts | 26 ++++--- test/integration/auth/mongodb_aws.test.ts | 73 +++++++++++++++---- .../providers/credentialsProvider.test.ts | 31 +++++++- 3 files changed, 105 insertions(+), 25 deletions(-) diff --git a/src/client-side-encryption/providers/aws.ts b/src/client-side-encryption/providers/aws.ts index 64aa9f0adc..b735e0a419 100644 --- a/src/client-side-encryption/providers/aws.ts +++ b/src/client-side-encryption/providers/aws.ts @@ -1,20 +1,28 @@ import { getAwsCredentialProvider } from '../../deps'; import { type KMSProviders } from '.'; +import { AWSSDKCredentialProvider } from '../../cmap/auth/aws_temporary_credentials'; /** * @internal */ export async function loadAWSCredentials(kmsProviders: KMSProviders): Promise { - const credentialProvider = getAwsCredentialProvider(); + const credentialProvider = new AWSSDKCredentialProvider(); - if ('kModuleError' in credentialProvider) { - return kmsProviders; - } + // We shouldn't ever receive a response from the AWS SDK that doesn't have a `SecretAccessKey` + // or `AccessKeyId`. However, TS says these fields are optional. We provide empty strings + // and let libmongocrypt error if we're unable to fetch the required keys. + const { + SecretAccessKey = '', + AccessKeyId = '', + Token + } = await credentialProvider.getCredentials(); + const aws: NonNullable = { + secretAccessKey: SecretAccessKey, + accessKeyId: AccessKeyId + }; + // the AWS session token is only required for temporary credentials so only attach it to the + // result if it's present in the response from the aws sdk + Token != null && (aws.sessionToken = Token); - const { fromNodeProviderChain } = credentialProvider; - const provider = fromNodeProviderChain(); - // The state machine is the only place calling this so it will - // catch if there is a rejection here. - const aws = await provider(); return { ...kmsProviders, aws }; } diff --git a/test/integration/auth/mongodb_aws.test.ts b/test/integration/auth/mongodb_aws.test.ts index a96ed91d53..2c0070e1db 100644 --- a/test/integration/auth/mongodb_aws.test.ts +++ b/test/integration/auth/mongodb_aws.test.ts @@ -5,30 +5,26 @@ import * as http from 'http'; import { performance } from 'perf_hooks'; import * as sinon from 'sinon'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports +import { KMSCredentialProvider, refreshKMSCredentials } from '../../../src/client-side-encryption/providers'; import { AWSTemporaryCredentialProvider, MongoAWSError, type MongoClient, MongoDBAWS, MongoMissingCredentialsError, - MongoServerError + MongoServerError, + setDifference } from '../../mongodb'; -function awsSdk() { - try { - return require('@aws-sdk/credential-providers'); - } catch { - return null; - } -} +const isMongoDBAWSAuthEnvironment = (process.env.MONGODB_URI ?? '').includes('MONGODB_AWS'); describe('MONGODB-AWS', function () { let awsSdkPresent; let client: MongoClient; beforeEach(function () { - const MONGODB_URI = process.env.MONGODB_URI; - if (!MONGODB_URI || MONGODB_URI.indexOf('MONGODB-AWS') === -1) { + if (!isMongoDBAWSAuthEnvironment) { this.currentTest.skipReason = 'requires MONGODB_URI to contain MONGODB-AWS auth mechanism'; return this.skip(); } @@ -39,7 +35,7 @@ describe('MONGODB-AWS', function () { `Always inform the AWS tests if they run with or without the SDK (MONGODB_AWS_SDK=${MONGODB_AWS_SDK})` ).to.include(MONGODB_AWS_SDK); - awsSdkPresent = !!awsSdk(); + awsSdkPresent = AWSTemporaryCredentialProvider.isAWSSDKInstalled; expect( awsSdkPresent, MONGODB_AWS_SDK === 'true' @@ -244,8 +240,10 @@ describe('MONGODB-AWS', function () { const envCheck = () => { const { AWS_WEB_IDENTITY_TOKEN_FILE = '' } = process.env; - credentialProvider = awsSdk(); - return AWS_WEB_IDENTITY_TOKEN_FILE.length === 0 || credentialProvider == null; + return ( + AWS_WEB_IDENTITY_TOKEN_FILE.length === 0 || + !AWSTemporaryCredentialProvider.isAWSSDKInstalled + ); }; beforeEach(function () { @@ -255,6 +253,9 @@ describe('MONGODB-AWS', function () { return this.skip(); } + // @ts-expect-error We intentionally access a protected variable. + credentialProvider = AWSTemporaryCredentialProvider.awsSDK; + storedEnv = process.env; if (test.env.AWS_STS_REGIONAL_ENDPOINTS === undefined) { delete process.env.AWS_STS_REGIONAL_ENDPOINTS; @@ -324,3 +325,49 @@ describe('MONGODB-AWS', function () { } }); }); + +describe('AWS KMS Credential Fetching', function () { + context('when the AWS SDK is not installed', function () { + beforeEach(function () { + this.currentTest.skipReason = !isMongoDBAWSAuthEnvironment + ? 'Test must run in an AWS auth testing environment' + : AWSTemporaryCredentialProvider.isAWSSDKInstalled + ? 'This test must run in an environment where the AWS SDK is not installed.' + : undefined; + this.currentTest?.skipReason && this.skip(); + }); + it('fetching AWS KMS credentials throws an error', async function () { + const error = await new KMSCredentialProvider({ aws: {} }).refreshCredentials().catch(e => e); + expect(error).to.be.instanceOf(MongoAWSError); + }); + }); + + context('when the AWS SDK is installed', function () { + beforeEach(function () { + this.currentTest.skipReason = !isMongoDBAWSAuthEnvironment + ? 'Test must run in an AWS auth testing environment' + : AWSTemporaryCredentialProvider.isAWSSDKInstalled + ? 'This test must run in an environment where the AWS SDK is installed.' + : undefined; + this.currentTest?.skipReason && this.skip(); + }); + it('KMS credentials are successfully fetched.', async function () { + const { aws } = await refreshKMSCredentials({ aws: {} }); + + expect(aws).to.have.property('accessKeyId'); + expect(aws).to.have.property('secretAccessKey'); + }); + + it('does not return any extra keys for the `aws` credential provider', async function () { + const { aws } = await refreshKMSCredentials({ aws: {} }); + + const keys = new Set(Object.keys(aws ?? {})); + const allowedKeys = ['accessKeyId', 'secretAccessKey', 'sessionToken']; + + expect( + setDifference(keys, allowedKeys), + 'received an unexpected key in the response refreshing KMS credentials' + ).to.deep.equal([]); + }); + }); +}); diff --git a/test/unit/client-side-encryption/providers/credentialsProvider.test.ts b/test/unit/client-side-encryption/providers/credentialsProvider.test.ts index ddd9c87b45..7d625e4bf4 100644 --- a/test/unit/client-side-encryption/providers/credentialsProvider.test.ts +++ b/test/unit/client-side-encryption/providers/credentialsProvider.test.ts @@ -21,6 +21,8 @@ import { // eslint-disable-next-line @typescript-eslint/no-restricted-imports import * as utils from '../../../../src/client-side-encryption/providers/utils'; import * as requirements from '../requirements.helper'; +import { AWSSDKCredentialProvider } from '../../../../src/cmap/auth/aws_temporary_credentials'; +import { MongoAWSError } from '../../../../src/error'; const originalAccessKeyId = process.env.AWS_ACCESS_KEY_ID; const originalSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; @@ -170,9 +172,32 @@ describe('#refreshKMSCredentials', function () { } }); - it('does not refresh credentials', async function () { - const providers = await refreshKMSCredentials(kmsProviders); - expect(providers).to.deep.equal(kmsProviders); + it('throws a MongoAWSError', async function () { + const error = await refreshKMSCredentials(kmsProviders).catch(e => e); + const expectedErrorMessage = 'Optional module `@aws-sdk/credential-providers` not found'; + expect(error).to.be.instanceOf(MongoAWSError).to.match(new RegExp(expectedErrorMessage, 'i')); + }); + }); + + context('when the AWS SDK returns unknown fields', function () { + beforeEach(() => { + sinon.stub(AWSSDKCredentialProvider.prototype, 'getCredentials').resolves({ + Token: 'example', + SecretAccessKey: 'example', + AccessKeyId: 'example', + Expiration: new Date() + }); + }); + afterEach(() => sinon.restore()); + it('only returns fields libmongocrypt expects', async function () { + const credentials = await refreshKMSCredentials({ aws: {} }); + expect(credentials).to.deep.equal({ + aws: { + accessKeyId: accessKey, + secretAccessKey: secretKey, + sessionToken: sessionToken + } + }); }); }); }); From 53219993853c3cc37ad94272a2a6f995a2be95e7 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Fri, 29 Mar 2024 12:35:02 -0600 Subject: [PATCH 2/8] chore: better skipping of failing unit tests on NOde18+ --- ...ling_srv_records_for_mongos_discovery.prose.test.ts | 10 ++++------ test/unit/connection_string.spec.test.ts | 5 ++--- test/unit/sdam/monitor.test.ts | 5 ++--- test/unit/sdam/topology.test.ts | 10 ++++------ 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/test/unit/assorted/polling_srv_records_for_mongos_discovery.prose.test.ts b/test/unit/assorted/polling_srv_records_for_mongos_discovery.prose.test.ts index d60a81d034..8ec5cd8e29 100644 --- a/test/unit/assorted/polling_srv_records_for_mongos_discovery.prose.test.ts +++ b/test/unit/assorted/polling_srv_records_for_mongos_discovery.prose.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as dns from 'dns'; import { once } from 'events'; -import { coerce } from 'semver'; +import { satisfies } from 'semver'; import * as sinon from 'sinon'; import { @@ -51,11 +51,9 @@ describe('Polling Srv Records for Mongos Discovery', () => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const test = this.currentTest!; - const { major } = coerce(process.version); - test.skipReason = - major === 18 || major === 20 - ? 'TODO(NODE-5666): fix failing unit tests on Node18' - : undefined; + test.skipReason = satisfies(process.version, '>=18.0.0') + ? `TODO(NODE-5666): fix failing unit tests on Node18 (Running with Nodejs ${process.version})` + : undefined; if (test.skipReason) this.skip(); }); diff --git a/test/unit/connection_string.spec.test.ts b/test/unit/connection_string.spec.test.ts index cc4fbb7c69..a1b623dfeb 100644 --- a/test/unit/connection_string.spec.test.ts +++ b/test/unit/connection_string.spec.test.ts @@ -1,4 +1,4 @@ -import { coerce } from 'semver'; +import { satisfies } from 'semver'; import { loadSpecTests } from '../spec'; import { executeUriValidationTest } from '../tools/uri_spec_runner'; @@ -15,13 +15,12 @@ describe('Connection String spec tests', function () { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const test = this.currentTest!; - const { major } = coerce(process.version); const skippedTests = [ 'Invalid port (zero) with IP literal', 'Invalid port (zero) with hostname' ]; test.skipReason = - major === 20 && skippedTests.includes(test.title) + satisfies(process.version, '>=20.0.0') && skippedTests.includes(test.title) ? 'TODO(NODE-5666): fix failing unit tests on Node18' : undefined; diff --git a/test/unit/sdam/monitor.test.ts b/test/unit/sdam/monitor.test.ts index 3c6e02a134..c1bd8dc33c 100644 --- a/test/unit/sdam/monitor.test.ts +++ b/test/unit/sdam/monitor.test.ts @@ -1,7 +1,7 @@ import * as net from 'node:net'; import { expect } from 'chai'; -import { coerce } from 'semver'; +import { satisfies } from 'semver'; import * as sinon from 'sinon'; import { setTimeout } from 'timers'; @@ -49,7 +49,6 @@ describe('monitoring', function () { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const test = this.currentTest!; - const { major } = coerce(process.version); const failingTests = [ 'should connect and issue an initial server check', 'should ignore attempts to connect when not already closed', @@ -58,7 +57,7 @@ describe('monitoring', function () { 'should upgrade to hello from legacy hello when initial handshake contains helloOk' ]; test.skipReason = - (major === 18 || major === 20) && failingTests.includes(test.title) + satisfies(process.version, '>=18.0.0') && failingTests.includes(test.title) ? 'TODO(NODE-5666): fix failing unit tests on Node18' : undefined; diff --git a/test/unit/sdam/topology.test.ts b/test/unit/sdam/topology.test.ts index c6511d27c4..e4a34417d5 100644 --- a/test/unit/sdam/topology.test.ts +++ b/test/unit/sdam/topology.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { once } from 'events'; import * as net from 'net'; import { type AddressInfo } from 'net'; -import { coerce, type SemVer } from 'semver'; +import { satisfies } from 'semver'; import * as sinon from 'sinon'; import { clearTimeout } from 'timers'; @@ -284,11 +284,9 @@ describe('Topology (unit)', function () { it('should encounter a server selection timeout on garbled server responses', function () { const test = this.test; - const { major } = coerce(process.version) as SemVer; - test.skipReason = - major === 18 || major === 20 - ? 'TODO(NODE-5666): fix failing unit tests on Node18' - : undefined; + test.skipReason = satisfies(process.version, '>=18.0.0') + ? 'TODO(NODE-5666): fix failing unit tests on Node18' + : undefined; if (test.skipReason) this.skip(); From a70299093277e2f7adac7d65e5e748bbf5bd0acb Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Fri, 29 Mar 2024 14:09:42 -0600 Subject: [PATCH 3/8] fix tests --- src/client-side-encryption/providers/aws.ts | 3 +-- test/integration/auth/mongodb_aws.test.ts | 6 ++--- .../providers/credentialsProvider.test.ts | 27 ++----------------- 3 files changed, 6 insertions(+), 30 deletions(-) diff --git a/src/client-side-encryption/providers/aws.ts b/src/client-side-encryption/providers/aws.ts index b735e0a419..240e560bd9 100644 --- a/src/client-side-encryption/providers/aws.ts +++ b/src/client-side-encryption/providers/aws.ts @@ -1,6 +1,5 @@ -import { getAwsCredentialProvider } from '../../deps'; -import { type KMSProviders } from '.'; import { AWSSDKCredentialProvider } from '../../cmap/auth/aws_temporary_credentials'; +import { type KMSProviders } from '.'; /** * @internal diff --git a/test/integration/auth/mongodb_aws.test.ts b/test/integration/auth/mongodb_aws.test.ts index 2c0070e1db..b3ea2b8a06 100644 --- a/test/integration/auth/mongodb_aws.test.ts +++ b/test/integration/auth/mongodb_aws.test.ts @@ -6,7 +6,7 @@ import { performance } from 'perf_hooks'; import * as sinon from 'sinon'; // eslint-disable-next-line @typescript-eslint/no-restricted-imports -import { KMSCredentialProvider, refreshKMSCredentials } from '../../../src/client-side-encryption/providers'; +import { refreshKMSCredentials } from '../../../src/client-side-encryption/providers'; import { AWSTemporaryCredentialProvider, MongoAWSError, @@ -17,7 +17,7 @@ import { setDifference } from '../../mongodb'; -const isMongoDBAWSAuthEnvironment = (process.env.MONGODB_URI ?? '').includes('MONGODB_AWS'); +const isMongoDBAWSAuthEnvironment = (process.env.MONGODB_URI ?? '').includes('MONGODB-AWS'); describe('MONGODB-AWS', function () { let awsSdkPresent; @@ -337,7 +337,7 @@ describe('AWS KMS Credential Fetching', function () { this.currentTest?.skipReason && this.skip(); }); it('fetching AWS KMS credentials throws an error', async function () { - const error = await new KMSCredentialProvider({ aws: {} }).refreshCredentials().catch(e => e); + const error = await refreshKMSCredentials({ aws: {} }).catch(e => e); expect(error).to.be.instanceOf(MongoAWSError); }); }); diff --git a/test/unit/client-side-encryption/providers/credentialsProvider.test.ts b/test/unit/client-side-encryption/providers/credentialsProvider.test.ts index 7d625e4bf4..486fb41c60 100644 --- a/test/unit/client-side-encryption/providers/credentialsProvider.test.ts +++ b/test/unit/client-side-encryption/providers/credentialsProvider.test.ts @@ -20,9 +20,9 @@ import { } from '../../../../src/client-side-encryption/providers/azure'; // eslint-disable-next-line @typescript-eslint/no-restricted-imports import * as utils from '../../../../src/client-side-encryption/providers/utils'; -import * as requirements from '../requirements.helper'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports import { AWSSDKCredentialProvider } from '../../../../src/cmap/auth/aws_temporary_credentials'; -import { MongoAWSError } from '../../../../src/error'; +import * as requirements from '../requirements.helper'; const originalAccessKeyId = process.env.AWS_ACCESS_KEY_ID; const originalSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; @@ -156,29 +156,6 @@ describe('#refreshKMSCredentials', function () { }); }); - context('when the sdk is not installed', function () { - const kmsProviders = { - local: { - key: Buffer.alloc(96) - }, - aws: {} - }; - - before(function () { - if (requirements.credentialProvidersInstalled.aws && this.currentTest) { - this.currentTest.skipReason = 'Credentials will be loaded when sdk present'; - this.currentTest.skip(); - return; - } - }); - - it('throws a MongoAWSError', async function () { - const error = await refreshKMSCredentials(kmsProviders).catch(e => e); - const expectedErrorMessage = 'Optional module `@aws-sdk/credential-providers` not found'; - expect(error).to.be.instanceOf(MongoAWSError).to.match(new RegExp(expectedErrorMessage, 'i')); - }); - }); - context('when the AWS SDK returns unknown fields', function () { beforeEach(() => { sinon.stub(AWSSDKCredentialProvider.prototype, 'getCredentials').resolves({ From fa6449dd27f0800843c3ce80a84faed44926728c Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Mon, 1 Apr 2024 11:26:49 -0600 Subject: [PATCH 4/8] Fix aws tests --- test/integration/auth/mongodb_aws.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/auth/mongodb_aws.test.ts b/test/integration/auth/mongodb_aws.test.ts index b3ea2b8a06..a5e3ea0191 100644 --- a/test/integration/auth/mongodb_aws.test.ts +++ b/test/integration/auth/mongodb_aws.test.ts @@ -346,7 +346,7 @@ describe('AWS KMS Credential Fetching', function () { beforeEach(function () { this.currentTest.skipReason = !isMongoDBAWSAuthEnvironment ? 'Test must run in an AWS auth testing environment' - : AWSTemporaryCredentialProvider.isAWSSDKInstalled + : !AWSTemporaryCredentialProvider.isAWSSDKInstalled ? 'This test must run in an environment where the AWS SDK is installed.' : undefined; this.currentTest?.skipReason && this.skip(); From 95346330832cf7454360ae219d3eb880ac722114 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Mon, 1 Apr 2024 11:35:23 -0600 Subject: [PATCH 5/8] Fix aws tests --- test/integration/auth/mongodb_aws.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/auth/mongodb_aws.test.ts b/test/integration/auth/mongodb_aws.test.ts index a5e3ea0191..5fceca50a4 100644 --- a/test/integration/auth/mongodb_aws.test.ts +++ b/test/integration/auth/mongodb_aws.test.ts @@ -365,7 +365,7 @@ describe('AWS KMS Credential Fetching', function () { const allowedKeys = ['accessKeyId', 'secretAccessKey', 'sessionToken']; expect( - setDifference(keys, allowedKeys), + Array.from(setDifference(keys, allowedKeys)), 'received an unexpected key in the response refreshing KMS credentials' ).to.deep.equal([]); }); From 642ba39607b13829bbf342be1142b1d8784ded38 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Mon, 1 Apr 2024 13:25:57 -0600 Subject: [PATCH 6/8] skip failing test --- test/integration/crud/bulk.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/crud/bulk.test.ts b/test/integration/crud/bulk.test.ts index 1f29288a23..181ef8a92e 100644 --- a/test/integration/crud/bulk.test.ts +++ b/test/integration/crud/bulk.test.ts @@ -723,7 +723,7 @@ describe('Bulk', function () { } }); - it('should correctly execute ordered batch using w:0', function (done) { + it.skip('should correctly execute ordered batch using w:0', function (done) { client.connect((err, client) => { const db = client.db(); const col = db.collection('batch_write_ordered_ops_9'); @@ -748,7 +748,7 @@ describe('Bulk', function () { client.close(done); }); }); - }); + }).skipReason = 'TODO(NODE-6060): set `moreToCome` op_msg bit when `w: 0` is specified'; it('should correctly handle single unordered batch API', function (done) { client.connect((err, client) => { From 717b17905fdb231cb49823b24de62b2ef2338bf1 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Mon, 1 Apr 2024 13:36:03 -0600 Subject: [PATCH 7/8] only skip on latest --- test/integration/crud/bulk.test.ts | 47 +++++++++++++++++------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/test/integration/crud/bulk.test.ts b/test/integration/crud/bulk.test.ts index 181ef8a92e..c479b84296 100644 --- a/test/integration/crud/bulk.test.ts +++ b/test/integration/crud/bulk.test.ts @@ -723,32 +723,37 @@ describe('Bulk', function () { } }); - it.skip('should correctly execute ordered batch using w:0', function (done) { - client.connect((err, client) => { - const db = client.db(); - const col = db.collection('batch_write_ordered_ops_9'); + it( + 'should correctly execute ordered batch using w:0', + // TODO(NODE-6060): set `moreToCome` op_msg bit when `w: 0` is specified + { requires: { mongodb: '<8.0.0' } }, + function (done) { + client.connect((err, client) => { + const db = client.db(); + const col = db.collection('batch_write_ordered_ops_9'); - const bulk = col.initializeOrderedBulkOp(); - for (let i = 0; i < 100; i++) { - bulk.insert({ a: 1 }); - } + const bulk = col.initializeOrderedBulkOp(); + for (let i = 0; i < 100; i++) { + bulk.insert({ a: 1 }); + } - bulk.find({ b: 1 }).upsert().update({ b: 1 }); - bulk.find({ c: 1 }).delete(); + bulk.find({ b: 1 }).upsert().update({ b: 1 }); + bulk.find({ c: 1 }).delete(); - bulk.execute({ writeConcern: { w: 0 } }, function (err, result) { - expect(err).to.not.exist; - test.equal(0, result.upsertedCount); - test.equal(0, result.insertedCount); - test.equal(0, result.matchedCount); - test.ok(0 === result.modifiedCount || result.modifiedCount == null); - test.equal(0, result.deletedCount); - test.equal(false, result.hasWriteErrors()); + bulk.execute({ writeConcern: { w: 0 } }, function (err, result) { + expect(err).to.not.exist; + test.equal(0, result.upsertedCount); + test.equal(0, result.insertedCount); + test.equal(0, result.matchedCount); + test.ok(0 === result.modifiedCount || result.modifiedCount == null); + test.equal(0, result.deletedCount); + test.equal(false, result.hasWriteErrors()); - client.close(done); + client.close(done); + }); }); - }); - }).skipReason = 'TODO(NODE-6060): set `moreToCome` op_msg bit when `w: 0` is specified'; + } + ); it('should correctly handle single unordered batch API', function (done) { client.connect((err, client) => { From db52e063744a6235f85a02df4350fb020db3d077 Mon Sep 17 00:00:00 2001 From: Bailey Pearson Date: Tue, 2 Apr 2024 15:55:24 -0600 Subject: [PATCH 8/8] Update test/unit/connection_string.spec.test.ts Co-authored-by: Warren James --- test/unit/connection_string.spec.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/connection_string.spec.test.ts b/test/unit/connection_string.spec.test.ts index a1b623dfeb..213b2101c9 100644 --- a/test/unit/connection_string.spec.test.ts +++ b/test/unit/connection_string.spec.test.ts @@ -21,7 +21,7 @@ describe('Connection String spec tests', function () { ]; test.skipReason = satisfies(process.version, '>=20.0.0') && skippedTests.includes(test.title) - ? 'TODO(NODE-5666): fix failing unit tests on Node18' + ? 'TODO(NODE-5666): fix failing unit tests on Node20+' : undefined; if (test.skipReason) this.skip();