Implement last opened functionality (#4633)
* Implement last opened functionality Fixes https://github.com/cdr/code-server/issues/4619 * Fix test temp dirs not being cleaned up * Mock logger everywhere This suppresses all the error and debug output we generate which makes it hard to actually find which test has failed. It also gives us a standard way to test logging for the few places we do that. * Use separate data directories for unit test instances Exactly as we do for the e2e tests. * Add integration tests for vscode route * Make settings use --user-data-dir Without this test instances step on each other feet and they also clobber your own non-test settings. * Make redirects consistent They will preserve the trailing slash if there is one. * Remove compilation check If you do a regular non-watch build there are no compilation stats so this bricks VS Code in CI when running the unit tests. I am not sure how best to fix this for the case where you have a build that has not been packaged yet so I just removed it for now and added a message to check if VS Code is compiling when in dev mode. * Update code-server update endpoint name
This commit is contained in:
@ -1,27 +1,29 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import { promises, rmdirSync } from "fs"
|
||||
import { promises } from "fs"
|
||||
import * as http from "http"
|
||||
import * as https from "https"
|
||||
import * as path from "path"
|
||||
import { createApp, ensureAddress, handleArgsSocketCatchError, handleServerError } from "../../../src/node/app"
|
||||
import { OptionalString, setDefaults } from "../../../src/node/cli"
|
||||
import { generateCertificate } from "../../../src/node/util"
|
||||
import { getAvailablePort, tmpdir } from "../../utils/helpers"
|
||||
import { clean, mockLogger, getAvailablePort, tmpdir } from "../../utils/helpers"
|
||||
|
||||
describe("createApp", () => {
|
||||
let spy: jest.SpyInstance
|
||||
let unlinkSpy: jest.SpyInstance
|
||||
let port: number
|
||||
let tmpDirPath: string
|
||||
let tmpFilePath: string
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpDirPath = await tmpdir("unlink-socket")
|
||||
mockLogger()
|
||||
|
||||
const testName = "unlink-socket"
|
||||
await clean(testName)
|
||||
tmpDirPath = await tmpdir(testName)
|
||||
tmpFilePath = path.join(tmpDirPath, "unlink-socket-file")
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(logger, "error")
|
||||
// NOTE:@jsjoeio
|
||||
// Be mindful when spying.
|
||||
// You can't spy on fs functions if you do import * as fs
|
||||
@ -36,12 +38,6 @@ describe("createApp", () => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks()
|
||||
// Ensure directory was removed
|
||||
rmdirSync(tmpDirPath, { recursive: true })
|
||||
})
|
||||
|
||||
it("should return an Express app, a WebSockets Express app and an http server", async () => {
|
||||
const defaultArgs = await setDefaults({
|
||||
port,
|
||||
@ -70,8 +66,8 @@ describe("createApp", () => {
|
||||
// By emitting an error event
|
||||
// Ref: https://stackoverflow.com/a/33872506/3015595
|
||||
app.server.emit("error", testError)
|
||||
expect(spy).toHaveBeenCalledTimes(1)
|
||||
expect(spy).toHaveBeenCalledWith(`http server error: ${testError.message} ${testError.stack}`)
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(`http server error: ${testError.message} ${testError.stack}`)
|
||||
|
||||
// Cleanup
|
||||
app.dispose()
|
||||
@ -152,20 +148,14 @@ describe("ensureAddress", () => {
|
||||
})
|
||||
|
||||
describe("handleServerError", () => {
|
||||
let spy: jest.SpyInstance
|
||||
|
||||
beforeEach(() => {
|
||||
spy = jest.spyOn(logger, "error")
|
||||
beforeAll(() => {
|
||||
mockLogger()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
it("should call reject if resolved is false", async () => {
|
||||
const resolved = false
|
||||
const reject = jest.fn((err: Error) => undefined)
|
||||
@ -184,33 +174,27 @@ describe("handleServerError", () => {
|
||||
|
||||
handleServerError(resolved, error, reject)
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1)
|
||||
expect(spy).toThrowErrorMatchingSnapshot()
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(`http server error: ${error.message} ${error.stack}`)
|
||||
})
|
||||
})
|
||||
|
||||
describe("handleArgsSocketCatchError", () => {
|
||||
let spy: jest.SpyInstance
|
||||
|
||||
beforeEach(() => {
|
||||
spy = jest.spyOn(logger, "error")
|
||||
beforeAll(() => {
|
||||
mockLogger()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
it("should log an error if its not an NodeJS.ErrnoException", () => {
|
||||
const error = new Error()
|
||||
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1)
|
||||
expect(spy).toHaveBeenCalledWith(error)
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(error)
|
||||
})
|
||||
|
||||
it("should log an error if its not an NodeJS.ErrnoException (and the error has a message)", () => {
|
||||
@ -219,8 +203,8 @@ describe("handleArgsSocketCatchError", () => {
|
||||
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1)
|
||||
expect(spy).toHaveBeenCalledWith(errorMessage)
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(errorMessage)
|
||||
})
|
||||
|
||||
it("should not log an error if its a iNodeJS.ErrnoException", () => {
|
||||
@ -229,7 +213,7 @@ describe("handleArgsSocketCatchError", () => {
|
||||
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(0)
|
||||
expect(logger.error).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
|
||||
it("should log an error if the code is not ENOENT (and the error has a message)", () => {
|
||||
@ -240,8 +224,8 @@ describe("handleArgsSocketCatchError", () => {
|
||||
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1)
|
||||
expect(spy).toHaveBeenCalledWith(errorMessage)
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(errorMessage)
|
||||
})
|
||||
|
||||
it("should log an error if the code is not ENOENT", () => {
|
||||
@ -250,7 +234,7 @@ describe("handleArgsSocketCatchError", () => {
|
||||
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1)
|
||||
expect(spy).toHaveBeenCalledWith(error)
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(error)
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user