Skip to content

Commit 5480b03

Browse files
committed
Migrate all tests to built-in Nodejs test runner
This will get rid of the dependency on Mocha and all dependency vulnerabilities
1 parent 440354e commit 5480b03

16 files changed

Lines changed: 328 additions & 851 deletions

package-lock.json

Lines changed: 0 additions & 531 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88
"dist/**/*"
99
],
1010
"scripts": {
11-
"prepublishOnly": "npm run clean && npm run lint && tsc && mocha",
11+
"prepublishOnly": "npm run clean && npm run lint && tsc && node --test 'test/*Spec.js'",
1212
"prepare": "tsc",
1313
"test": "npm run prepublishOnly",
1414
"clean": "rm -rf dist",
1515
"lint": "eslint \"./src/**/*.ts\"",
1616
"lint-fix": "eslint --fix \"./src/**/*.ts\"",
1717
"dev": "npm run clean && tsc --watch",
18-
"tdd": "mocha --watch",
18+
"tdd": "node --test --watch 'test/*Spec.js'",
1919
"buildOnly": "tsc",
20-
"test:integration": "npm run buildOnly && mocha 'test/integration/**Spec.js'"
20+
"test:integration": "npm run buildOnly && node --test 'test/integration/**Spec.js'"
2121
},
2222
"repository": {
2323
"type": "git",
@@ -41,13 +41,11 @@
4141
"devDependencies": {
4242
"@eslint/eslintrc": "3.3.5",
4343
"@eslint/js": "10.0.1",
44-
"@types/mocha": "10.0.10",
4544
"@types/node": "25.9.1",
4645
"@typescript-eslint/eslint-plugin": "8.59.4",
4746
"@typescript-eslint/parser": "8.59.4",
4847
"eslint": "10.4.0",
4948
"globals": "17.6.0",
50-
"mocha": "11.7.5",
5149
"testcontainers": "11.14.0",
5250
"typescript": "6.0.3"
5351
}

test/canarySpec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { describe, it } = require("node:test");
12
const assert = require("assert");
23

34
describe("Canary", function() {

test/commandSpec.js

Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { describe, it, beforeEach, afterEach } = require("node:test");
12
const assert = require("assert");
23
const { Client } = require("../dist");
34
const MockFtpServer = require("./MockFtpServer");
@@ -13,124 +14,126 @@ const NO_FEAT_REPLY = `
1314
`;
1415
const FILENAME = "file.txt"
1516

16-
describe("Simple commands", function() {
17+
describe("Simple commands", () => {
1718

18-
this.beforeEach(() => {
19-
this.server = new MockFtpServer()
20-
this.client = new Client(1000)
21-
return this.client.access({
22-
port: this.server.ctrlAddress.port,
19+
let server, client;
20+
21+
beforeEach(() => {
22+
server = new MockFtpServer()
23+
client = new Client(1000)
24+
return client.access({
25+
port: server.ctrlAddress.port,
2326
user: "test",
2427
password: "test"
2528
})
2629
})
2730

28-
this.afterEach(() => {
29-
this.client.close()
30-
this.server.close()
31+
afterEach(() => {
32+
client.close()
33+
server.close()
3134
})
3235

3336
it("can get a file size", () => {
34-
this.server.addHandlers({
35-
"size": ({arg}) => arg === "file.txt" ? "213 6666" : "400 File not found"
37+
server.addHandlers({
38+
"size": ({arg}) => arg === "file.txt" ? "213 6666" : "400 File not found"
3639
})
37-
return this.client.size("file.txt").then(result => {
40+
return client.size("file.txt").then(result => {
3841
assert.strictEqual(result, 6666)
3942
})
4043
})
4144

4245
it("can get last modified time", () => {
43-
this.server.addHandlers({
46+
server.addHandlers({
4447
"mdtm": ({arg}) => arg === "file.txt" ? "213 19951217032400" : "400 File not found"
4548
})
46-
return this.client.lastMod("file.txt").then(result => {
49+
return client.lastMod("file.txt").then(result => {
4750
assert.deepEqual(result, new Date("1995-12-17T03:24:00+0000"))
48-
})
51+
})
4952
})
5053

5154
it("can get features", () => {
52-
this.server.addHandlers({
55+
server.addHandlers({
5356
"feat": () => FEAT_REPLY
5457
})
55-
return this.client.features().then(result => {
58+
return client.features().then(result => {
5659
assert.deepEqual(result, new Map([["MLST", "size*;create"], ["SIZE", ""]]))
57-
})
60+
})
5861
})
5962

6063
it("can handle no features", () => {
61-
this.server.addHandlers({
64+
server.addHandlers({
6265
"feat": () => NO_FEAT_REPLY
6366
})
64-
return this.client.features().then(result => {
67+
return client.features().then(result => {
6568
assert.deepEqual(result, new Map())
66-
})
69+
})
6770
})
6871

6972
it("returns empty feature set when server sends error", () => {
70-
this.server.addHandlers({
73+
server.addHandlers({
7174
"test": () => "200 OK"
7275
})
73-
return this.client.send("TEST").then(result => {
76+
return client.send("TEST").then(result => {
7477
assert.deepEqual(result, { code: 200, message: "200 OK" })
75-
})
78+
})
7679
})
7780

7881
it("sending command handles error", () => {
79-
this.server.addHandlers({
82+
server.addHandlers({
8083
"test": () => "500 Command unknown"
8184
})
82-
return assert.rejects(() => this.client.send("TEST"), {
85+
return assert.rejects(() => client.send("TEST"), {
8386
name: "FTPError",
8487
message: "500 Command unknown"
85-
})
88+
})
8689
})
8790

8891
it("can ignore error response ", () => {
89-
this.server.addHandlers({
92+
server.addHandlers({
9093
"test": () => "500 Command unknown"
9194
})
92-
return assert.doesNotReject(() => this.client.sendIgnoringError("TEST"))
95+
return assert.doesNotReject(() => client.sendIgnoringError("TEST"))
9396
})
9497

9598
it("throws if connection error even if ignoring errors has been requested", () => {
96-
this.server.addHandlers({
97-
"test": () => this.server.ctrlConn.destroy()
99+
server.addHandlers({
100+
"test": () => server.ctrlConn.destroy()
98101
})
99-
return assert.rejects(() => this.client.send("TEST"), {
102+
return assert.rejects(() => client.send("TEST"), {
100103
name: "Error",
101104
message: "Server sent FIN packet unexpectedly, closing connection."
102-
})
105+
})
103106
})
104107

105108
it("can rename a file", () => {
106-
this.server.addHandlers({
109+
server.addHandlers({
107110
"rnfr": ({arg}) => arg === "old.txt" ? "350 Accepted" : "500 File not found",
108111
"rnto": ({arg}) => arg === "new.txt" ? "200 Renamed" : "500 File not found",
109112
})
110-
return this.client.rename("old.txt", "new.txt").then(result => {
113+
return client.rename("old.txt", "new.txt").then(result => {
111114
assert.deepEqual(result, { code: 200, message: "200 Renamed" })
112115
})
113116
})
114-
117+
115118
it("can handle leading whitespace in a filename", () => {
116-
this.server.addHandlers({
119+
server.addHandlers({
117120
"pwd": () => `257 "/this/that"`
118121
})
119-
return this.client.protectWhitespace(" file.txt").then(result => {
122+
return client.protectWhitespace(" file.txt").then(result => {
120123
assert.strictEqual(result, "/this/that/ file.txt")
121124
})
122125
})
123126

124127
it("can handle leading whitespace in relative path", () => {
125-
this.server.addHandlers({
128+
server.addHandlers({
126129
"pwd": () => `257 "/this/that"`
127130
})
128-
return this.client.protectWhitespace(" a/b").then(result => {
131+
return client.protectWhitespace(" a/b").then(result => {
129132
assert.strictEqual(result, "/this/that/ a/b")
130133
})
131134
})
132135

133-
it("can remove a file")
134-
it("can change directory")
135-
it("can get the current working directory")
136-
})
136+
it.todo("can remove a file")
137+
it.todo("can change directory")
138+
it.todo("can get the current working directory")
139+
})

test/connectivitySpec.js

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
1+
const { describe, it, beforeEach, afterEach } = require("node:test");
12
const assert = require("assert");
23
const { Client } = require("../dist");
34
const MockFtpServer = require("./MockFtpServer");
45

5-
describe("Connectivity", function() {
6+
describe("Connectivity", () => {
67

7-
this.beforeEach(() => {
8-
this.server = new MockFtpServer()
9-
this.client = new Client(50)
8+
let server, client;
9+
10+
beforeEach(() => {
11+
server = new MockFtpServer()
12+
client = new Client(50)
1013
})
1114

12-
this.afterEach(() => {
13-
this.client.close()
14-
this.server.close()
15+
afterEach(() => {
16+
client.close()
17+
server.close()
1518
})
1619

1720
it("throws error when sending before connecting", () => {
18-
return assert.rejects(() => this.client.send("hi"), {
21+
return assert.rejects(() => client.send("hi"), {
1922
message: "Socket is closed (control socket)"
2023
})
2124
})
2225

2326
it("handles closing uninitialized socket", () => {
24-
this.client.close()
27+
client.close()
2528
})
2629

2730
it("can access a server", () => {
28-
return this.client.access({
29-
port: this.server.ctrlAddress.port,
31+
return client.access({
32+
port: server.ctrlAddress.port,
3033
user: "test",
3134
password: "test"
3235
}).then(result => {
@@ -35,24 +38,24 @@ describe("Connectivity", function() {
3538
});
3639

3740
it("throws on timeout when accessing a server", () => {
38-
return assert.rejects(() => this.client.access({
41+
return assert.rejects(() => client.access({
3942
host: "192.168.0.123"
4043
}), {
4144
message: "Timeout (control socket)"
4245
})
4346
})
4447

4548
it("throws if connection failed", () => {
46-
return assert.rejects(() => this.client.access({
49+
return assert.rejects(() => client.access({
4750
port: 111
4851
}), {
4952
code: "ECONNREFUSED"
5053
})
5154
})
5255

5356
it("throws if password wrong", () => {
54-
return assert.rejects(() => this.client.access({
55-
port: this.server.ctrlAddress.port,
57+
return assert.rejects(() => client.access({
58+
port: server.ctrlAddress.port,
5659
user: "test",
5760
password: "WRONGPASSWORD"
5861
}), {
@@ -62,8 +65,8 @@ describe("Connectivity", function() {
6265
})
6366

6467
it("throws if user unknown", () => {
65-
return assert.rejects(() => this.client.access({
66-
port: this.server.ctrlAddress.port,
68+
return assert.rejects(() => client.access({
69+
port: server.ctrlAddress.port,
6770
user: "UNKNOWNUSER",
6871
password: "test"
6972
}), {
@@ -73,17 +76,17 @@ describe("Connectivity", function() {
7376
})
7477

7578
it("access executes default set of commands", () => {
76-
this.server.handlers = {
79+
server.handlers = {
7780
// Set the minimum required commands, not all default settings need to succeed.
7881
user: () => "200 OK",
7982
type: () => "200 OK"
8083
}
81-
return this.client.access({
82-
port: this.server.ctrlAddress.port,
84+
return client.access({
85+
port: server.ctrlAddress.port,
8386
user: "test",
8487
password: "test"
8588
}).then(() => {
86-
assert.deepEqual(this.server.receivedCommands, [
89+
assert.deepEqual(server.receivedCommands, [
8790
"OPTS UTF8 ON",
8891
"USER test",
8992
"FEAT",
@@ -95,21 +98,21 @@ describe("Connectivity", function() {
9598
});
9699

97100
it("client reflects closed state correctly", async () => {
98-
assert.strictEqual(this.client.closed, true, "before access")
99-
await this.client.access({
100-
port: this.server.ctrlAddress.port,
101+
assert.strictEqual(client.closed, true, "before access")
102+
await client.access({
103+
port: server.ctrlAddress.port,
101104
user: "test",
102105
password: "test"
103106
})
104-
assert.strictEqual(this.client.closed, false, "after access")
105-
this.client.close()
106-
assert.strictEqual(this.client.closed, true, "after close")
107-
return assert.rejects(() => this.client.send("TYPE I"), {
107+
assert.strictEqual(client.closed, false, "after access")
108+
client.close()
109+
assert.strictEqual(client.closed, true, "after close")
110+
return assert.rejects(() => client.send("TYPE I"), {
108111
name: "Error",
109112
message: "Client is closed because User closed client"
110113
})
111114
});
112115

113-
it("can connect using explicit TLS")
114-
it("can connect using implicit TLS")
115-
})
116+
it.todo("can connect using explicit TLS")
117+
it.todo("can connect using implicit TLS")
118+
})

0 commit comments

Comments
 (0)