Skip to content

Commit d8ed06e

Browse files
add passing tests
1 parent cb2c0c9 commit d8ed06e

File tree

8 files changed

+1340
-0
lines changed

8 files changed

+1340
-0
lines changed

.eslintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
lib
33
test/disabled
44
!etc/docs
5+
6+
7+
test/explicit-resource-management

src/resource_management.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,29 @@ export interface AsyncDisposable {
1111
[Symbol.asyncDispose]: () => Promise<void>;
1212
}
1313

14+
/**
15+
* @public
16+
* @beta
17+
*
18+
* Attaches `Symbol.asyncDispose` methods to the MongoClient, Cursors, sessions and change streams
19+
* if Symbol.asyncDispose is defined.
20+
*
21+
* It's usually not necessary to call this method - the driver attempts to attach these methods
22+
* itself when its loaded. However, sometimes the driver may be loaded before `Symbol.asyncDispose`
23+
* is defined, in which case it is necessary to call this method directly. This can happen if the
24+
* application is polyfilling `Symbol.asyncDispose`.
25+
*
26+
* Example:
27+
*
28+
* ```typescript
29+
* import { load, MongoClient } from 'mongodb/beta';
30+
*
31+
* Symbol.asyncDispose ??= Symbol('dispose');
32+
* load();
33+
*
34+
* await using client = new MongoClient(...);
35+
* ```
36+
*/
1437
export function load() {
1538
Symbol.asyncDispose &&
1639
(MongoClient.prototype[Symbol.asyncDispose] = async function () {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.js
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/mocharc.json",
3+
"extension": [
4+
"js"
5+
],
6+
"reporter": "../tools/reporter/mongodb_reporter.js",
7+
"recursive": true,
8+
"timeout": 60000,
9+
"failZero": true,
10+
"sort": true,
11+
"color": true
12+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
2+
import { expect } from 'chai';
3+
import { describe, it } from 'mocha';
4+
import { AbstractCursor, ChangeStream, ClientSession, GridFSBucket, MongoClient } from 'mongodb/lib/beta';
5+
import * as sinon from 'sinon';
6+
import { Readable } from 'stream';
7+
import { pipeline } from 'stream/promises';
8+
import { setTimeout } from 'timers/promises';
9+
10+
// @ts-expect-error Assigning readonly property.
11+
Symbol.asyncDispose ??= Symbol('dispose');
12+
13+
async function setUpCollection(client: MongoClient) {
14+
const collection = client.db('foo').collection<{ name: string }>('bar');
15+
const documents: Array<{ name: string }> = Array.from({ length: 5 }).map(i => ({
16+
name: String(i)
17+
}));
18+
await collection.insertMany(documents)
19+
return collection;
20+
}
21+
22+
describe('explicit resource management smoke tests', function () {
23+
const clientSpy = sinon.spy(MongoClient.prototype, Symbol.asyncDispose);
24+
const cursorSpy = sinon.spy(AbstractCursor.prototype, Symbol.asyncDispose);
25+
const endSessionSpy = sinon.spy(ClientSession.prototype, Symbol.asyncDispose);
26+
const changeStreamSpy = sinon.spy(ChangeStream.prototype, Symbol.asyncDispose);
27+
const readableSpy = sinon.spy(Readable.prototype, Symbol.asyncDispose);
28+
29+
afterEach(function () {
30+
clientSpy.resetHistory();
31+
cursorSpy.resetHistory();
32+
endSessionSpy.resetHistory();
33+
changeStreamSpy.resetHistory();
34+
readableSpy.resetHistory();
35+
});
36+
37+
describe('MongoClient', function () {
38+
it('can be used with await-using syntax', async function () {
39+
{
40+
await using client = new MongoClient(process.env.MONGODB_URI!);
41+
await client.connect();
42+
}
43+
expect(clientSpy.called).to.be.true;
44+
expect(clientSpy.callCount).to.equal(1);
45+
})
46+
})
47+
48+
describe('Cursors', function () {
49+
it('can be used with await-using syntax', async function () {
50+
{
51+
await using client = new MongoClient(process.env.MONGODB_URI!);
52+
await client.connect();
53+
54+
const collection = await setUpCollection(client);
55+
56+
await using cursor = collection.find();
57+
await cursor.next();
58+
await cursor.next();
59+
await cursor.next();
60+
}
61+
expect(cursorSpy.callCount).to.equal(1);
62+
})
63+
64+
describe('cursor streams', function() {
65+
it('can be used with await-using syntax', async function() {
66+
{
67+
await using client = new MongoClient(process.env.MONGODB_URI!);
68+
await client.connect();
69+
70+
const collection = await setUpCollection(client);
71+
72+
await using readable = collection.find().stream();
73+
}
74+
expect(readableSpy.callCount).to.equal(1);
75+
})
76+
})
77+
})
78+
79+
describe('Sessions', function () {
80+
it('can be used with await-using syntax', async function () {
81+
{
82+
await using client = new MongoClient(process.env.MONGODB_URI!);
83+
await client.connect();
84+
85+
await using session = client.startSession();
86+
}
87+
expect(endSessionSpy.callCount).to.equal(1);
88+
})
89+
})
90+
91+
describe('ChangeStreams', function () {
92+
it('can be used with await-using syntax', async function () {
93+
{
94+
await using client = new MongoClient(process.env.MONGODB_URI!);
95+
await client.connect();
96+
97+
const collection = await setUpCollection(client);
98+
await using cs = collection.watch();
99+
100+
setTimeout(1000).then(() => collection.insertOne({ name: 'bailey' }));
101+
await cs.next();
102+
}
103+
expect(changeStreamSpy.callCount).to.equal(1);
104+
})
105+
});
106+
107+
describe('GridFSDownloadStream', function () {
108+
it('can be used with await-using syntax', async function () {
109+
{
110+
await using client = new MongoClient(process.env.MONGODB_URI!);
111+
await client.connect();
112+
113+
const bucket = new GridFSBucket(client.db('foo'));
114+
const uploadStream = bucket.openUploadStream('foo.txt')
115+
await pipeline(Readable.from("AAAAAAA".split('')), uploadStream);
116+
117+
await using downloadStream = bucket.openDownloadStreamByName('foo.txt');
118+
119+
}
120+
expect(readableSpy.callCount).to.equal(1);
121+
})
122+
});
123+
})

0 commit comments

Comments
 (0)