feat(#369): install @mosaicstack/telemetry-client in API
- Add .npmrc with scoped Gitea npm registry for @mosaicstack packages - Create MosaicTelemetryModule (global, lifecycle-aware) at apps/api/src/mosaic-telemetry/ - Create MosaicTelemetryService wrapping TelemetryClient with convenience methods: trackTaskCompletion, getPrediction, refreshPredictions, eventBuilder - Create mosaic-telemetry.config.ts for env var integration via NestJS ConfigService - Register MosaicTelemetryModule in AppModule - Add 32 unit tests covering module init, service methods, disabled mode, dry-run mode, and lifecycle management Refs #369 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
212
apps/api/src/mosaic-telemetry/mosaic-telemetry.module.spec.ts
Normal file
212
apps/api/src/mosaic-telemetry/mosaic-telemetry.module.spec.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { ConfigModule } from "@nestjs/config";
|
||||
import { MosaicTelemetryModule } from "./mosaic-telemetry.module";
|
||||
import { MosaicTelemetryService } from "./mosaic-telemetry.service";
|
||||
|
||||
// Mock the telemetry client to avoid real HTTP calls
|
||||
vi.mock("@mosaicstack/telemetry-client", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("@mosaicstack/telemetry-client")>();
|
||||
|
||||
class MockTelemetryClient {
|
||||
private _isRunning = false;
|
||||
|
||||
constructor(_config: unknown) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
get eventBuilder() {
|
||||
return { build: vi.fn().mockReturnValue({ event_id: "test-event-id" }) };
|
||||
}
|
||||
|
||||
start(): void {
|
||||
this._isRunning = true;
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
this._isRunning = false;
|
||||
}
|
||||
|
||||
track(_event: unknown): void {
|
||||
// no-op
|
||||
}
|
||||
|
||||
getPrediction(_query: unknown): unknown {
|
||||
return null;
|
||||
}
|
||||
|
||||
async refreshPredictions(_queries: unknown): Promise<void> {
|
||||
// no-op
|
||||
}
|
||||
|
||||
get queueSize(): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
get isRunning(): boolean {
|
||||
return this._isRunning;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...actual,
|
||||
TelemetryClient: MockTelemetryClient,
|
||||
};
|
||||
});
|
||||
|
||||
describe("MosaicTelemetryModule", () => {
|
||||
let module: TestingModule;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("module initialization", () => {
|
||||
it("should compile the module successfully", async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: [],
|
||||
load: [
|
||||
() => ({
|
||||
MOSAIC_TELEMETRY_ENABLED: "false",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
MosaicTelemetryModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
expect(module).toBeDefined();
|
||||
await module.close();
|
||||
});
|
||||
|
||||
it("should provide MosaicTelemetryService", async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: [],
|
||||
load: [
|
||||
() => ({
|
||||
MOSAIC_TELEMETRY_ENABLED: "false",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
MosaicTelemetryModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
const service = module.get<MosaicTelemetryService>(MosaicTelemetryService);
|
||||
expect(service).toBeDefined();
|
||||
expect(service).toBeInstanceOf(MosaicTelemetryService);
|
||||
|
||||
await module.close();
|
||||
});
|
||||
|
||||
it("should export MosaicTelemetryService for injection in other modules", async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: [],
|
||||
load: [
|
||||
() => ({
|
||||
MOSAIC_TELEMETRY_ENABLED: "false",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
MosaicTelemetryModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
const service = module.get(MosaicTelemetryService);
|
||||
expect(service).toBeDefined();
|
||||
|
||||
await module.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe("lifecycle integration", () => {
|
||||
it("should initialize service on module init when enabled", async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: [],
|
||||
load: [
|
||||
() => ({
|
||||
MOSAIC_TELEMETRY_ENABLED: "true",
|
||||
MOSAIC_TELEMETRY_SERVER_URL: "https://tel.test.local",
|
||||
MOSAIC_TELEMETRY_API_KEY: "a".repeat(64),
|
||||
MOSAIC_TELEMETRY_INSTANCE_ID: "550e8400-e29b-41d4-a716-446655440000",
|
||||
MOSAIC_TELEMETRY_DRY_RUN: "false",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
MosaicTelemetryModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
await module.init();
|
||||
|
||||
const service = module.get<MosaicTelemetryService>(MosaicTelemetryService);
|
||||
expect(service.isEnabled).toBe(true);
|
||||
|
||||
await module.close();
|
||||
});
|
||||
|
||||
it("should not start client when disabled via env", async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: [],
|
||||
load: [
|
||||
() => ({
|
||||
MOSAIC_TELEMETRY_ENABLED: "false",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
MosaicTelemetryModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
await module.init();
|
||||
|
||||
const service = module.get<MosaicTelemetryService>(MosaicTelemetryService);
|
||||
expect(service.isEnabled).toBe(false);
|
||||
|
||||
await module.close();
|
||||
});
|
||||
|
||||
it("should cleanly shut down on module destroy", async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: [],
|
||||
load: [
|
||||
() => ({
|
||||
MOSAIC_TELEMETRY_ENABLED: "true",
|
||||
MOSAIC_TELEMETRY_SERVER_URL: "https://tel.test.local",
|
||||
MOSAIC_TELEMETRY_API_KEY: "a".repeat(64),
|
||||
MOSAIC_TELEMETRY_INSTANCE_ID: "550e8400-e29b-41d4-a716-446655440000",
|
||||
MOSAIC_TELEMETRY_DRY_RUN: "false",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
MosaicTelemetryModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
await module.init();
|
||||
|
||||
const service = module.get<MosaicTelemetryService>(MosaicTelemetryService);
|
||||
expect(service.isEnabled).toBe(true);
|
||||
|
||||
await expect(module.close()).resolves.not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user