ssh-client-wrapper 2.11.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/util.js CHANGED
@@ -1,18 +1,20 @@
1
- "use strict";
2
- const { EOL } = require("os");
3
- const fs = require("fs");
4
- const debug = require("debug")("sshClientWrapper:debug:util");
5
- const { setTimeout: setTimeoutPromise } = require("timers/promises");
1
+ import { EOL } from "os";
2
+ import fs from "fs";
3
+ import Debug from "debug";
4
+ import { setTimeout as setTimeoutPromise } from "timers/promises";
5
+ import Ajv from "ajv";
6
+ import ajvKeywords from "ajv-keywords";
6
7
 
7
- const sshCmd = "ssh";
8
- const rsyncCmd = "rsync";
9
- const acceptableRsyncRetrunCodes = [10, 11, 12, 13, 14];
8
+ const debug = Debug("sshClientWrapper:debug:util");
10
9
 
11
- const rePwPrompt = /password:/;
12
- const rePhPrompt = /Enter passphrase for key/;
13
- const reNewHostPrompt = /Are you sure you want to continue connecting/;
14
- const reRemoteHostIdentificationHasChanged = /WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! /;
15
- const Ajv = require("ajv");
10
+ export const sshCmd = "ssh";
11
+ export const rsyncCmd = "rsync";
12
+ export const acceptableRsyncRetrunCodes = [10, 11, 12, 13, 14];
13
+
14
+ export const rePwPrompt = /password:/;
15
+ export const rePhPrompt = /Enter passphrase for key/;
16
+ export const reNewHostPrompt = /Are you sure you want to continue connecting/;
17
+ export const reRemoteHostIdentificationHasChanged = /WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! /;
16
18
 
17
19
  const ajv = new Ajv({
18
20
  allErrors: true,
@@ -24,9 +26,9 @@ const ajv = new Ajv({
24
26
  error: debug
25
27
  }
26
28
  });
27
- require("ajv-keywords")(ajv, "transform");
29
+ ajvKeywords(ajv, "transform");
28
30
 
29
- // never validate password and passphrase value to avoid security insident
31
+ //never validate password and passphrase value to avoid security insident
30
32
  const hostInfoSchema = {
31
33
  type: "object",
32
34
  properties: {
@@ -42,7 +44,11 @@ const hostInfoSchema = {
42
44
  retryDuration: { type: "number", minimum: 0, default: 1000 },
43
45
  rcfile: { type: "string", pattern: "\\S+", transform: ["trim"] },
44
46
  prependCmd: { type: "string", pattern: "\\S+", transform: ["trim"] },
45
- sshOpt: { type: "array", minItems: 1, items: { type: "string", pattern: "\\S+", transform: ["trim"] } }
47
+ sshOpt: {
48
+ type: "array",
49
+ minItems: 1,
50
+ items: { type: "string", pattern: "\\S+", transform: ["trim"] }
51
+ }
46
52
  },
47
53
  required: ["host"]
48
54
  };
@@ -66,20 +72,20 @@ const validate = ajv.compile(hostInfoSchema);
66
72
  * @param {Function} func - function
67
73
  * @param {data} data - binary data which can be converted to string
68
74
  */
69
- const buff2String = (func, data) => {
75
+ export const buff2String = (func, data)=>{
70
76
  func(data.toString().replace(/\r\n/g, EOL));
71
77
  };
72
78
 
73
79
  /**
74
80
  * check if given hostInfo object is OK
75
- * @param { Object } hostInfo - host information object defined in index.js
81
+ * @param {object} hostInfo - host information object defined in index.js
76
82
  */
77
- const sanityCheck = (hostInfo) => {
83
+ export const sanityCheck = (hostInfo)=>{
78
84
  debug("sanityCheck called", hostInfo);
79
85
 
80
- // keep password, passphrase, and masterPty before validate.
81
- // these properties can have a iellegal value as JSON data
82
- // so we keep them before ajv validation and put them back
86
+ //keep password, passphrase, and masterPty before validate.
87
+ //these properties can have a iellegal value as JSON data
88
+ //so we keep them before ajv validation and put them back
83
89
 
84
90
  const { password, passphrase, masterPty } = hostInfo;
85
91
  validate(hostInfo);
@@ -102,7 +108,7 @@ const sanityCheck = (hostInfo) => {
102
108
  }
103
109
  if (prop.startsWith("sshOpt")) {
104
110
  debug("remove empty member of sshOpt");
105
- hostInfo.sshOpt = hostInfo.sshOpt.filter((opt) => {
111
+ hostInfo.sshOpt = hostInfo.sshOpt.filter((opt)=>{
106
112
  return opt !== "";
107
113
  });
108
114
  continue;
@@ -134,7 +140,7 @@ const sanityCheck = (hostInfo) => {
134
140
  return hostInfo;
135
141
  };
136
142
 
137
- function getControlPersistDir (hostInfo) {
143
+ function getControlPersistDir(hostInfo) {
138
144
  for (const candidate of [hostInfo.ControlPersistDir, process.env.SSH_CONTROL_PERSIST_DIR]) {
139
145
  if (typeof candidate === "string") {
140
146
  const stat = fs.statSync(candidate, { throwIfNoEntry: false });
@@ -148,10 +154,10 @@ function getControlPersistDir (hostInfo) {
148
154
 
149
155
  /**
150
156
  * return ssh option with some hard corded options
151
- * @param { Object} hostInfo - host information object defined in index.js
157
+ * @param {object} hostInfo - host information object defined in index.js
152
158
  * @param {boolean} withoutDestination - return except for hostname
153
159
  */
154
- const getSshOption = (hostInfo, withoutDestination) => {
160
+ export const getSshOption = (hostInfo, withoutDestination)=>{
155
161
  debug("getSshOption called");
156
162
  const args = [];
157
163
 
@@ -205,7 +211,7 @@ const getSshOption = (hostInfo, withoutDestination) => {
205
211
  args.push(`-oConnectTimeout=${hostInfo.ConnectTimeout}`);
206
212
  }
207
213
  if (Array.isArray(hostInfo.sshOpt)) {
208
- args.push(...hostInfo.sshOpt.filter((e) => {
214
+ args.push(...hostInfo.sshOpt.filter((e)=>{
209
215
  return typeof e === "string";
210
216
  }));
211
217
  }
@@ -213,24 +219,24 @@ const getSshOption = (hostInfo, withoutDestination) => {
213
219
  return args;
214
220
  };
215
221
 
216
- const isArrayOfString = (target) => {
222
+ export const isArrayOfString = (target)=>{
217
223
  if (!Array.isArray(target)) {
218
224
  return false;
219
225
  }
220
- return !target.some((e) => {
221
- // target has non string member
226
+ return !target.some((e)=>{
227
+ //target has non string member
222
228
  return typeof e !== "string";
223
229
  });
224
230
  };
225
231
 
226
232
  /**
227
233
  * log and send message to pty
228
- * @param {Object} pty - pty object which message will be send to
234
+ * @param {object} pty - pty object which message will be send to
229
235
  * @param {string} message - message
230
236
  * @param {Function} logger - logging function
231
237
  * @param {string} label - where this function is called
232
238
  */
233
- const sendPty = async (pty, message, logger, label) => {
239
+ export const sendPty = async (pty, message, logger, label)=>{
234
240
  logger(`${label}: ${message}`);
235
241
  pty.write(message);
236
242
  };
@@ -242,15 +248,15 @@ const sendPty = async (pty, message, logger, label) => {
242
248
  * @param {Function} cb - call back function which will be called after timeout
243
249
  * @returns {AbortController} - ac to stop watch dog timer
244
250
  */
245
- const watchDogTimer = (timeout, label, cb) => {
251
+ export const watchDogTimer = (timeout, label, cb)=>{
246
252
  const ac = new AbortController();
247
253
  const signal = ac.signal;
248
254
  setTimeoutPromise(timeout * 1000, "neverUsedValue", { signal })
249
- .then(() => {
255
+ .then(()=>{
250
256
  debug(`can not finish ${label} within ${timeout} sec`);
251
257
  return typeof cb === "function" ? cb() : true;
252
258
  })
253
- .catch((err) => {
259
+ .catch((err)=>{
254
260
  if (err.name === "AbortError") {
255
261
  debug(`timeout was aborted because ${label} has finished or canceled`);
256
262
  } else {
@@ -259,19 +265,3 @@ const watchDogTimer = (timeout, label, cb) => {
259
265
  });
260
266
  return ac;
261
267
  };
262
-
263
- module.exports = {
264
- sshCmd,
265
- rsyncCmd,
266
- acceptableRsyncRetrunCodes,
267
- rePwPrompt,
268
- rePhPrompt,
269
- reNewHostPrompt,
270
- reRemoteHostIdentificationHasChanged,
271
- buff2String,
272
- getSshOption,
273
- sanityCheck,
274
- isArrayOfString,
275
- sendPty,
276
- watchDogTimer
277
- };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ssh-client-wrapper",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "description": "wrapper library for open ssh client and rsync",
5
5
  "keywords": [
6
6
  "ssh",
@@ -11,17 +11,17 @@
11
11
  "wrapper",
12
12
  "rsync"
13
13
  ],
14
+ "type": "module",
14
15
  "main": "lib/index.js",
15
16
  "scripts": {
16
17
  "mocha": "mocha --recursive test",
17
- "lint": "eslint --fix lib test",
18
- "test": "nyc --reporter=html --reporter=text mocha",
19
- "coverage": "nyc report --reporter=text-lcov > coverage-report.lcov",
20
- "postversion": "git push && git push origin $(git describe --abbrev=0 --tags)",
21
- "prepare": "husky install"
18
+ "lint": "eslint --fix ./",
19
+ "test": "c8 --reporter=html --reporter=text mocha --recursive test",
20
+ "coverage": "c8 report --reporter=text-lcov > coverage-report.lcov",
21
+ "prepare": "husky"
22
22
  },
23
23
  "engines": {
24
- "node": ">=12.9"
24
+ "node": ">=16.0.0"
25
25
  },
26
26
  "author": "Naoyuki Sogo <sogo@longtail-software.co.jp>",
27
27
  "license": "MIT",
@@ -34,31 +34,32 @@
34
34
  "*.js": "eslint --fix"
35
35
  },
36
36
  "dependencies": {
37
- "ajv": "^8.13.0",
37
+ "ajv": "^8.17.1",
38
38
  "ajv-keywords": "^5.1.0",
39
- "debug": "^4.3.4",
40
- "glob": "^10.3.12",
41
- "node-pty": "^0.10.1",
42
- "promise-retry": "^2.0.1"
39
+ "debug": "^4.4.1",
40
+ "glob": "^11.0.3",
41
+ "node-pty-prebuilt-multiarch": "^0.10.1-pre.5"
43
42
  },
44
43
  "devDependencies": {
45
- "chai": "^4.3.7",
46
- "chai-as-promised": "^7.1.1",
47
- "chai-fs": "^2.0.0",
48
- "eslint": "^8.38.0",
49
- "eslint-config-standard": "^17.1.0",
50
- "eslint-plugin-chai-expect": "^3.0.0",
51
- "eslint-plugin-chai-friendly": "^0.7.4",
52
- "eslint-plugin-import": "^2.29.1",
53
- "eslint-plugin-n": "^16.6.2",
54
- "eslint-plugin-promise": "^6.1.1",
55
- "fs-extra": "^11.1.1",
56
- "husky": "^8.0.0",
57
- "lint-staged": "^13.2.1",
58
- "mocha": "^10.2.0",
59
- "nyc": "^15.1.0",
60
- "rewire": "^7.0.0",
61
- "sinon": "^15.0.3",
62
- "sinon-chai": "^3.7.0"
44
+ "@eslint/js": "^9.33.0",
45
+ "@semantic-release/changelog": "^6.0.3",
46
+ "@semantic-release/git": "^10.0.1",
47
+ "@semantic-release/github": "^11.0.4",
48
+ "@semantic-release/npm": "^12.0.2",
49
+ "@stylistic/eslint-plugin": "^5.2.3",
50
+ "c8": "^10.1.3",
51
+ "chai": "^5.3.1",
52
+ "chai-as-promised": "^8.0.1",
53
+ "eslint-plugin-chai-friendly": "^1.1.0",
54
+ "eslint-plugin-jsdoc": "^54.1.0",
55
+ "eslint-plugin-node": "^11.1.0",
56
+ "fs-extra": "^11.3.1",
57
+ "globals": "^16.3.0",
58
+ "husky": "^9.1.7",
59
+ "lint-staged": "^16.1.5",
60
+ "mocha": "^11.7.1",
61
+ "semantic-release": "^24.2.7",
62
+ "sinon": "^21.0.0",
63
+ "sinon-chai": "^4.0.0"
63
64
  }
64
65
  }
@@ -1,22 +1,22 @@
1
- "use strict";
2
- process.on("unhandledRejection", console.dir); // eslint-disable-line no-console
1
+ process.on("unhandledRejection", console.dir);
3
2
 
4
- // setup test framework
5
- const chai = require("chai");
6
- const { expect } = require("chai");
7
- chai.use(require("chai-as-promised"));
3
+ //setup test framework
4
+ import * as chai from "chai";
5
+ import { expect } from "chai";
6
+ import chaiAsPromised from "chai-as-promised";
7
+ chai.use(chaiAsPromised);
8
8
 
9
- // testee
10
- const { getSshOption } = require("../lib/util.js");
9
+ //testee
10
+ import { getSshOption } from "../lib/util.js";
11
11
 
12
- describe("test for getSshOption", () => {
12
+ describe("test for getSshOption", ()=>{
13
13
  const defaultValues = {
14
14
  host: "testHostName",
15
15
  ControlPersist: 180,
16
16
  maxRetry: 3,
17
17
  retryDuration: 1000
18
18
  };
19
- it("should return minimum ssh option array", () => {
19
+ it("should return minimum ssh option array", ()=>{
20
20
  const sshOpts = getSshOption(defaultValues);
21
21
  expect(sshOpts).to.be.an("array");
22
22
  expect(sshOpts).to.have.lengthOf(4);
@@ -25,7 +25,7 @@ describe("test for getSshOption", () => {
25
25
  expect(sshOpts[2]).to.equal("-oControlPath=~/.ssh/ssh-client-wrapper-%r@%h:%p");
26
26
  expect(sshOpts[3]).to.equal("-oControlPersist=180");
27
27
  });
28
- it("should change ControlPath by ControlPersistDir", () => {
28
+ it("should change ControlPath by ControlPersistDir", ()=>{
29
29
  const hostInfo = { ...defaultValues };
30
30
  hostInfo.ControlPersistDir = "/tmp";
31
31
  const sshOpts = getSshOption(hostInfo);
@@ -36,7 +36,7 @@ describe("test for getSshOption", () => {
36
36
  expect(sshOpts[2]).to.equal("-oControlPath=/tmp/ssh-client-wrapper-%r@%h:%p");
37
37
  expect(sshOpts[3]).to.equal("-oControlPersist=180");
38
38
  });
39
- it("should change ControlPath by Environment variable", () => {
39
+ it("should change ControlPath by Environment variable", ()=>{
40
40
  process.env.SSH_CONTROL_PERSIST_DIR = "/tmp";
41
41
  const sshOpts = getSshOption(defaultValues);
42
42
  expect(sshOpts).to.be.an("array");
package/test/interface.js CHANGED
@@ -1,53 +1,56 @@
1
- "use strict";
2
- process.on("unhandledRejection", console.dir); // eslint-disable-line no-console
1
+ process.on("unhandledRejection", console.dir);
3
2
  Error.traceLimit = 100000;
4
3
 
5
- // setup test framework
6
- const chai = require("chai");
7
- const { expect } = require("chai");
8
- const sinon = require("sinon");
9
- chai.use(require("sinon-chai"));
10
- chai.use(require("chai-as-promised"));
4
+ //setup test framework
5
+ import * as chai from "chai";
6
+ import { expect } from "chai";
7
+ import sinon from "sinon";
8
+ import sinonChai from "sinon-chai";
9
+ import chaiAsPromised from "chai-as-promised";
10
+ chai.use(sinonChai);
11
+ chai.use(chaiAsPromised);
11
12
 
12
- const rewire = require("rewire");
13
-
14
- // testee
15
- const SshClientWrapper = rewire("../lib/index.js");
13
+ //testee
14
+ import SshClientWrapper from "../lib/index.js";
16
15
 
17
16
  const sshExec = sinon.stub();
18
17
  const canConnect = sinon.stub();
19
18
  const disconnect = sinon.stub();
20
- const ls = sinon.stub();
19
+ const expectStub = sinon.stub();
21
20
  const send = sinon.stub();
22
21
  const recv = sinon.stub();
23
22
 
24
- // eslint-disable-next-line no-underscore-dangle
25
- SshClientWrapper.__set__({
26
- sshExec, canConnect, disconnect, ls, send, recv
27
- });
23
+ const deps = {
24
+ sshExec,
25
+ canConnect,
26
+ disconnect,
27
+ expect: expectStub,
28
+ send,
29
+ recv
30
+ };
28
31
 
29
- describe("test for interface", () => {
30
- describe("test for constructor", () => {
31
- it("should throw error when instanciate with non-empty string host", () => {
32
- expect(() => {
33
- // eslint-disable-next-line no-new
34
- new SshClientWrapper({});
32
+ describe("test for interface", ()=>{
33
+ describe("test for constructor", ()=>{
34
+ it("should throw error when instanciate with non-empty string host", ()=>{
35
+ expect(()=>{
36
+ new SshClientWrapper({}, deps);
35
37
  }).to.throw("host is required");
36
- expect(() => {
37
- // eslint-disable-next-line no-new
38
- new SshClientWrapper({ host: "" });
38
+ expect(()=>{
39
+ new SshClientWrapper({ host: "" }, deps);
39
40
  }).to.throw("empty host is not allowed");
40
41
  });
41
- it("should successfully instanciate only with host prop", () => {
42
- expect(new SshClientWrapper({ host: "hoge" })).to.have.property("exec");
43
- expect(new SshClientWrapper({ host: "hoge" })).to.have.property("ls");
44
- expect(new SshClientWrapper({ host: "hoge" })).to.have.property("send");
45
- expect(new SshClientWrapper({ host: "hoge" })).to.have.property("recv");
46
- expect(new SshClientWrapper({ host: "hoge" })).to.have.property("canConnect");
47
- expect(new SshClientWrapper({ host: "hoge" })).to.have.property("disconnect");
42
+ it("should successfully instanciate only with host prop", ()=>{
43
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("exec");
44
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("execAndGetOutput");
45
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("ls");
46
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("expect");
47
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("send");
48
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("recv");
49
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("canConnect");
50
+ expect(new SshClientWrapper({ host: "hoge" }, deps)).to.have.property("disconnect");
48
51
  });
49
52
  });
50
- describe("test for public method", () => {
53
+ describe("test for public method", ()=>{
51
54
  let ssh;
52
55
  const hostInfoOrg = {
53
56
  host: "hoge",
@@ -56,122 +59,122 @@ describe("test for interface", () => {
56
59
  retryDuration: 1000
57
60
  };
58
61
  const hostInfo = { ...hostInfoOrg, masterPty: null, rsyncVersion: null };
59
- beforeEach(() => {
60
- ssh = new SshClientWrapper(hostInfoOrg);
62
+ beforeEach(()=>{
63
+ ssh = new SshClientWrapper(hostInfoOrg, deps);
61
64
  sshExec.reset();
62
65
  canConnect.reset();
63
66
  disconnect.reset();
64
- ls.reset();
65
67
  send.reset();
66
68
  recv.reset();
69
+ expectStub.reset();
67
70
  });
68
- describe("test for exec", () => {
69
- it("should call sshExec with cmd", () => {
71
+ describe("test for exec", ()=>{
72
+ it("should call sshExec with cmd", ()=>{
70
73
  ssh.exec("ls");
71
74
  expect(sshExec).to.be.calledWith(hostInfo, "ls", 0, null);
72
75
  });
73
- it("should call sshExec with cmd and timeout", () => {
76
+ it("should call sshExec with cmd and timeout", ()=>{
74
77
  ssh.exec("ls", 10);
75
78
  expect(sshExec).to.be.calledWith(hostInfo, "ls", 10, null);
76
79
  });
77
- it("should call sshExec with cmd, timeout and call back function", () => {
78
- const cb = () => {};
80
+ it("should call sshExec with cmd, timeout and call back function", ()=>{
81
+ const cb = ()=>{};
79
82
  ssh.exec("ls", 10, cb);
80
83
  expect(sshExec).to.be.calledWith(hostInfo, "ls", 10, cb);
81
84
  });
82
- it("should reject if cmd is not string (number)", () => {
85
+ it("should reject if cmd is not string (number)", ()=>{
83
86
  return expect(ssh.exec(0)).to.be.rejectedWith("cmd must be string");
84
87
  });
85
- it("should reject if cmd is not string (null)", () => {
88
+ it("should reject if cmd is not string (null)", ()=>{
86
89
  return expect(ssh.exec(null)).to.be.rejectedWith("cmd must be string");
87
90
  });
88
- it("should reject if cmd is empty string", () => {
91
+ it("should reject if cmd is empty string", ()=>{
89
92
  return expect(ssh.exec("")).to.be.rejectedWith("cmd must be string");
90
93
  });
91
94
  });
92
- describe("test for ls", () => {
93
- it("should call ls without timeout", () => {
95
+ describe("test for ls", ()=>{
96
+ it("should call ls without timeout", ()=>{
94
97
  ssh.ls("hoge");
95
- expect(ls).to.be.calledWith(hostInfo, "hoge", [], 0);
98
+ expect(sshExec).to.be.calledWith(hostInfo, "ls hoge", 0);
96
99
  });
97
- it("should call ls with option", () => {
100
+ it("should call ls with option", ()=>{
98
101
  ssh.ls("hoge", ["-l", "-r", "-t"]);
99
- expect(ls).to.be.calledWith(hostInfo, "hoge", ["-l", "-r", "-t"], 0);
102
+ expect(sshExec).to.be.calledWith(hostInfo, "ls -l -r -t hoge", 0);
100
103
  });
101
- it("should call ls with option and timeout", () => {
104
+ it("should call ls with option and timeout", ()=>{
102
105
  ssh.ls("hoge", ["-l", "-r", "-t"], 10);
103
- expect(ls).to.be.calledWith(hostInfo, "hoge", ["-l", "-r", "-t"], 10);
106
+ expect(sshExec).to.be.calledWith(hostInfo, "ls -l -r -t hoge", 10);
104
107
  });
105
108
  });
106
- describe("test for send", () => {
107
- it("should call send with src and dst", () => {
109
+ describe("test for send", ()=>{
110
+ it("should call send with src and dst", ()=>{
108
111
  ssh.send(["src"], "dst");
109
112
  expect(send).to.be.calledWith(hostInfo, ["src"], "dst", [], 0);
110
113
  });
111
- it("should call send with src, dst, and opt", () => {
114
+ it("should call send with src, dst, and opt", ()=>{
112
115
  ssh.send(["src"], "dst", ["--dry-run", "--delete"]);
113
116
  expect(send).to.be.calledWith(hostInfo, ["src"], "dst", ["--dry-run", "--delete"], 0);
114
117
  });
115
- it("should call send with src, dst, opt, and timeout", () => {
118
+ it("should call send with src, dst, opt, and timeout", ()=>{
116
119
  ssh.send(["src"], "dst", ["--dry-run", "--delete"], 10);
117
120
  expect(send).to.be.calledWith(hostInfo, ["src"], "dst", ["--dry-run", "--delete"], 10);
118
121
  });
119
- it("should be rejected if src is not array of string", () => {
122
+ it("should be rejected if src is not array of string", ()=>{
120
123
  return expect(ssh.send(1)).to.be.rejectedWith("src must be array of string");
121
124
  });
122
- it("should be rejected if src has only empty string element", () => {
125
+ it("should be rejected if src has only empty string element", ()=>{
123
126
  return expect(ssh.send(["", ""])).to.be.rejectedWith("src must contain non-empty string");
124
127
  });
125
- it("should be rejected if src has only empty string element", () => {
128
+ it("should be rejected if src has only empty string element", ()=>{
126
129
  return expect(ssh.send([""])).to.be.rejectedWith("src must contain non-empty string");
127
130
  });
128
- it("should be called if src includes empty string ", () => {
131
+ it("should be called if src includes empty string ", ()=>{
129
132
  ssh.send(["src", ""], "dst");
130
133
  expect(send).to.be.calledWith(hostInfo, ["src", ""], "dst", [], 0);
131
134
  });
132
- it("should be rejected if dst is not string", () => {
135
+ it("should be rejected if dst is not string", ()=>{
133
136
  return expect(ssh.send(["src"], 0)).to.be.rejectedWith("dst must be string");
134
137
  });
135
- it("should be rejected if dst is empty string", () => {
138
+ it("should be rejected if dst is empty string", ()=>{
136
139
  return expect(ssh.send(["src"], "")).to.be.rejectedWith("dst must be non-empty string");
137
140
  });
138
- it("should be rejected if opt is not array of string", () => {
141
+ it("should be rejected if opt is not array of string", ()=>{
139
142
  return expect(ssh.send(["src"], "dst", [null])).to.be.rejectedWith("opt must be array of string");
140
143
  });
141
144
  });
142
- describe("test for recv", () => {
143
- it("should call recv with src and dst", () => {
145
+ describe("test for recv", ()=>{
146
+ it("should call recv with src and dst", ()=>{
144
147
  ssh.recv(["src"], "dst");
145
148
  expect(recv).to.be.calledWith(hostInfo, ["src"], "dst", [], 0);
146
149
  });
147
- it("should call recv with src, dst, and opt", () => {
150
+ it("should call recv with src, dst, and opt", ()=>{
148
151
  ssh.recv(["src"], "dst", ["--dry-run", "--delete"]);
149
152
  expect(recv).to.be.calledWith(hostInfo, ["src"], "dst", ["--dry-run", "--delete"], 0);
150
153
  });
151
- it("should call recv with src, dst, opt, and timeout", () => {
154
+ it("should call recv with src, dst, opt, and timeout", ()=>{
152
155
  ssh.recv(["src"], "dst", ["--dry-run", "--delete"], 10);
153
156
  expect(recv).to.be.calledWith(hostInfo, ["src"], "dst", ["--dry-run", "--delete"], 10);
154
157
  });
155
- it("should be rejected if src is not array of string", () => {
158
+ it("should be rejected if src is not array of string", ()=>{
156
159
  return expect(ssh.recv(1)).to.be.rejectedWith("src must be array of string");
157
160
  });
158
- it("should be rejected if src has only empty string element", () => {
161
+ it("should be rejected if src has only empty string element", ()=>{
159
162
  return expect(ssh.recv(["", ""])).to.be.rejectedWith("src must contain non-empty string");
160
163
  });
161
- it("should be rejected if src has only empty string element", () => {
164
+ it("should be rejected if src has only empty string element", ()=>{
162
165
  return expect(ssh.recv([""])).to.be.rejectedWith("src must contain non-empty string");
163
166
  });
164
- it("should be called if src includes empty string ", () => {
167
+ it("should be called if src includes empty string ", ()=>{
165
168
  ssh.recv(["src", ""], "dst");
166
169
  expect(recv).to.be.calledWith(hostInfo, ["src", ""], "dst", [], 0);
167
170
  });
168
- it("should be rejected if dst is not string", () => {
171
+ it("should be rejected if dst is not string", ()=>{
169
172
  return expect(ssh.recv(["src"], 0)).to.be.rejectedWith("dst must be string");
170
173
  });
171
- it("should be rejected if dst is empty string", () => {
174
+ it("should be rejected if dst is empty string", ()=>{
172
175
  return expect(ssh.recv(["src"], "")).to.be.rejectedWith("dst must be non-empty string");
173
176
  });
174
- it("should be rejected if opt is not array of string", () => {
177
+ it("should be rejected if opt is not array of string", ()=>{
175
178
  return expect(ssh.recv(["src"], "dst", [null])).to.be.rejectedWith("opt must be array of string");
176
179
  });
177
180
  });