feat(#37-41): Add domains, ideas, relationships, agents, widgets schema
Schema additions for issues #37-41: New models: - Domain (#37): Life domains (work, marriage, homelab, etc.) - Idea (#38): Brain dumps with pgvector embeddings - Relationship (#39): Generic entity linking (blocks, depends_on) - Agent (#40): ClawdBot agent tracking with metrics - AgentSession (#40): Conversation session tracking - WidgetDefinition (#41): HUD widget registry - UserLayout (#41): Per-user dashboard configuration Updated models: - Task, Event, Project: Added domainId foreign key - User, Workspace: Added new relations New enums: - IdeaStatus: CAPTURED, PROCESSING, ACTIONABLE, ARCHIVED, DISCARDED - RelationshipType: BLOCKS, BLOCKED_BY, DEPENDS_ON, etc. - AgentStatus: IDLE, WORKING, WAITING, ERROR, TERMINATED - EntityType: Added IDEA, DOMAIN Migration: 20260129182803_add_domains_ideas_agents_widgets
This commit is contained in:
@@ -0,0 +1,772 @@
|
||||
import { describe, it, expect, beforeEach, vi } from "vitest";
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { ActivityLoggingInterceptor } from "./activity-logging.interceptor";
|
||||
import { ActivityService } from "../activity.service";
|
||||
import { ExecutionContext, CallHandler } from "@nestjs/common";
|
||||
import { of } from "rxjs";
|
||||
import { ActivityAction, EntityType } from "@prisma/client";
|
||||
|
||||
describe("ActivityLoggingInterceptor", () => {
|
||||
let interceptor: ActivityLoggingInterceptor;
|
||||
let activityService: ActivityService;
|
||||
|
||||
const mockActivityService = {
|
||||
logActivity: vi.fn(),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
ActivityLoggingInterceptor,
|
||||
{
|
||||
provide: ActivityService,
|
||||
useValue: mockActivityService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
interceptor = module.get<ActivityLoggingInterceptor>(
|
||||
ActivityLoggingInterceptor
|
||||
);
|
||||
activityService = module.get<ActivityService>(ActivityService);
|
||||
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
const createMockExecutionContext = (
|
||||
method: string,
|
||||
params: any = {},
|
||||
body: any = {},
|
||||
user: any = null,
|
||||
ip = "127.0.0.1",
|
||||
userAgent = "test-agent"
|
||||
): ExecutionContext => {
|
||||
return {
|
||||
switchToHttp: () => ({
|
||||
getRequest: () => ({
|
||||
method,
|
||||
params,
|
||||
body,
|
||||
user,
|
||||
ip,
|
||||
headers: {
|
||||
"user-agent": userAgent,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
getClass: () => ({ name: "TestController" }),
|
||||
getHandler: () => ({ name: "testMethod" }),
|
||||
} as any;
|
||||
};
|
||||
|
||||
const createMockCallHandler = (result: any = {}): CallHandler => {
|
||||
return {
|
||||
handle: () => of(result),
|
||||
} as any;
|
||||
};
|
||||
|
||||
describe("intercept", () => {
|
||||
it("should not log if user is not authenticated", async () => {
|
||||
const context = createMockExecutionContext("POST", {}, {}, null);
|
||||
const next = createMockCallHandler();
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should log POST request as CREATE action", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "task-123",
|
||||
workspaceId: "workspace-123",
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext(
|
||||
"POST",
|
||||
{},
|
||||
body,
|
||||
user,
|
||||
"127.0.0.1",
|
||||
"Mozilla/5.0"
|
||||
);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-123",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).toHaveBeenCalledWith({
|
||||
workspaceId: "workspace-123",
|
||||
userId: "user-123",
|
||||
action: ActivityAction.CREATED,
|
||||
entityType: expect.any(String),
|
||||
entityId: "task-123",
|
||||
details: expect.objectContaining({
|
||||
method: "POST",
|
||||
controller: "TestController",
|
||||
handler: "testMethod",
|
||||
}),
|
||||
ipAddress: "127.0.0.1",
|
||||
userAgent: "Mozilla/5.0",
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should log PATCH request as UPDATE action", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const params = {
|
||||
id: "task-456",
|
||||
};
|
||||
|
||||
const body = {
|
||||
status: "IN_PROGRESS",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "task-456",
|
||||
workspaceId: "workspace-123",
|
||||
status: "IN_PROGRESS",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("PATCH", params, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-124",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).toHaveBeenCalledWith({
|
||||
workspaceId: "workspace-123",
|
||||
userId: "user-123",
|
||||
action: ActivityAction.UPDATED,
|
||||
entityType: expect.any(String),
|
||||
entityId: "task-456",
|
||||
details: expect.objectContaining({
|
||||
method: "PATCH",
|
||||
changes: body,
|
||||
}),
|
||||
ipAddress: "127.0.0.1",
|
||||
userAgent: "test-agent",
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should log PUT request as UPDATE action", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const params = {
|
||||
id: "event-789",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "Updated Event",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "event-789",
|
||||
workspaceId: "workspace-123",
|
||||
title: "Updated Event",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("PUT", params, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-125",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).toHaveBeenCalledWith({
|
||||
workspaceId: "workspace-123",
|
||||
userId: "user-123",
|
||||
action: ActivityAction.UPDATED,
|
||||
entityType: expect.any(String),
|
||||
entityId: "event-789",
|
||||
details: expect.objectContaining({
|
||||
method: "PUT",
|
||||
}),
|
||||
ipAddress: "127.0.0.1",
|
||||
userAgent: "test-agent",
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should log DELETE request as DELETE action", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const params = {
|
||||
id: "project-999",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "project-999",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("DELETE", params, {}, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-126",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).toHaveBeenCalledWith({
|
||||
workspaceId: "workspace-123",
|
||||
userId: "user-123",
|
||||
action: ActivityAction.DELETED,
|
||||
entityType: expect.any(String),
|
||||
entityId: "project-999",
|
||||
details: expect.objectContaining({
|
||||
method: "DELETE",
|
||||
}),
|
||||
ipAddress: "127.0.0.1",
|
||||
userAgent: "test-agent",
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should not log GET requests", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("GET", {}, {}, user);
|
||||
const next = createMockCallHandler({ data: [] });
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should extract entity ID from result if not in params", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "task-new-123",
|
||||
workspaceId: "workspace-123",
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-127",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
entityId: "task-new-123",
|
||||
})
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle errors gracefully", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, {}, user);
|
||||
const next = createMockCallHandler({ id: "test-123" });
|
||||
|
||||
mockActivityService.logActivity.mockRejectedValue(
|
||||
new Error("Logging failed")
|
||||
);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not throw error, just log it
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases", () => {
|
||||
it("should handle POST request with no id field in response", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const result = {
|
||||
workspaceId: "workspace-123",
|
||||
title: "New Task",
|
||||
// No 'id' field in response
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-123",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not call logActivity when entityId is missing
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle user object missing workspaceId", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
// No workspaceId
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "task-123",
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not call logActivity when workspaceId is missing
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle body missing workspaceId when user also missing workspaceId", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
// No workspaceId
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "New Task",
|
||||
// No workspaceId
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "task-123",
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not call logActivity when workspaceId is missing
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should extract workspaceId from body when not in user object", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
// No workspaceId
|
||||
};
|
||||
|
||||
const body = {
|
||||
workspaceId: "workspace-from-body",
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "task-123",
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-123",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
expect(mockActivityService.logActivity).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
workspaceId: "workspace-from-body",
|
||||
})
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle null result from handler", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("DELETE", { id: "task-123" }, {}, user);
|
||||
const next = createMockCallHandler(null);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-123",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should still log activity with entityId from params
|
||||
expect(mockActivityService.logActivity).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
entityId: "task-123",
|
||||
workspaceId: "workspace-123",
|
||||
})
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle undefined result from handler", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, { title: "New Task" }, user);
|
||||
const next = createMockCallHandler(undefined);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not log when entityId cannot be determined
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should log warning when entityId is missing", async () => {
|
||||
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const result = {
|
||||
workspaceId: "workspace-123",
|
||||
title: "New Task",
|
||||
// No 'id' field
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should log warning when workspaceId is missing", async () => {
|
||||
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
|
||||
const user = {
|
||||
id: "user-123",
|
||||
// No workspaceId
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "task-123",
|
||||
title: "New Task",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should handle activity service throwing an error", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, {}, user);
|
||||
const next = createMockCallHandler({ id: "test-123" });
|
||||
|
||||
const activityError = new Error("Activity logging failed");
|
||||
mockActivityService.logActivity.mockRejectedValue(activityError);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not throw error, just log it
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle OPTIONS requests", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("OPTIONS", {}, {}, user);
|
||||
const next = createMockCallHandler({});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not log OPTIONS requests
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle HEAD requests", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("HEAD", {}, {}, user);
|
||||
const next = createMockCallHandler({});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
// Should not log HEAD requests
|
||||
expect(mockActivityService.logActivity).not.toHaveBeenCalled();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("sensitive data sanitization", () => {
|
||||
it("should redact password field", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
username: "testuser",
|
||||
password: "secret123",
|
||||
email: "test@example.com",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "user-456",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-123",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
const logCall = mockActivityService.logActivity.mock.calls[0][0];
|
||||
expect(logCall.details.data.password).toBe("[REDACTED]");
|
||||
expect(logCall.details.data.username).toBe("testuser");
|
||||
expect(logCall.details.data.email).toBe("test@example.com");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should redact token field", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "Integration",
|
||||
apiToken: "sk_test_1234567890",
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "integration-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-124",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
const logCall = mockActivityService.logActivity.mock.calls[0][0];
|
||||
expect(logCall.details.data.apiToken).toBe("[REDACTED]");
|
||||
expect(logCall.details.data.title).toBe("Integration");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should redact sensitive fields in nested objects", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "Config",
|
||||
settings: {
|
||||
apiKey: "secret_key",
|
||||
public: "visible_data",
|
||||
auth: {
|
||||
token: "auth_token_123",
|
||||
refreshToken: "refresh_token_456",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "config-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-128",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
const logCall = mockActivityService.logActivity.mock.calls[0][0];
|
||||
expect(logCall.details.data.title).toBe("Config");
|
||||
expect(logCall.details.data.settings.apiKey).toBe("[REDACTED]");
|
||||
expect(logCall.details.data.settings.public).toBe("visible_data");
|
||||
expect(logCall.details.data.settings.auth.token).toBe("[REDACTED]");
|
||||
expect(logCall.details.data.settings.auth.refreshToken).toBe(
|
||||
"[REDACTED]"
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should not modify non-sensitive fields", async () => {
|
||||
const user = {
|
||||
id: "user-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const body = {
|
||||
title: "Safe Data",
|
||||
description: "This is public",
|
||||
count: 42,
|
||||
active: true,
|
||||
};
|
||||
|
||||
const result = {
|
||||
id: "item-123",
|
||||
workspaceId: "workspace-123",
|
||||
};
|
||||
|
||||
const context = createMockExecutionContext("POST", {}, body, user);
|
||||
const next = createMockCallHandler(result);
|
||||
|
||||
mockActivityService.logActivity.mockResolvedValue({
|
||||
id: "activity-130",
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
interceptor.intercept(context, next).subscribe(() => {
|
||||
const logCall = mockActivityService.logActivity.mock.calls[0][0];
|
||||
expect(logCall.details.data).toEqual(body);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user