chore: create additional tests
This commit is contained in:
parent
1a5ebc649d
commit
eb551d1c4a
3 changed files with 296 additions and 0 deletions
88
tests/errors.test.js
Normal file
88
tests/errors.test.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
const {
|
||||||
|
WebSSH2Error,
|
||||||
|
ConfigError,
|
||||||
|
SSHConnectionError,
|
||||||
|
handleError
|
||||||
|
} = require("../app/errors")
|
||||||
|
const { logError } = require("../app/logger")
|
||||||
|
const { HTTP, MESSAGES } = require("../app/constants")
|
||||||
|
|
||||||
|
jest.mock("../app/logger", () => ({
|
||||||
|
logError: jest.fn(),
|
||||||
|
createNamespacedDebug: jest.fn(() => jest.fn())
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe("errors", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("WebSSH2Error", () => {
|
||||||
|
it("should create a WebSSH2Error with correct properties", () => {
|
||||||
|
const error = new WebSSH2Error("Test error", "TEST_CODE")
|
||||||
|
expect(error).toBeInstanceOf(Error)
|
||||||
|
expect(error.name).toBe("WebSSH2Error")
|
||||||
|
expect(error.message).toBe("Test error")
|
||||||
|
expect(error.code).toBe("TEST_CODE")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("ConfigError", () => {
|
||||||
|
it("should create a ConfigError with correct properties", () => {
|
||||||
|
const error = new ConfigError("Config error")
|
||||||
|
expect(error).toBeInstanceOf(WebSSH2Error)
|
||||||
|
expect(error.name).toBe("ConfigError")
|
||||||
|
expect(error.message).toBe("Config error")
|
||||||
|
expect(error.code).toBe(MESSAGES.CONFIG_ERROR)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("SSHConnectionError", () => {
|
||||||
|
it("should create a SSHConnectionError with correct properties", () => {
|
||||||
|
const error = new SSHConnectionError("SSH connection error")
|
||||||
|
expect(error).toBeInstanceOf(WebSSH2Error)
|
||||||
|
expect(error.name).toBe("SSHConnectionError")
|
||||||
|
expect(error.message).toBe("SSH connection error")
|
||||||
|
expect(error.code).toBe(MESSAGES.SSH_CONNECTION_ERROR)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("handleError", () => {
|
||||||
|
const mockRes = {
|
||||||
|
status: jest.fn(() => mockRes),
|
||||||
|
json: jest.fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
it("should handle WebSSH2Error correctly", () => {
|
||||||
|
const error = new WebSSH2Error("Test error", "TEST_CODE")
|
||||||
|
handleError(error, mockRes)
|
||||||
|
|
||||||
|
expect(logError).toHaveBeenCalledWith("Test error", error)
|
||||||
|
expect(mockRes.status).toHaveBeenCalledWith(HTTP.INTERNAL_SERVER_ERROR)
|
||||||
|
expect(mockRes.json).toHaveBeenCalledWith({
|
||||||
|
error: "Test error",
|
||||||
|
code: "TEST_CODE"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle generic Error correctly", () => {
|
||||||
|
const error = new Error("Generic error")
|
||||||
|
handleError(error, mockRes)
|
||||||
|
|
||||||
|
expect(logError).toHaveBeenCalledWith(MESSAGES.UNEXPECTED_ERROR, error)
|
||||||
|
expect(mockRes.status).toHaveBeenCalledWith(HTTP.INTERNAL_SERVER_ERROR)
|
||||||
|
expect(mockRes.json).toHaveBeenCalledWith({
|
||||||
|
error: MESSAGES.UNEXPECTED_ERROR
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should not send response if res is not provided", () => {
|
||||||
|
const error = new Error("No response error")
|
||||||
|
handleError(error)
|
||||||
|
|
||||||
|
expect(logError).toHaveBeenCalledWith(MESSAGES.UNEXPECTED_ERROR, error)
|
||||||
|
expect(mockRes.status).not.toHaveBeenCalled()
|
||||||
|
expect(mockRes.json).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
48
tests/logger.test.js
Normal file
48
tests/logger.test.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// server
|
||||||
|
// tests/logger.test.js
|
||||||
|
|
||||||
|
const createDebug = require("debug")
|
||||||
|
const { createNamespacedDebug, logError } = require("../app/logger")
|
||||||
|
|
||||||
|
jest.mock("debug")
|
||||||
|
|
||||||
|
describe("logger", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
console.error = jest.fn()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("createNamespacedDebug", () => {
|
||||||
|
it("should create a debug function with the correct namespace", () => {
|
||||||
|
const mockDebug = jest.fn()
|
||||||
|
createDebug.mockReturnValue(mockDebug)
|
||||||
|
|
||||||
|
const result = createNamespacedDebug("test")
|
||||||
|
|
||||||
|
expect(createDebug).toHaveBeenCalledWith("webssh2:test")
|
||||||
|
expect(result).toBe(mockDebug)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("logError", () => {
|
||||||
|
it("should log an error message without an error object", () => {
|
||||||
|
const message = "Test error message"
|
||||||
|
|
||||||
|
logError(message)
|
||||||
|
|
||||||
|
expect(console.error).toHaveBeenCalledWith(message)
|
||||||
|
expect(console.error).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should log an error message with an error object", () => {
|
||||||
|
const message = "Test error message"
|
||||||
|
const error = new Error("Test error")
|
||||||
|
|
||||||
|
logError(message, error)
|
||||||
|
|
||||||
|
expect(console.error).toHaveBeenCalledWith(message)
|
||||||
|
expect(console.error).toHaveBeenCalledWith("ERROR: Error: Test error")
|
||||||
|
expect(console.error).toHaveBeenCalledTimes(2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
160
tests/ssh.test.js
Normal file
160
tests/ssh.test.js
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
// server
|
||||||
|
// tests/ssh.test.js
|
||||||
|
|
||||||
|
const SSH2 = require("ssh2")
|
||||||
|
const SSHConnection = require("../app/ssh")
|
||||||
|
const { SSHConnectionError } = require("../app/errors")
|
||||||
|
const { maskSensitiveData } = require("../app/utils")
|
||||||
|
|
||||||
|
jest.mock("ssh2")
|
||||||
|
jest.mock("../app/logger", () => ({
|
||||||
|
createNamespacedDebug: jest.fn(() => jest.fn()),
|
||||||
|
logError: jest.fn()
|
||||||
|
}))
|
||||||
|
jest.mock("../app/utils", () => ({
|
||||||
|
maskSensitiveData: jest.fn(data => data)
|
||||||
|
}))
|
||||||
|
jest.mock("../app/errors", () => ({
|
||||||
|
SSHConnectionError: jest.fn(function(message) {
|
||||||
|
this.message = message
|
||||||
|
}),
|
||||||
|
handleError: jest.fn()
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe("SSHConnection", () => {
|
||||||
|
let sshConnection
|
||||||
|
let mockConfig
|
||||||
|
let mockSSH2Client
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockConfig = {
|
||||||
|
ssh: {
|
||||||
|
algorithms: {
|
||||||
|
kex: ["algo1", "algo2"],
|
||||||
|
cipher: ["cipher1", "cipher2"],
|
||||||
|
serverHostKey: ["ssh-rsa", "ssh-dss"],
|
||||||
|
hmac: ["hmac1", "hmac2"],
|
||||||
|
compress: ["none", "zlib"]
|
||||||
|
},
|
||||||
|
readyTimeout: 20000,
|
||||||
|
keepaliveInterval: 60000,
|
||||||
|
keepaliveCountMax: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sshConnection = new SSHConnection(mockConfig)
|
||||||
|
mockSSH2Client = {
|
||||||
|
on: jest.fn(),
|
||||||
|
connect: jest.fn(),
|
||||||
|
shell: jest.fn(),
|
||||||
|
end: jest.fn()
|
||||||
|
}
|
||||||
|
SSH2.Client.mockImplementation(() => mockSSH2Client)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("connect", () => {
|
||||||
|
// ... previous tests ...
|
||||||
|
|
||||||
|
it("should handle connection errors", () => {
|
||||||
|
const mockCreds = {
|
||||||
|
host: "example.com",
|
||||||
|
port: 22,
|
||||||
|
username: "user",
|
||||||
|
password: "pass"
|
||||||
|
}
|
||||||
|
|
||||||
|
mockSSH2Client.on.mockImplementation((event, callback) => {
|
||||||
|
if (event === "error") {
|
||||||
|
callback(new Error("Connection failed"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return sshConnection.connect(mockCreds).catch(error => {
|
||||||
|
expect(error).toBeInstanceOf(SSHConnectionError)
|
||||||
|
expect(error.message).toBe("SSH Connection error: Connection failed")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("shell", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
sshConnection.conn = mockSSH2Client
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should open a shell successfully", () => {
|
||||||
|
const mockStream = {
|
||||||
|
on: jest.fn(),
|
||||||
|
stderr: { on: jest.fn() }
|
||||||
|
}
|
||||||
|
|
||||||
|
mockSSH2Client.shell.mockImplementation((options, callback) => {
|
||||||
|
callback(null, mockStream)
|
||||||
|
})
|
||||||
|
|
||||||
|
return sshConnection.shell().then(result => {
|
||||||
|
expect(result).toBe(mockStream)
|
||||||
|
expect(sshConnection.stream).toBe(mockStream)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle shell errors", () => {
|
||||||
|
mockSSH2Client.shell.mockImplementation((options, callback) => {
|
||||||
|
callback(new Error("Shell error"))
|
||||||
|
})
|
||||||
|
|
||||||
|
return sshConnection.shell().catch(error => {
|
||||||
|
expect(error.message).toBe("Shell error")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("resizeTerminal", () => {
|
||||||
|
it("should resize the terminal if stream exists", () => {
|
||||||
|
const mockStream = {
|
||||||
|
setWindow: jest.fn()
|
||||||
|
}
|
||||||
|
sshConnection.stream = mockStream
|
||||||
|
|
||||||
|
sshConnection.resizeTerminal(80, 24)
|
||||||
|
|
||||||
|
expect(mockStream.setWindow).toHaveBeenCalledWith(80, 24)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should not resize if stream does not exist", () => {
|
||||||
|
sshConnection.stream = null
|
||||||
|
|
||||||
|
sshConnection.resizeTerminal(80, 24)
|
||||||
|
|
||||||
|
// No error should be thrown
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("end", () => {
|
||||||
|
it("should end the stream and connection", () => {
|
||||||
|
const mockStream = {
|
||||||
|
end: jest.fn()
|
||||||
|
}
|
||||||
|
sshConnection.stream = mockStream
|
||||||
|
sshConnection.conn = mockSSH2Client
|
||||||
|
|
||||||
|
sshConnection.end()
|
||||||
|
|
||||||
|
expect(mockStream.end).toHaveBeenCalled()
|
||||||
|
expect(mockSSH2Client.end).toHaveBeenCalled()
|
||||||
|
expect(sshConnection.stream).toBeNull()
|
||||||
|
expect(sshConnection.conn).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should handle ending when stream and connection do not exist", () => {
|
||||||
|
sshConnection.stream = null
|
||||||
|
sshConnection.conn = null
|
||||||
|
|
||||||
|
sshConnection.end()
|
||||||
|
|
||||||
|
// No error should be thrown
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue