66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
assertSafeSelect,
|
|
buildWhereClause,
|
|
quoteIdentifier,
|
|
resolveDatabaseName,
|
|
validateProcedureDefinition
|
|
} from "../src/sql.js";
|
|
|
|
describe("SQL helper safety", () => {
|
|
it("quotes SQL Server identifiers and escapes closing brackets", () => {
|
|
expect(quoteIdentifier("dbo")).toBe("[dbo]");
|
|
expect(quoteIdentifier("stock]audit")).toBe("[stock]]audit]");
|
|
});
|
|
|
|
it("rejects empty identifiers", () => {
|
|
expect(() => quoteIdentifier("")).toThrow(/identifier/i);
|
|
});
|
|
|
|
it("requires safe single-statement SELECT queries", () => {
|
|
expect(() => assertSafeSelect("select top 1 * from dbo.Users")).not.toThrow();
|
|
expect(() => assertSafeSelect("with cte as (select 1 as id) select * from cte")).not.toThrow();
|
|
expect(() => assertSafeSelect("update dbo.Users set name = 'x'")).toThrow(/select/i);
|
|
expect(() => assertSafeSelect("select * from dbo.Users; drop table dbo.Users")).toThrow(/single/i);
|
|
});
|
|
|
|
it("builds parameterized WHERE clauses from object criteria", () => {
|
|
const where = buildWhereClause({ id: 1, status: "pending" }, "w");
|
|
|
|
expect(where.clause).toBe("[id] = @w0 AND [status] = @w1");
|
|
expect(where.params).toEqual([
|
|
{ name: "w0", value: 1 },
|
|
{ name: "w1", value: "pending" }
|
|
]);
|
|
});
|
|
|
|
it("rejects empty WHERE criteria", () => {
|
|
expect(() => buildWhereClause({}, "w")).toThrow(/where/i);
|
|
});
|
|
|
|
it("restricts database selection to the configured allowlist", () => {
|
|
expect(resolveDatabaseName(undefined, "MainDb", ["MainDb", "ReportDb"])).toBe("MainDb");
|
|
expect(resolveDatabaseName("ReportDb", "MainDb", ["MainDb", "ReportDb"])).toBe("ReportDb");
|
|
expect(() => resolveDatabaseName("OtherDb", "MainDb", ["MainDb", "ReportDb"])).toThrow(/allowed/i);
|
|
});
|
|
|
|
it("validates stored procedure definitions before execution", () => {
|
|
expect(() =>
|
|
validateProcedureDefinition(
|
|
"CREATE OR ALTER PROCEDURE [dbo].[p_test] AS BEGIN SELECT 1 END",
|
|
"dbo",
|
|
"p_test"
|
|
)
|
|
).not.toThrow();
|
|
|
|
expect(() => validateProcedureDefinition("SELECT 1", "dbo", "p_test")).toThrow(/procedure/i);
|
|
expect(() =>
|
|
validateProcedureDefinition(
|
|
"CREATE OR ALTER PROCEDURE [dbo].[other_proc] AS BEGIN SELECT 1 END",
|
|
"dbo",
|
|
"p_test"
|
|
)
|
|
).toThrow(/name/i);
|
|
});
|
|
});
|