120 lines
4.0 KiB
TypeScript
120 lines
4.0 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, mock, spyOn } from "bun:test"
|
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "fs"
|
|
import { join } from "path"
|
|
import os from "os"
|
|
|
|
import * as configModule from "./config"
|
|
import { lspManager } from "./lsp-server"
|
|
import { isDirectoryPath } from "./lsp-client-wrapper"
|
|
import { aggregateDiagnosticsForDirectory } from "./directory-diagnostics"
|
|
import type { Diagnostic } from "./types"
|
|
|
|
const diagnosticsMock = mock(async (_filePath: string) => ({ items: [] as Diagnostic[] }))
|
|
const getClientMock = mock(async () => ({ diagnostics: diagnosticsMock }))
|
|
const releaseClientMock = mock(() => {})
|
|
|
|
function createDiagnostic(message: string): Diagnostic {
|
|
return {
|
|
message,
|
|
severity: 1,
|
|
range: {
|
|
start: { line: 0, character: 0 },
|
|
end: { line: 0, character: 1 },
|
|
},
|
|
}
|
|
}
|
|
|
|
describe("directory diagnostics", () => {
|
|
beforeEach(() => {
|
|
diagnosticsMock.mockReset()
|
|
diagnosticsMock.mockImplementation(async (_filePath: string) => ({ items: [] }))
|
|
getClientMock.mockClear()
|
|
releaseClientMock.mockClear()
|
|
|
|
spyOn(configModule, "findServerForExtension").mockReturnValue({
|
|
status: "found",
|
|
server: {
|
|
id: "test-server",
|
|
command: ["test-server"],
|
|
extensions: [".ts"],
|
|
priority: 1,
|
|
},
|
|
})
|
|
spyOn(lspManager, "getClient").mockImplementation(getClientMock)
|
|
spyOn(lspManager, "releaseClient").mockImplementation(releaseClientMock)
|
|
})
|
|
|
|
afterEach(() => {
|
|
mock.restore()
|
|
})
|
|
|
|
describe("isDirectoryPath", () => {
|
|
it("returns true for existing directory", () => {
|
|
const tmp = mkdtempSync(join(os.tmpdir(), "omo-isdir-"))
|
|
try {
|
|
expect(isDirectoryPath(tmp)).toBe(true)
|
|
} finally {
|
|
rmSync(tmp, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it("returns false for existing file", () => {
|
|
const tmp = mkdtempSync(join(os.tmpdir(), "omo-isdir-file-"))
|
|
try {
|
|
const file = join(tmp, "test.txt")
|
|
writeFileSync(file, "content")
|
|
expect(isDirectoryPath(file)).toBe(false)
|
|
} finally {
|
|
rmSync(tmp, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it("returns false for non-existent path", () => {
|
|
const nonExistent = join(os.tmpdir(), "omo-nonexistent-" + Date.now())
|
|
expect(isDirectoryPath(nonExistent)).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe("aggregateDiagnosticsForDirectory", () => {
|
|
it("throws error when extension does not start with dot", async () => {
|
|
const tmp = mkdtempSync(join(os.tmpdir(), "omo-aggr-ext-"))
|
|
try {
|
|
await expect(aggregateDiagnosticsForDirectory(tmp, "ts")).rejects.toThrow(
|
|
'Extension must start with a dot (e.g., ".ts", not "ts")'
|
|
)
|
|
} finally {
|
|
rmSync(tmp, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it("throws error when directory does not exist", async () => {
|
|
const nonExistent = join(os.tmpdir(), "omo-nonexistent-dir-" + Date.now())
|
|
await expect(aggregateDiagnosticsForDirectory(nonExistent, ".ts")).rejects.toThrow(
|
|
"Directory does not exist"
|
|
)
|
|
})
|
|
|
|
it("#given diagnostics from multiple files #when aggregating directory diagnostics #then each entry includes the source file path", async () => {
|
|
const tmp = mkdtempSync(join(os.tmpdir(), "omo-aggr-files-"))
|
|
try {
|
|
const firstFile = join(tmp, "first.ts")
|
|
const secondFile = join(tmp, "second.ts")
|
|
|
|
writeFileSync(firstFile, "export const first = true\n")
|
|
writeFileSync(secondFile, "export const second = true\n")
|
|
|
|
diagnosticsMock.mockImplementation(async (filePath: string) => ({
|
|
items: [createDiagnostic(`problem in ${filePath}`)],
|
|
}))
|
|
|
|
const result = await aggregateDiagnosticsForDirectory(tmp, ".ts")
|
|
|
|
expect(result).toContain(`${firstFile}: error at 1:0: problem in ${firstFile}`)
|
|
expect(result).toContain(`${secondFile}: error at 1:0: problem in ${secondFile}`)
|
|
} finally {
|
|
rmSync(tmp, { recursive: true, force: true })
|
|
}
|
|
})
|
|
})
|
|
})
|