mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-15 23:31:04 +00:00
724 lines
22 KiB
TypeScript
724 lines
22 KiB
TypeScript
import type { ExtensionContext } from "vscode"
|
|
|
|
import type { OrganizationSettings, AuthService } from "@roo-code/types"
|
|
|
|
import { CloudSettingsService } from "../CloudSettingsService.js"
|
|
import { RefreshTimer } from "../RefreshTimer.js"
|
|
|
|
vi.mock("../RefreshTimer")
|
|
|
|
vi.mock("../config", () => ({
|
|
getRooCodeApiUrl: vi.fn().mockReturnValue("https://app.roocode.com"),
|
|
}))
|
|
|
|
global.fetch = vi.fn()
|
|
|
|
describe("CloudSettingsService", () => {
|
|
let mockContext: ExtensionContext
|
|
let mockAuthService: {
|
|
getState: ReturnType<typeof vi.fn>
|
|
getSessionToken: ReturnType<typeof vi.fn>
|
|
hasActiveSession: ReturnType<typeof vi.fn>
|
|
on: ReturnType<typeof vi.fn>
|
|
getStoredOrganizationId: ReturnType<typeof vi.fn>
|
|
}
|
|
let mockRefreshTimer: {
|
|
start: ReturnType<typeof vi.fn>
|
|
stop: ReturnType<typeof vi.fn>
|
|
}
|
|
let cloudSettingsService: CloudSettingsService
|
|
let mockLog: ReturnType<typeof vi.fn>
|
|
|
|
const mockSettings: OrganizationSettings = {
|
|
version: 1,
|
|
defaultSettings: {},
|
|
allowList: {
|
|
allowAll: true,
|
|
providers: {},
|
|
},
|
|
}
|
|
|
|
const mockUserSettings = {
|
|
features: {},
|
|
settings: {},
|
|
version: 1,
|
|
}
|
|
|
|
const mockExtensionSettingsResponse = {
|
|
organization: mockSettings,
|
|
user: mockUserSettings,
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
|
|
mockContext = {
|
|
globalState: {
|
|
get: vi.fn(),
|
|
update: vi.fn().mockResolvedValue(undefined),
|
|
},
|
|
} as unknown as ExtensionContext
|
|
|
|
mockAuthService = {
|
|
getState: vi.fn().mockReturnValue("logged-out"),
|
|
getSessionToken: vi.fn(),
|
|
hasActiveSession: vi.fn().mockReturnValue(false),
|
|
on: vi.fn(),
|
|
getStoredOrganizationId: vi.fn().mockReturnValue(null),
|
|
}
|
|
|
|
mockRefreshTimer = {
|
|
start: vi.fn(),
|
|
stop: vi.fn(),
|
|
}
|
|
|
|
mockLog = vi.fn()
|
|
|
|
// Mock RefreshTimer constructor
|
|
vi.mocked(RefreshTimer).mockImplementation(() => mockRefreshTimer as unknown as RefreshTimer)
|
|
|
|
cloudSettingsService = new CloudSettingsService(mockContext, mockAuthService as unknown as AuthService, mockLog)
|
|
})
|
|
|
|
afterEach(() => {
|
|
cloudSettingsService.dispose()
|
|
})
|
|
|
|
describe("constructor", () => {
|
|
it("should create CloudSettingsService with proper dependencies", () => {
|
|
expect(cloudSettingsService).toBeInstanceOf(CloudSettingsService)
|
|
expect(RefreshTimer).toHaveBeenCalledWith({
|
|
callback: expect.any(Function),
|
|
successInterval: 3_600_000,
|
|
initialBackoffMs: 1000,
|
|
maxBackoffMs: 3_600_000,
|
|
})
|
|
})
|
|
|
|
it("should use console.log as default logger when none provided", () => {
|
|
const service = new CloudSettingsService(mockContext, mockAuthService as unknown as AuthService)
|
|
expect(service).toBeInstanceOf(CloudSettingsService)
|
|
})
|
|
})
|
|
|
|
describe("initialize", () => {
|
|
it("should load cached settings on initialization", async () => {
|
|
const cachedSettings = {
|
|
version: 1,
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
// Create a fresh mock context for this test
|
|
const testContext = {
|
|
globalState: {
|
|
get: vi.fn((key: string) => {
|
|
if (key === "organization-settings") return cachedSettings
|
|
if (key === "user-settings") return mockUserSettings
|
|
return undefined
|
|
}),
|
|
update: vi.fn().mockResolvedValue(undefined),
|
|
},
|
|
} as unknown as ExtensionContext
|
|
|
|
// Mock auth service to not be logged out
|
|
const testAuthService = {
|
|
getState: vi.fn().mockReturnValue("active"),
|
|
getSessionToken: vi.fn(),
|
|
hasActiveSession: vi.fn().mockReturnValue(false),
|
|
on: vi.fn(),
|
|
}
|
|
|
|
// Create a new instance to test initialization
|
|
const testService = new CloudSettingsService(
|
|
testContext,
|
|
testAuthService as unknown as AuthService,
|
|
mockLog,
|
|
)
|
|
await testService.initialize()
|
|
|
|
expect(testContext.globalState.get).toHaveBeenCalledWith("organization-settings")
|
|
expect(testContext.globalState.get).toHaveBeenCalledWith("user-settings")
|
|
expect(testService.getSettings()).toEqual(cachedSettings)
|
|
|
|
testService.dispose()
|
|
})
|
|
|
|
it("should clear cached settings if user is logged out", async () => {
|
|
const cachedSettings = {
|
|
version: 1,
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
mockContext.globalState.get = vi.fn((key: string) => {
|
|
if (key === "organization-settings") return cachedSettings
|
|
if (key === "user-settings") return mockUserSettings
|
|
return undefined
|
|
})
|
|
mockAuthService.getState.mockReturnValue("logged-out")
|
|
|
|
await cloudSettingsService.initialize()
|
|
|
|
// Check that both cache keys are cleared
|
|
const updateCalls = vi.mocked(mockContext.globalState.update).mock.calls
|
|
const orgSettingsCall = updateCalls.find((call) => call[0] === "organization-settings")
|
|
const userSettingsCall = updateCalls.find((call) => call[0] === "user-settings")
|
|
|
|
expect(orgSettingsCall).toBeDefined()
|
|
expect(orgSettingsCall?.[1]).toBeUndefined()
|
|
expect(userSettingsCall).toBeDefined()
|
|
expect(userSettingsCall?.[1]).toBeUndefined()
|
|
})
|
|
|
|
it("should set up auth service event listeners", async () => {
|
|
await cloudSettingsService.initialize()
|
|
|
|
expect(mockAuthService.on).toHaveBeenCalledWith("auth-state-changed", expect.any(Function))
|
|
})
|
|
|
|
it("should start timer if user has active session", async () => {
|
|
mockAuthService.hasActiveSession.mockReturnValue(true)
|
|
|
|
await cloudSettingsService.initialize()
|
|
|
|
expect(mockRefreshTimer.start).toHaveBeenCalled()
|
|
})
|
|
|
|
it("should not start timer if user has no active session", async () => {
|
|
mockAuthService.hasActiveSession.mockReturnValue(false)
|
|
|
|
await cloudSettingsService.initialize()
|
|
|
|
expect(mockRefreshTimer.start).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe("event emission", () => {
|
|
beforeEach(async () => {
|
|
await cloudSettingsService.initialize()
|
|
})
|
|
|
|
it("should emit 'settings-updated' event when settings change", async () => {
|
|
const eventSpy = vi.fn()
|
|
cloudSettingsService.on("settings-updated", eventSpy)
|
|
|
|
mockAuthService.getSessionToken.mockReturnValue("valid-token")
|
|
vi.mocked(fetch).mockResolvedValue({
|
|
ok: true,
|
|
json: vi.fn().mockResolvedValue(mockExtensionSettingsResponse),
|
|
} as unknown as Response)
|
|
|
|
// Get the callback function passed to RefreshTimer
|
|
const timerCallback = vi.mocked(RefreshTimer).mock.calls[0]?.[0]?.callback
|
|
|
|
await timerCallback?.()
|
|
|
|
expect(eventSpy).toHaveBeenCalledWith({})
|
|
})
|
|
|
|
it("should emit event when either org or user settings change", async () => {
|
|
const eventSpy = vi.fn()
|
|
|
|
const previousSettings = {
|
|
version: 1,
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
const newSettings = {
|
|
version: 2,
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
// Create a fresh mock context for this test
|
|
const testContext = {
|
|
globalState: {
|
|
get: vi.fn((key: string) => {
|
|
if (key === "organization-settings") return previousSettings
|
|
if (key === "user-settings") return mockUserSettings
|
|
return undefined
|
|
}),
|
|
update: vi.fn().mockResolvedValue(undefined),
|
|
},
|
|
} as unknown as ExtensionContext
|
|
|
|
// Mock auth service to not be logged out
|
|
const testAuthService = {
|
|
getState: vi.fn().mockReturnValue("active"),
|
|
getSessionToken: vi.fn().mockReturnValue("valid-token"),
|
|
hasActiveSession: vi.fn().mockReturnValue(false),
|
|
on: vi.fn(),
|
|
}
|
|
|
|
// Create a new service instance with cached settings
|
|
const testService = new CloudSettingsService(
|
|
testContext,
|
|
testAuthService as unknown as AuthService,
|
|
mockLog,
|
|
)
|
|
testService.on("settings-updated", eventSpy)
|
|
await testService.initialize()
|
|
|
|
vi.mocked(fetch).mockResolvedValue({
|
|
ok: true,
|
|
json: vi.fn().mockResolvedValue({
|
|
organization: newSettings,
|
|
user: mockUserSettings,
|
|
}),
|
|
} as unknown as Response)
|
|
|
|
// Get the callback function passed to RefreshTimer for this instance
|
|
const timerCallback =
|
|
vi.mocked(RefreshTimer).mock.calls[vi.mocked(RefreshTimer).mock.calls.length - 1]?.[0]?.callback
|
|
|
|
await timerCallback?.()
|
|
|
|
expect(eventSpy).toHaveBeenCalledWith({})
|
|
|
|
testService.dispose()
|
|
})
|
|
|
|
it("should not emit event when settings version is unchanged", async () => {
|
|
const eventSpy = vi.fn()
|
|
|
|
// Create a fresh mock context for this test
|
|
const testContext = {
|
|
globalState: {
|
|
get: vi.fn((key: string) => {
|
|
if (key === "organization-settings") return mockSettings
|
|
if (key === "user-settings") return mockUserSettings
|
|
return undefined
|
|
}),
|
|
update: vi.fn().mockResolvedValue(undefined),
|
|
},
|
|
} as unknown as ExtensionContext
|
|
|
|
// Mock auth service to not be logged out
|
|
const testAuthService = {
|
|
getState: vi.fn().mockReturnValue("active"),
|
|
getSessionToken: vi.fn().mockReturnValue("valid-token"),
|
|
hasActiveSession: vi.fn().mockReturnValue(false),
|
|
on: vi.fn(),
|
|
}
|
|
|
|
// Create a new service instance with cached settings
|
|
const testService = new CloudSettingsService(
|
|
testContext,
|
|
testAuthService as unknown as AuthService,
|
|
mockLog,
|
|
)
|
|
testService.on("settings-updated", eventSpy)
|
|
await testService.initialize()
|
|
|
|
vi.mocked(fetch).mockResolvedValue({
|
|
ok: true,
|
|
json: vi.fn().mockResolvedValue(mockExtensionSettingsResponse), // Same version
|
|
} as unknown as Response)
|
|
|
|
// Get the callback function passed to RefreshTimer for this instance
|
|
const timerCallback =
|
|
vi.mocked(RefreshTimer).mock.calls[vi.mocked(RefreshTimer).mock.calls.length - 1]?.[0]?.callback
|
|
|
|
await timerCallback?.()
|
|
|
|
expect(eventSpy).not.toHaveBeenCalled()
|
|
|
|
testService.dispose()
|
|
})
|
|
|
|
it("should not emit event when fetch fails", async () => {
|
|
const eventSpy = vi.fn()
|
|
cloudSettingsService.on("settings-updated", eventSpy)
|
|
|
|
mockAuthService.getSessionToken.mockReturnValue("valid-token")
|
|
vi.mocked(fetch).mockResolvedValue({
|
|
ok: false,
|
|
status: 500,
|
|
statusText: "Internal Server Error",
|
|
} as unknown as Response)
|
|
|
|
// Get the callback function passed to RefreshTimer
|
|
const timerCallback = vi.mocked(RefreshTimer).mock.calls[0]?.[0]?.callback
|
|
|
|
await timerCallback?.()
|
|
|
|
expect(eventSpy).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it("should not emit event when no auth token available", async () => {
|
|
const eventSpy = vi.fn()
|
|
cloudSettingsService.on("settings-updated", eventSpy)
|
|
|
|
mockAuthService.getSessionToken.mockReturnValue(null)
|
|
|
|
// Get the callback function passed to RefreshTimer
|
|
const timerCallback = vi.mocked(RefreshTimer).mock.calls[0]?.[0]?.callback
|
|
|
|
await timerCallback?.()
|
|
|
|
expect(eventSpy).not.toHaveBeenCalled()
|
|
expect(fetch).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe("fetchSettings", () => {
|
|
beforeEach(async () => {
|
|
await cloudSettingsService.initialize()
|
|
})
|
|
|
|
it("should fetch and cache settings successfully", async () => {
|
|
mockAuthService.getSessionToken.mockReturnValue("valid-token")
|
|
vi.mocked(fetch).mockResolvedValue({
|
|
ok: true,
|
|
json: vi.fn().mockResolvedValue(mockExtensionSettingsResponse),
|
|
} as unknown as Response)
|
|
|
|
// Get the callback function passed to RefreshTimer
|
|
const timerCallback = vi.mocked(RefreshTimer).mock.calls[0]?.[0]?.callback
|
|
|
|
const result = await timerCallback?.()
|
|
|
|
expect(result).toBe(true)
|
|
|
|
expect(fetch).toHaveBeenCalledWith("https://app.roocode.com/api/extension-settings", {
|
|
headers: {
|
|
Authorization: "Bearer valid-token",
|
|
},
|
|
})
|
|
|
|
expect(mockContext.globalState.update).toHaveBeenCalledWith("organization-settings", mockSettings)
|
|
expect(mockContext.globalState.update).toHaveBeenCalledWith("user-settings", mockUserSettings)
|
|
})
|
|
|
|
it("should handle fetch errors gracefully", async () => {
|
|
mockAuthService.getSessionToken.mockReturnValue("valid-token")
|
|
vi.mocked(fetch).mockRejectedValue(new Error("Network error"))
|
|
|
|
// Get the callback function passed to RefreshTimer
|
|
const timerCallback = vi.mocked(RefreshTimer).mock.calls[0]?.[0]?.callback
|
|
|
|
const result = await timerCallback?.()
|
|
|
|
expect(result).toBe(false)
|
|
|
|
expect(mockLog).toHaveBeenCalledWith(
|
|
"[cloud-settings] Error fetching extension settings:",
|
|
expect.any(Error),
|
|
)
|
|
})
|
|
|
|
it("should handle invalid response format", async () => {
|
|
mockAuthService.getSessionToken.mockReturnValue("valid-token")
|
|
vi.mocked(fetch).mockResolvedValue({
|
|
ok: true,
|
|
json: vi.fn().mockResolvedValue({ invalid: "data" }),
|
|
} as unknown as Response)
|
|
|
|
// Get the callback function passed to RefreshTimer
|
|
const timerCallback = vi.mocked(RefreshTimer).mock.calls[0]?.[0]?.callback
|
|
|
|
const result = await timerCallback?.()
|
|
|
|
expect(result).toBe(false)
|
|
|
|
expect(mockLog).toHaveBeenCalledWith(
|
|
"[cloud-settings] Invalid extension settings format:",
|
|
expect.any(Object),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("getAllowList", () => {
|
|
it("should return settings allowList when available", async () => {
|
|
mockContext.globalState.get = vi.fn((key: string) => {
|
|
if (key === "organization-settings") return mockSettings
|
|
return undefined
|
|
})
|
|
await cloudSettingsService.initialize()
|
|
|
|
const allowList = cloudSettingsService.getAllowList()
|
|
expect(allowList).toEqual(mockSettings.allowList)
|
|
})
|
|
|
|
it("should return default allow all when no settings available", () => {
|
|
const allowList = cloudSettingsService.getAllowList()
|
|
expect(allowList).toEqual({ allowAll: true, providers: {} })
|
|
})
|
|
})
|
|
|
|
describe("getSettings", () => {
|
|
it("should return current settings", async () => {
|
|
// Create a fresh mock context for this test
|
|
const testContext = {
|
|
globalState: {
|
|
get: vi.fn((key: string) => {
|
|
if (key === "organization-settings") return mockSettings
|
|
return undefined
|
|
}),
|
|
update: vi.fn().mockResolvedValue(undefined),
|
|
},
|
|
} as unknown as ExtensionContext
|
|
|
|
// Mock auth service to not be logged out
|
|
const testAuthService = {
|
|
getState: vi.fn().mockReturnValue("active"),
|
|
getSessionToken: vi.fn(),
|
|
hasActiveSession: vi.fn().mockReturnValue(false),
|
|
on: vi.fn(),
|
|
}
|
|
|
|
const testService = new CloudSettingsService(
|
|
testContext,
|
|
testAuthService as unknown as AuthService,
|
|
mockLog,
|
|
)
|
|
await testService.initialize()
|
|
|
|
const settings = testService.getSettings()
|
|
expect(settings).toEqual(mockSettings)
|
|
|
|
testService.dispose()
|
|
})
|
|
|
|
it("should return undefined when no settings available", () => {
|
|
const settings = cloudSettingsService.getSettings()
|
|
expect(settings).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe("dispose", () => {
|
|
it("should remove all listeners and stop timer", () => {
|
|
const removeAllListenersSpy = vi.spyOn(cloudSettingsService, "removeAllListeners")
|
|
|
|
cloudSettingsService.dispose()
|
|
|
|
expect(removeAllListenersSpy).toHaveBeenCalled()
|
|
expect(mockRefreshTimer.stop).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe("auth service event handlers", () => {
|
|
it("should start timer when auth-state-changed event is triggered with active-session", async () => {
|
|
await cloudSettingsService.initialize()
|
|
|
|
// Get the auth-state-changed handler
|
|
const authStateChangedHandler = mockAuthService.on.mock.calls.find(
|
|
(call: string[]) => call[0] === "auth-state-changed",
|
|
)?.[1]
|
|
expect(authStateChangedHandler).toBeDefined()
|
|
|
|
// Simulate active-session state change
|
|
authStateChangedHandler({
|
|
state: "active-session",
|
|
previousState: "attempting-session",
|
|
})
|
|
expect(mockRefreshTimer.start).toHaveBeenCalled()
|
|
})
|
|
|
|
it("should stop timer and remove settings when auth-state-changed event is triggered with logged-out", async () => {
|
|
await cloudSettingsService.initialize()
|
|
|
|
// Get the auth-state-changed handler
|
|
const authStateChangedHandler = mockAuthService.on.mock.calls.find(
|
|
(call: string[]) => call[0] === "auth-state-changed",
|
|
)?.[1]
|
|
expect(authStateChangedHandler).toBeDefined()
|
|
|
|
// Simulate logged-out state change from active-session
|
|
await authStateChangedHandler({
|
|
state: "logged-out",
|
|
previousState: "active-session",
|
|
})
|
|
expect(mockRefreshTimer.stop).toHaveBeenCalled()
|
|
expect(mockContext.globalState.update).toHaveBeenCalledWith("organization-settings", undefined)
|
|
expect(mockContext.globalState.update).toHaveBeenCalledWith("user-settings", undefined)
|
|
})
|
|
})
|
|
|
|
describe("isTaskSyncEnabled", () => {
|
|
beforeEach(async () => {
|
|
await cloudSettingsService.initialize()
|
|
})
|
|
|
|
it("should return true when org recordTaskMessages is true", () => {
|
|
// Set up mock settings with org recordTaskMessages = true
|
|
const mockSettings = {
|
|
version: 1,
|
|
cloudSettings: {
|
|
recordTaskMessages: true,
|
|
},
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
// Mock that user has organization ID (indicating org settings should be used)
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
|
|
|
|
// Use reflection to set private settings
|
|
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
|
|
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(true)
|
|
})
|
|
|
|
it("should return false when org recordTaskMessages is false", () => {
|
|
// Set up mock settings with org recordTaskMessages = false
|
|
const mockSettings = {
|
|
version: 1,
|
|
cloudSettings: {
|
|
recordTaskMessages: false,
|
|
},
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
// Mock that user has organization ID (indicating org settings should be used)
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
|
|
|
|
// Use reflection to set private settings
|
|
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
|
|
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
|
|
})
|
|
|
|
it("should fall back to user taskSyncEnabled when org recordTaskMessages is undefined", () => {
|
|
// Set up mock settings with org recordTaskMessages undefined
|
|
const mockSettings = {
|
|
version: 1,
|
|
cloudSettings: {},
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
const mockUserSettings = {
|
|
version: 1,
|
|
features: {},
|
|
settings: {
|
|
taskSyncEnabled: true,
|
|
},
|
|
}
|
|
|
|
// Mock that user has no organization ID (indicating user settings should be used)
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
|
|
|
|
// Use reflection to set private settings
|
|
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
|
|
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
|
|
mockUserSettings
|
|
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(true)
|
|
})
|
|
|
|
it("should return false when user taskSyncEnabled is false", () => {
|
|
// Set up mock settings with org recordTaskMessages undefined
|
|
const mockSettings = {
|
|
version: 1,
|
|
cloudSettings: {},
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
const mockUserSettings = {
|
|
version: 1,
|
|
features: {},
|
|
settings: {
|
|
taskSyncEnabled: false,
|
|
},
|
|
}
|
|
|
|
// Mock that user has no organization ID (indicating user settings should be used)
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
|
|
|
|
// Use reflection to set private settings
|
|
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
|
|
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
|
|
mockUserSettings
|
|
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
|
|
})
|
|
|
|
it("should return true when user taskSyncEnabled is undefined (default)", () => {
|
|
// Set up mock settings with org recordTaskMessages undefined
|
|
const mockSettings = {
|
|
version: 1,
|
|
cloudSettings: {},
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
const mockUserSettings = {
|
|
version: 1,
|
|
features: {},
|
|
settings: {},
|
|
}
|
|
|
|
// Mock that user has no organization ID (indicating user settings should be used)
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
|
|
|
|
// Use reflection to set private settings
|
|
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
|
|
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
|
|
mockUserSettings
|
|
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(true)
|
|
})
|
|
|
|
it("should return false when no settings are available", () => {
|
|
// Mock that user has no organization ID
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
|
|
|
|
// Clear both settings
|
|
;(cloudSettingsService as unknown as { settings: undefined }).settings = undefined
|
|
;(cloudSettingsService as unknown as { userSettings: undefined }).userSettings = undefined
|
|
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
|
|
})
|
|
|
|
it("should return false when only org settings are available but cloudSettings is undefined", () => {
|
|
const mockSettings = {
|
|
version: 1,
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
// Mock that user has organization ID (indicating org settings should be used)
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
|
|
|
|
// Use reflection to set private settings
|
|
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
|
|
;(cloudSettingsService as unknown as { userSettings: undefined }).userSettings = undefined
|
|
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
|
|
})
|
|
|
|
it("should prioritize org settings over user settings", () => {
|
|
// Set up conflicting settings: org = false, user = true
|
|
const mockSettings = {
|
|
version: 1,
|
|
cloudSettings: {
|
|
recordTaskMessages: false,
|
|
},
|
|
defaultSettings: {},
|
|
allowList: { allowAll: true, providers: {} },
|
|
}
|
|
|
|
const mockUserSettings = {
|
|
version: 1,
|
|
features: {},
|
|
settings: {
|
|
taskSyncEnabled: true,
|
|
},
|
|
}
|
|
|
|
// Mock that user has organization ID (indicating org settings should be used)
|
|
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
|
|
|
|
// Use reflection to set private settings
|
|
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
|
|
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
|
|
mockUserSettings
|
|
|
|
// Should return false (org setting takes precedence)
|
|
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
|
|
})
|
|
})
|
|
})
|