generated from nhcarrigan/template
feat: multiple improvements to library functionality #50
+4
-1
@@ -3,7 +3,10 @@ module.exports = {
|
||||
preset: '../jest.preset.js',
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
||||
'^.+\\.[tj]s$': ['ts-jest', {
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
isolatedModules: true,
|
||||
}],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../coverage/api',
|
||||
|
||||
@@ -57,5 +57,13 @@ export async function app(fastify: FastifyInstance, opts: AppOptions) {
|
||||
fastify.register(AutoLoad, {
|
||||
dir: path.join(__dirname, 'routes'),
|
||||
options: { ...opts, prefix: '/api' },
|
||||
ignorePattern: /root\.ts$/,
|
||||
});
|
||||
|
||||
// Register root route without prefix
|
||||
fastify.register(AutoLoad, {
|
||||
dir: path.join(__dirname, 'routes'),
|
||||
options: { ...opts },
|
||||
matchFilter: /root\.ts$/,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,30 @@
|
||||
import { FastifyInstance } from 'fastify';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
interface PackageJson {
|
||||
version: string;
|
||||
}
|
||||
|
||||
let cachedVersion: string | null = null;
|
||||
|
||||
function getVersion(): string {
|
||||
if (cachedVersion) {
|
||||
return cachedVersion;
|
||||
}
|
||||
|
||||
try {
|
||||
const packageJsonPath = join(process.cwd(), 'package.json');
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as PackageJson;
|
||||
cachedVersion = packageJson.version;
|
||||
return cachedVersion;
|
||||
} catch {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
export default async function (fastify: FastifyInstance) {
|
||||
fastify.get('/', async function () {
|
||||
return { message: 'Hello API' };
|
||||
return { version: getVersion() };
|
||||
});
|
||||
}
|
||||
|
||||
+33
-1
@@ -12,4 +12,36 @@ process.env.DOMAIN = 'http://localhost:3000';
|
||||
process.env.API_URL = 'http://localhost:3000/api';
|
||||
process.env.DATABASE_URL = 'postgresql://test:test@localhost:5432/test';
|
||||
process.env.BASE_URL = 'http://localhost:4200';
|
||||
process.env.NODE_ENV = 'test';
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
// Mock ESM packages to avoid import issues in Jest
|
||||
jest.mock('jsdom', () => ({
|
||||
JSDOM: class {
|
||||
window = {
|
||||
document: {
|
||||
createElement: jest.fn(() => ({})),
|
||||
},
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('marked', () => ({
|
||||
marked: jest.fn((input: string) => `<p>${input}</p>`),
|
||||
}));
|
||||
|
||||
jest.mock('dompurify', () => {
|
||||
const mockDOMPurify = {
|
||||
sanitize: jest.fn((input: string) => input),
|
||||
addHook: jest.fn(),
|
||||
};
|
||||
const createDOMPurify = jest.fn(() => mockDOMPurify);
|
||||
return createDOMPurify;
|
||||
});
|
||||
|
||||
jest.mock('@nhcarrigan/logger', () => ({
|
||||
Logger: class {
|
||||
log = jest.fn().mockResolvedValue(undefined);
|
||||
error = jest.fn().mockResolvedValue(undefined);
|
||||
metric = jest.fn().mockResolvedValue(undefined);
|
||||
},
|
||||
}));
|
||||
@@ -10,6 +10,7 @@
|
||||
"jest.config.ts",
|
||||
"jest.config.cts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.ts"
|
||||
"src/**/*.test.ts",
|
||||
"src/test-setup.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ import { ApiService } from '../../services/api.service';
|
||||
[alt]="user.username"
|
||||
class="user-avatar"
|
||||
(click)="toggleDropdown()"
|
||||
(keyup.enter)="toggleDropdown()"
|
||||
(keyup.space)="toggleDropdown()"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
/>
|
||||
}
|
||||
@if (showDropdown()) {
|
||||
|
||||
@@ -6,7 +6,14 @@
|
||||
|
||||
<div class="toast-container">
|
||||
@for (toast of toastService.toastList(); track toast.id) {
|
||||
<div class="toast toast-{{ toast.type }}" (click)="toastService.remove(toast.id)">
|
||||
<div
|
||||
class="toast toast-{{ toast.type }}"
|
||||
(click)="toastService.remove(toast.id)"
|
||||
(keyup.enter)="toastService.remove(toast.id)"
|
||||
(keyup.space)="toastService.remove(toast.id)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
>
|
||||
<div class="toast-icon">
|
||||
@switch (toast.type) {
|
||||
@case ('error') { ❌ }
|
||||
|
||||
@@ -17,10 +17,11 @@ describe("book Types", () => {
|
||||
|
||||
it("should have all expected enum values", () => {
|
||||
const values = Object.values(BookStatus);
|
||||
expect(values).toHaveLength(3);
|
||||
expect(values).toHaveLength(4);
|
||||
expect(values).toContain("READING");
|
||||
expect(values).toContain("FINISHED");
|
||||
expect(values).toContain("TO_READ");
|
||||
expect(values).toContain("RETIRED");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -17,10 +17,11 @@ describe("game Types", () => {
|
||||
|
||||
it("should have all expected enum values", () => {
|
||||
const values = Object.values(GameStatus);
|
||||
expect(values).toHaveLength(3);
|
||||
expect(values).toHaveLength(4);
|
||||
expect(values).toContain("PLAYING");
|
||||
expect(values).toContain("COMPLETED");
|
||||
expect(values).toContain("BACKLOG");
|
||||
expect(values).toContain("RETIRED");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -17,10 +17,11 @@ describe("manga Types", () => {
|
||||
|
||||
it("should have all expected enum values", () => {
|
||||
const values = Object.values(MangaStatus);
|
||||
expect(values).toHaveLength(3);
|
||||
expect(values).toHaveLength(4);
|
||||
expect(values).toContain("READING");
|
||||
expect(values).toContain("COMPLETED");
|
||||
expect(values).toContain("WANT_TO_READ");
|
||||
expect(values).toContain("RETIRED");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -33,10 +33,11 @@ describe("music Types", () => {
|
||||
|
||||
it("should have all expected enum values", () => {
|
||||
const values = Object.values(MusicStatus);
|
||||
expect(values).toHaveLength(3);
|
||||
expect(values).toHaveLength(4);
|
||||
expect(values).toContain("LISTENING");
|
||||
expect(values).toContain("COMPLETED");
|
||||
expect(values).toContain("WANT_TO_LISTEN");
|
||||
expect(values).toContain("RETIRED");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -35,10 +35,11 @@ describe("show Types", () => {
|
||||
|
||||
it("should have all expected enum values", () => {
|
||||
const values = Object.values(ShowStatus);
|
||||
expect(values).toHaveLength(3);
|
||||
expect(values).toHaveLength(4);
|
||||
expect(values).toContain("WATCHING");
|
||||
expect(values).toContain("COMPLETED");
|
||||
expect(values).toContain("WANT_TO_WATCH");
|
||||
expect(values).toContain("RETIRED");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user