Add organizationFeaturesSchema with roomoteControlEnabled (#8085)

feat: add organizationFeaturesSchema with roomoteControlEnabled

- Add organizationFeaturesSchema with optional roomoteControlEnabled boolean
- Integrate features property into organizationSettingsSchema as optional
- Add comprehensive tests for new schema validation
- Maintain backward compatibility with existing organization settings

Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
roomote[bot] 2025-09-17 14:31:12 -07:00 • committed by GitHub
parent c837025d48
commit 961338e0ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 184 additions and 0 deletions

View file

@ -0,0 +1,173 @@
// npx vitest run src/__tests__/cloud.test.ts
import {
organizationFeaturesSchema,
organizationSettingsSchema,
type OrganizationFeatures,
type OrganizationSettings,
} from "../cloud.js"
describe("organizationFeaturesSchema", () => {
it("should validate empty object", () => {
const result = organizationFeaturesSchema.safeParse({})
expect(result.success).toBe(true)
expect(result.data).toEqual({})
})
it("should validate with roomoteControlEnabled as true", () => {
const input = { roomoteControlEnabled: true }
const result = organizationFeaturesSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data).toEqual(input)
})
it("should validate with roomoteControlEnabled as false", () => {
const input = { roomoteControlEnabled: false }
const result = organizationFeaturesSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data).toEqual(input)
})
it("should reject non-boolean roomoteControlEnabled", () => {
const input = { roomoteControlEnabled: "true" }
const result = organizationFeaturesSchema.safeParse(input)
expect(result.success).toBe(false)
})
it("should allow additional properties (for future extensibility)", () => {
const input = { roomoteControlEnabled: true, futureProperty: "test" }
const result = organizationFeaturesSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data?.roomoteControlEnabled).toBe(true)
// Note: Additional properties are stripped by Zod, which is expected behavior
})
it("should have correct TypeScript type", () => {
// Type-only test to ensure TypeScript compilation
const features: OrganizationFeatures = {
roomoteControlEnabled: true,
}
expect(features.roomoteControlEnabled).toBe(true)
const emptyFeatures: OrganizationFeatures = {}
expect(emptyFeatures.roomoteControlEnabled).toBeUndefined()
})
})
describe("organizationSettingsSchema with features", () => {
const validBaseSettings = {
version: 1,
defaultSettings: {},
allowList: {
allowAll: true,
providers: {},
},
}
it("should validate without features property", () => {
const result = organizationSettingsSchema.safeParse(validBaseSettings)
expect(result.success).toBe(true)
expect(result.data?.features).toBeUndefined()
})
it("should validate with empty features object", () => {
const input = {
...validBaseSettings,
features: {},
}
const result = organizationSettingsSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data?.features).toEqual({})
})
it("should validate with features.roomoteControlEnabled as true", () => {
const input = {
...validBaseSettings,
features: {
roomoteControlEnabled: true,
},
}
const result = organizationSettingsSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data?.features?.roomoteControlEnabled).toBe(true)
})
it("should validate with features.roomoteControlEnabled as false", () => {
const input = {
...validBaseSettings,
features: {
roomoteControlEnabled: false,
},
}
const result = organizationSettingsSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data?.features?.roomoteControlEnabled).toBe(false)
})
it("should reject invalid features object", () => {
const input = {
...validBaseSettings,
features: {
roomoteControlEnabled: "invalid",
},
}
const result = organizationSettingsSchema.safeParse(input)
expect(result.success).toBe(false)
})
it("should have correct TypeScript type for features", () => {
// Type-only test to ensure TypeScript compilation
const settings: OrganizationSettings = {
version: 1,
defaultSettings: {},
allowList: {
allowAll: true,
providers: {},
},
features: {
roomoteControlEnabled: true,
},
}
expect(settings.features?.roomoteControlEnabled).toBe(true)
const settingsWithoutFeatures: OrganizationSettings = {
version: 1,
defaultSettings: {},
allowList: {
allowAll: true,
providers: {},
},
}
expect(settingsWithoutFeatures.features).toBeUndefined()
})
it("should maintain all existing properties", () => {
const input = {
version: 1,
cloudSettings: {
recordTaskMessages: true,
enableTaskSharing: false,
},
defaultSettings: {},
allowList: {
allowAll: false,
providers: {
openai: {
allowAll: true,
models: ["gpt-4"],
},
},
},
features: {
roomoteControlEnabled: true,
},
hiddenMcps: ["test-mcp"],
hideMarketplaceMcps: true,
mcps: [],
providerProfiles: {},
}
const result = organizationSettingsSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data).toEqual(input)
})
})

View file

@ -133,6 +133,16 @@ export const organizationCloudSettingsSchema = z.object({
export type OrganizationCloudSettings = z.infer<typeof organizationCloudSettingsSchema>
/**
* OrganizationFeatures
*/
export const organizationFeaturesSchema = z.object({
roomoteControlEnabled: z.boolean().optional(),
})
export type OrganizationFeatures = z.infer<typeof organizationFeaturesSchema>
/**
* OrganizationSettings
*/
@ -142,6 +152,7 @@ export const organizationSettingsSchema = z.object({
cloudSettings: organizationCloudSettingsSchema.optional(),
defaultSettings: organizationDefaultSettingsSchema,
allowList: organizationAllowListSchema,
features: organizationFeaturesSchema.optional(),
hiddenMcps: z.array(z.string()).optional(),
hideMarketplaceMcps: z.boolean().optional(),
mcps: z.array(mcpMarketplaceItemSchema).optional(),