deep research addressement
This commit is contained in:
@@ -3,32 +3,40 @@ import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import { wrap } from "@typeschema/valibot";
|
||||
import {
|
||||
CreateEnrollmentSchema,
|
||||
EnrollAdditionalSampleSchema,
|
||||
DeleteEnrollmentSchema,
|
||||
AnalyzeAudioSchema,
|
||||
AnalysisFilterSchema,
|
||||
AnalysisResultSchema,
|
||||
AnalysisFeedbackSchema,
|
||||
JobStatusSchema,
|
||||
} from "../schemas/voiceprint";
|
||||
|
||||
vi.mock("~/server/services/voiceprint.service", () => ({
|
||||
getEnrollments: vi.fn(),
|
||||
createEnrollment: vi.fn(),
|
||||
enrollAdditionalSample: vi.fn(),
|
||||
deleteEnrollment: vi.fn(),
|
||||
analyzeAudio: vi.fn(),
|
||||
reportAnalysisFeedback: vi.fn(),
|
||||
getAnalyses: vi.fn(),
|
||||
getAnalysisResult: vi.fn(),
|
||||
getJobStatus: vi.fn(),
|
||||
getUsageStats: vi.fn(),
|
||||
}));
|
||||
|
||||
import * as voiceprintService from "~/server/services/voiceprint.service";
|
||||
|
||||
const mockGetEnrollments = vi.mocked(voiceprintService.getEnrollments);
|
||||
const mockCreateEnrollment = vi.mocked(voiceprintService.createEnrollment);
|
||||
const mockEnrollAdditionalSample = vi.mocked(voiceprintService.enrollAdditionalSample);
|
||||
const mockDeleteEnrollment = vi.mocked(voiceprintService.deleteEnrollment);
|
||||
const mockAnalyzeAudio = vi.mocked(voiceprintService.analyzeAudio);
|
||||
const mockReportAnalysisFeedback = vi.mocked(voiceprintService.reportAnalysisFeedback);
|
||||
const mockGetAnalyses = vi.mocked(voiceprintService.getAnalyses);
|
||||
const mockGetAnalysisResult = vi.mocked(voiceprintService.getAnalysisResult);
|
||||
const mockGetJobStatus = vi.mocked(voiceprintService.getJobStatus);
|
||||
const mockGetUsageStats = vi.mocked(voiceprintService.getUsageStats);
|
||||
|
||||
type User = {
|
||||
id: string; email: string; name: string | null; image: string | null;
|
||||
@@ -54,6 +62,11 @@ function createCaller(user: User | null) {
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return mockCreateEnrollment(ctx.user.id, input.name, input.audioBase64);
|
||||
}),
|
||||
enrollAdditionalSample: t.procedure.use(isAuthed)
|
||||
.input(wrap(EnrollAdditionalSampleSchema))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return mockEnrollAdditionalSample(ctx.user.id, input.enrollmentId, input.audioBase64);
|
||||
}),
|
||||
deleteEnrollment: t.procedure.use(isAuthed)
|
||||
.input(wrap(DeleteEnrollmentSchema))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
@@ -64,6 +77,14 @@ function createCaller(user: User | null) {
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return mockAnalyzeAudio(ctx.user.id, input.audioBase64, input.enrollmentId);
|
||||
}),
|
||||
reportAnalysisFeedback: t.procedure.use(isAuthed)
|
||||
.input(wrap(AnalysisFeedbackSchema))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return mockReportAnalysisFeedback(ctx.user.id, input.analysisId, {
|
||||
isFalsePositive: input.isFalsePositive,
|
||||
notes: input.notes,
|
||||
});
|
||||
}),
|
||||
getAnalyses: t.procedure.use(isAuthed)
|
||||
.input(wrap(AnalysisFilterSchema))
|
||||
.query(async ({ ctx, input }) => {
|
||||
@@ -79,6 +100,9 @@ function createCaller(user: User | null) {
|
||||
.query(async ({ ctx, input }) => {
|
||||
return mockGetJobStatus(ctx.user.id, input.jobId);
|
||||
}),
|
||||
getUsageStats: t.procedure.use(isAuthed).query(async ({ ctx }) => {
|
||||
return mockGetUsageStats(ctx.user.id);
|
||||
}),
|
||||
});
|
||||
|
||||
const caller = t.createCallerFactory(router);
|
||||
@@ -131,6 +155,26 @@ describe("voiceprint.createEnrollment", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("voiceprint.enrollAdditionalSample", () => {
|
||||
it("enrolls an additional audio sample", async () => {
|
||||
const result = { id: "enr-1", enrollmentsCount: 3, enrollmentStatus: "Enrolled" };
|
||||
mockEnrollAdditionalSample.mockResolvedValue(result as never);
|
||||
const api = createCaller(makeUser());
|
||||
const res = await api.enrollAdditionalSample({
|
||||
enrollmentId: "enr-1",
|
||||
audioBase64: "bW9yZS1hdWRpbw==",
|
||||
});
|
||||
expect(res.enrollmentsCount).toBe(3);
|
||||
});
|
||||
|
||||
it("rejects missing enrollmentId", async () => {
|
||||
const api = createCaller(makeUser());
|
||||
await expect(
|
||||
api.enrollAdditionalSample({ enrollmentId: "", audioBase64: "dGVzdA==" }),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("voiceprint.deleteEnrollment", () => {
|
||||
it("deletes enrollment", async () => {
|
||||
mockDeleteEnrollment.mockResolvedValue({ id: "enr-1", isActive: false } as never);
|
||||
@@ -157,6 +201,20 @@ describe("voiceprint.analyzeAudio", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("voiceprint.reportAnalysisFeedback", () => {
|
||||
it("submits feedback on analysis", async () => {
|
||||
const result = { id: "ana-1", userFeedback: { isFalsePositive: true } };
|
||||
mockReportAnalysisFeedback.mockResolvedValue(result as never);
|
||||
const api = createCaller(makeUser());
|
||||
const res = await api.reportAnalysisFeedback({
|
||||
analysisId: "ana-1",
|
||||
isFalsePositive: true,
|
||||
notes: "Not synthetic",
|
||||
});
|
||||
expect((res.userFeedback as { isFalsePositive: boolean }).isFalsePositive).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("voiceprint.getAnalyses", () => {
|
||||
it("returns paginated analyses", async () => {
|
||||
const data = { items: [], total: 0, page: 1, limit: 20, totalPages: 0 };
|
||||
@@ -193,3 +251,14 @@ describe("voiceprint.getJobStatus", () => {
|
||||
expect(result.status).toBe("RUNNING");
|
||||
});
|
||||
});
|
||||
|
||||
describe("voiceprint.getUsageStats", () => {
|
||||
it("returns usage statistics", async () => {
|
||||
const stats = { analysesThisMonth: 5, activeEnrollments: 2 };
|
||||
mockGetUsageStats.mockResolvedValue(stats);
|
||||
const api = createCaller(makeUser());
|
||||
const result = await api.getUsageStats();
|
||||
expect(result.analysesThisMonth).toBe(5);
|
||||
expect(result.activeEnrollments).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user