Skip to content
This repository was archived by the owner on May 31, 2022. It is now read-only.

Commit e4c4576

Browse files
committed
fix: Update ssh-tunnel mock to match new implementation
1 parent 51f0a80 commit e4c4576

File tree

3 files changed

+63
-13
lines changed

3 files changed

+63
-13
lines changed

lib/connect.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,20 @@ const getTasks = (model, setupListeners) => {
240240
setupListeners(mongoClient);
241241
}
242242

243+
let maybeTunnelError;
244+
245+
if (tunnel) {
246+
tunnel.on('error', (tunnelError) => {
247+
maybeTunnelError = tunnelError;
248+
});
249+
}
250+
243251
mongoClient.connect((err, _client) => {
252+
// When mongo client failed to connect AND tunnel encountered an error
253+
// those two are totally related and we want to return a tunnel error as
254+
// it will have more relevant context for the end user
255+
err = err && maybeTunnelError ? maybeTunnelError : err;
256+
244257
ctx(err);
245258

246259
if (err) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"scripts": {
1717
"ci": "npm run check && npm test",
1818
"pretest": "mongodb-runner install",
19-
"test": "mocha",
19+
"test": "mocha --timeout 15000",
2020
"check": "mongodb-js-precommit"
2121
},
2222
"peerDependencies": {

test/connect.test.js

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const Connection = require('../');
44
const connect = Connection.connect;
55
const mock = require('mock-require');
66
const sinon = require('sinon');
7+
const SSHTunnel = require('@mongodb-js/ssh-tunnel').default;
78

89
const setupListeners = () => {};
910

@@ -74,13 +75,15 @@ describe('connection model connector', () => {
7475
});
7576

7677
describe('ssh tunnel failures', () => {
77-
const spy = sinon.spy();
78+
let closeSpy;
7879

79-
mock('../lib/ssh-tunnel', (model, cb) => {
80-
// simulate successful tunnel creation
81-
cb();
82-
// then return a mocked tunnel object with a spy close() function
83-
return { close: spy };
80+
mock('@mongodb-js/ssh-tunnel', {
81+
default: class MockTunnel extends SSHTunnel {
82+
constructor(...args) {
83+
super(...args);
84+
this.close = closeSpy = sinon.spy(this.close.bind(this));
85+
}
86+
}
8487
});
8588

8689
const MockConnection = mock.reRequire('../lib/extended-model');
@@ -99,12 +102,46 @@ describe('connection model connector', () => {
99102

100103
assert(model.isValid());
101104
mockConnect(model, setupListeners, (err) => {
102-
// must throw error here, because the connection details are invalid
103-
assert.ok(err);
104-
assert.ok(/ECONNREFUSED/.test(err.message));
105-
// assert that tunnel.close() was called once
106-
assert.ok(spy.calledOnce);
107-
done();
105+
try {
106+
// must throw error here, because the connection details are invalid
107+
assert.ok(err);
108+
// assert that tunnel.close() was called once
109+
assert.ok(
110+
closeSpy.calledOnce,
111+
'Expected tunnel.close to be called exactly once'
112+
);
113+
done();
114+
} catch (e) {
115+
done(e);
116+
}
117+
});
118+
});
119+
120+
it('should propagate tunnel error if tunnel fails to connect', (done) => {
121+
const model = new MockConnection({
122+
hostname: 'localhost',
123+
port: 27020,
124+
sshTunnel: 'USER_PASSWORD',
125+
sshTunnelHostname: 'my.ssh-server.com',
126+
sshTunnelPassword: 'password',
127+
sshTunnelUsername: 'my-user',
128+
extraOptions: { serverSelectionTimeoutMS: 100 }
129+
});
130+
131+
assert(model.isValid());
132+
mockConnect(model, setupListeners, (err) => {
133+
try {
134+
const regex = /ENOTFOUND my.ssh-server.com/;
135+
136+
assert.ok(err);
137+
assert.ok(
138+
regex.test(err.message),
139+
`Expected "${err.message}" to match ${regex}`
140+
);
141+
done();
142+
} catch (e) {
143+
done(e);
144+
}
108145
});
109146
});
110147
});

0 commit comments

Comments
 (0)