Improve test coverage
This commit is contained in:
parent
6bdf7a32a9
commit
b2a0cafe6e
|
@ -17,6 +17,7 @@
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-inferrable-types": 0,
|
"@typescript-eslint/no-inferrable-types": 0,
|
||||||
"@typescript-eslint/no-unused-vars": 2,
|
"@typescript-eslint/no-unused-vars": 2,
|
||||||
"@typescript-eslint/no-var-requires": 0
|
"@typescript-eslint/no-var-requires": 0,
|
||||||
|
"@typescript-eslint/no-explicit-any": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||||
|
|
||||||
|
describe("Environment Configuration", () => {
|
||||||
|
const originalEnv = process.env;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.resetModules();
|
||||||
|
process.env = { ...originalEnv };
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
process.env = originalEnv;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set NODE_ENV to development by default", async () => {
|
||||||
|
delete process.env.NODE_ENV;
|
||||||
|
const { envs, isProduction } = await import("./index");
|
||||||
|
expect(envs.NODE_ENV).toBe("development");
|
||||||
|
expect(isProduction).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use existing NODE_ENV if set", async () => {
|
||||||
|
process.env.NODE_ENV = "production";
|
||||||
|
const { envs, isProduction } = await import("./index");
|
||||||
|
expect(envs.NODE_ENV).toBe("production");
|
||||||
|
expect(isProduction).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should export config from dotenv-flow", async () => {
|
||||||
|
const { config } = await import("./index");
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||||
|
import { $log } from "@tsed/common";
|
||||||
|
|
||||||
|
vi.mock("@tsed/common", () => ({
|
||||||
|
$log: {
|
||||||
|
appenders: {
|
||||||
|
set: vi.fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe("Logger Configuration", () => {
|
||||||
|
const originalEnv = process.env;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.resetModules();
|
||||||
|
vi.clearAllMocks();
|
||||||
|
process.env = { ...originalEnv };
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
process.env = originalEnv;
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not set appenders in non-production environment", async () => {
|
||||||
|
process.env.NODE_ENV = "development";
|
||||||
|
await import("./index");
|
||||||
|
expect($log.appenders.set).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set appenders in production environment", async () => {
|
||||||
|
process.env.NODE_ENV = "production";
|
||||||
|
await import("./index");
|
||||||
|
|
||||||
|
expect($log.appenders.set).toHaveBeenCalledTimes(2);
|
||||||
|
expect($log.appenders.set).toHaveBeenCalledWith("stdout", {
|
||||||
|
type: "stdout",
|
||||||
|
levels: ["info", "debug"],
|
||||||
|
layout: {
|
||||||
|
type: "json"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect($log.appenders.set).toHaveBeenCalledWith("stderr", {
|
||||||
|
levels: ["trace", "fatal", "error", "warn"],
|
||||||
|
type: "stderr",
|
||||||
|
layout: {
|
||||||
|
type: "json"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should export correct DILoggerOptions in non-production", async () => {
|
||||||
|
process.env.NODE_ENV = "development";
|
||||||
|
const { default: loggerOptions } = await import("./index");
|
||||||
|
expect(loggerOptions).toEqual({
|
||||||
|
disableRoutesSummary: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should export correct DILoggerOptions in production", async () => {
|
||||||
|
process.env.NODE_ENV = "production";
|
||||||
|
const { default: loggerOptions } = await import("./index");
|
||||||
|
expect(loggerOptions).toEqual({
|
||||||
|
disableRoutesSummary: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { IndexController } from "./IndexController";
|
||||||
|
import { describe, it, expect, beforeEach } from "vitest";
|
||||||
|
|
||||||
|
describe("IndexController", () => {
|
||||||
|
let controller: IndexController;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
controller = new IndexController();
|
||||||
|
// @ts-expect-error - swagger is private
|
||||||
|
controller.swagger = [
|
||||||
|
{ path: "/api-docs", specVersion: "3.0.1" },
|
||||||
|
{ path: "/api-docs-2", specVersion: "3.0.2" }
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return correct view data", () => {
|
||||||
|
const protocol = "https";
|
||||||
|
const host = "example.com";
|
||||||
|
|
||||||
|
const result = controller.get(protocol, host);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
BASE_URL: "https://example.com",
|
||||||
|
docs: [
|
||||||
|
{ url: "https://example.com/api-docs", path: "/api-docs", specVersion: "3.0.1" },
|
||||||
|
{ url: "https://example.com/api-docs-2", path: "/api-docs-2", specVersion: "3.0.2" }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use http when protocol is not provided", () => {
|
||||||
|
const host = "example.com";
|
||||||
|
|
||||||
|
const result = controller.get("", host);
|
||||||
|
|
||||||
|
expect(result.BASE_URL).toBe("http://example.com");
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from "vitest";
|
||||||
|
import { Server } from "./Server";
|
||||||
|
|
||||||
|
vi.mock("@tsed/common", () => ({
|
||||||
|
$log: {
|
||||||
|
error: vi.fn()
|
||||||
|
},
|
||||||
|
PlatformApplication: vi.fn()
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@tsed/platform-express", () => ({
|
||||||
|
PlatformExpress: {
|
||||||
|
bootstrap: vi.fn()
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe("bootstrap function", () => {
|
||||||
|
let bootstrap: () => Promise<void>;
|
||||||
|
let mockPlatform: {
|
||||||
|
listen: Mock;
|
||||||
|
stop: Mock;
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
|
||||||
|
mockPlatform = {
|
||||||
|
listen: vi.fn().mockResolvedValue(undefined),
|
||||||
|
stop: vi.fn().mockResolvedValue(undefined)
|
||||||
|
};
|
||||||
|
|
||||||
|
const { PlatformExpress } = await import("@tsed/platform-express");
|
||||||
|
(PlatformExpress.bootstrap as Mock).mockResolvedValue(mockPlatform);
|
||||||
|
|
||||||
|
const module = await import("./index");
|
||||||
|
bootstrap = module.bootstrap;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should bootstrap the server successfully", async () => {
|
||||||
|
await bootstrap();
|
||||||
|
const { PlatformExpress } = await import("@tsed/platform-express");
|
||||||
|
expect(PlatformExpress.bootstrap).toHaveBeenCalledWith(Server);
|
||||||
|
expect(mockPlatform.listen).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle errors during bootstrap", async () => {
|
||||||
|
const error = new Error("Bootstrap error");
|
||||||
|
const { PlatformExpress } = await import("@tsed/platform-express");
|
||||||
|
(PlatformExpress.bootstrap as Mock).mockRejectedValueOnce(error);
|
||||||
|
|
||||||
|
await bootstrap();
|
||||||
|
|
||||||
|
const { $log } = await import("@tsed/common");
|
||||||
|
expect($log.error).toHaveBeenCalledWith({
|
||||||
|
event: "SERVER_BOOTSTRAP_ERROR",
|
||||||
|
message: error.message,
|
||||||
|
stack: error.stack
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should set up SIGINT handler", async () => {
|
||||||
|
const processOnSpy = vi.spyOn(process, "on");
|
||||||
|
await bootstrap();
|
||||||
|
expect(processOnSpy).toHaveBeenCalledWith("SIGINT", expect.any(Function));
|
||||||
|
|
||||||
|
// Simulate SIGINT
|
||||||
|
const sigintHandler = processOnSpy.mock.calls.find((call) => call[0] === "SIGINT")?.[1];
|
||||||
|
if (sigintHandler && typeof sigintHandler === "function") {
|
||||||
|
sigintHandler();
|
||||||
|
expect(mockPlatform.stop).toHaveBeenCalled();
|
||||||
|
} else {
|
||||||
|
throw new Error("SIGINT handler not found or not a function");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -2,11 +2,10 @@ import { $log } from "@tsed/common";
|
||||||
import { PlatformExpress } from "@tsed/platform-express";
|
import { PlatformExpress } from "@tsed/platform-express";
|
||||||
import { Server } from "./Server";
|
import { Server } from "./Server";
|
||||||
|
|
||||||
async function bootstrap() {
|
export async function bootstrap() {
|
||||||
try {
|
try {
|
||||||
const platform = await PlatformExpress.bootstrap(Server);
|
const platform = await PlatformExpress.bootstrap(Server);
|
||||||
await platform.listen();
|
await platform.listen();
|
||||||
|
|
||||||
process.on("SIGINT", () => {
|
process.on("SIGINT", () => {
|
||||||
platform.stop();
|
platform.stop();
|
||||||
});
|
});
|
||||||
|
@ -15,4 +14,7 @@ async function bootstrap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only call bootstrap if this file is being run directly
|
||||||
|
if (require.main === module) {
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"useDefineForClassFields": false,
|
"useDefineForClassFields": false,
|
||||||
"lib": ["es7", "dom", "ESNext.AsyncIterable"],
|
"lib": ["es7", "dom", "ESNext.AsyncIterable"],
|
||||||
"typeRoots": ["./node_modules/@types"]
|
"typeRoots": ["./node_modules/@types"],
|
||||||
|
"noEmitHelpers": false
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
"linterOptions": {
|
"linterOptions": {
|
||||||
|
|
|
@ -4,7 +4,10 @@ import { defineConfig } from "vitest/config";
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
root: "./"
|
root: "./",
|
||||||
|
coverage: {
|
||||||
|
exclude: ["./processes.config.js", "vitest.config.mts"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
// This is required to build the test files with SWC
|
// This is required to build the test files with SWC
|
||||||
|
|
Loading…
Reference in New Issue