ai-details.test.ts 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import { beforeEach, describe, expect, it, vi } from 'vitest'
  2. import { getOrgAIDetails, getProjectAIDetails } from './ai-details'
  3. vi.mock('@/data/organizations/organizations-query', () => ({
  4. getOrganizations: vi.fn(),
  5. }))
  6. vi.mock('@/data/projects/project-detail-query', () => ({
  7. getProjectDetail: vi.fn(),
  8. }))
  9. vi.mock('@/data/subscriptions/org-subscription-query', () => ({
  10. getOrgSubscription: vi.fn(),
  11. }))
  12. vi.mock('@/data/config/project-settings-v2-query', () => ({
  13. getProjectSettings: vi.fn(),
  14. }))
  15. vi.mock('@/hooks/misc/useOrgOptedIntoAi', () => ({
  16. getAiOptInLevel: vi.fn(),
  17. }))
  18. vi.mock('@/components/interfaces/Billing/Subscription/Subscription.utils', () => ({
  19. subscriptionHasHipaaAddon: vi.fn(),
  20. }))
  21. vi.mock('@/data/entitlements/entitlements-query', () => ({
  22. checkEntitlement: vi.fn(),
  23. }))
  24. const AUTH = 'Bearer token'
  25. const HEADERS = { 'Content-Type': 'application/json', Authorization: AUTH }
  26. describe('getOrgAIDetails', () => {
  27. let mockGetOrganizations: ReturnType<typeof vi.fn>
  28. let mockGetOrgSubscription: ReturnType<typeof vi.fn>
  29. let mockGetAiOptInLevel: ReturnType<typeof vi.fn>
  30. let mockSubscriptionHasHipaaAddon: ReturnType<typeof vi.fn>
  31. let mockCheckEntitlement: ReturnType<typeof vi.fn>
  32. beforeEach(async () => {
  33. vi.clearAllMocks()
  34. const orgsQuery = await import('@/data/organizations/organizations-query')
  35. const subscriptionQuery = await import('@/data/subscriptions/org-subscription-query')
  36. const aiHook = await import('@/hooks/misc/useOrgOptedIntoAi')
  37. const subscriptionUtils =
  38. await import('@/components/interfaces/Billing/Subscription/Subscription.utils')
  39. const entitlementsQuery = await import('@/data/entitlements/entitlements-query')
  40. mockGetOrganizations = vi.mocked(orgsQuery.getOrganizations)
  41. mockGetOrgSubscription = vi.mocked(subscriptionQuery.getOrgSubscription)
  42. mockGetAiOptInLevel = vi.mocked(aiHook.getAiOptInLevel)
  43. mockSubscriptionHasHipaaAddon = vi.mocked(subscriptionUtils.subscriptionHasHipaaAddon)
  44. mockCheckEntitlement = vi.mocked(entitlementsQuery.checkEntitlement)
  45. mockGetOrgSubscription.mockResolvedValue({ addons: [] })
  46. mockSubscriptionHasHipaaAddon.mockReturnValue(false)
  47. mockCheckEntitlement.mockResolvedValue({ hasAccess: false })
  48. })
  49. it('returns org-level fields', async () => {
  50. mockGetOrganizations.mockResolvedValue([
  51. { id: 1, slug: 'test-org', plan: { id: 'pro' }, opt_in_tags: [] },
  52. ])
  53. mockGetAiOptInLevel.mockReturnValue('schema')
  54. const result = await getOrgAIDetails({ orgSlug: 'test-org', authorization: AUTH })
  55. expect(result).toEqual({
  56. aiOptInLevel: 'schema',
  57. hasAccessToAdvanceModel: false,
  58. hasHipaaAddon: false,
  59. orgId: 1,
  60. planId: 'pro',
  61. })
  62. })
  63. it('returns hasAccessToAdvanceModel true when entitlement grants access', async () => {
  64. mockGetOrganizations.mockResolvedValue([
  65. { id: 1, slug: 'test-org', plan: { id: 'pro' }, opt_in_tags: [] },
  66. ])
  67. mockGetAiOptInLevel.mockReturnValue('schema')
  68. mockCheckEntitlement.mockResolvedValue({ hasAccess: true })
  69. const result = await getOrgAIDetails({ orgSlug: 'test-org', authorization: AUTH })
  70. expect(result.hasAccessToAdvanceModel).toBe(true)
  71. })
  72. it('returns hasHipaaAddon from subscription', async () => {
  73. mockGetOrganizations.mockResolvedValue([
  74. { id: 1, slug: 'test-org', plan: { id: 'enterprise' }, opt_in_tags: [] },
  75. ])
  76. mockGetAiOptInLevel.mockReturnValue('schema')
  77. mockSubscriptionHasHipaaAddon.mockReturnValue(true)
  78. const result = await getOrgAIDetails({ orgSlug: 'test-org', authorization: AUTH })
  79. expect(result.hasHipaaAddon).toBe(true)
  80. })
  81. it('calls getAiOptInLevel with the matched org opt_in_tags', async () => {
  82. const opt_in_tags = ['AI_SQL_GENERATOR_OPT_IN']
  83. mockGetOrganizations.mockResolvedValue([
  84. { id: 1, slug: 'test-org', plan: { id: 'pro' }, opt_in_tags },
  85. ])
  86. mockGetAiOptInLevel.mockReturnValue('schema')
  87. await getOrgAIDetails({ orgSlug: 'test-org', authorization: AUTH })
  88. expect(mockGetAiOptInLevel).toHaveBeenCalledWith(opt_in_tags)
  89. })
  90. it('forwards authorization headers to all fetches', async () => {
  91. mockGetOrganizations.mockResolvedValue([
  92. { id: 1, slug: 'test-org', plan: { id: 'pro' }, opt_in_tags: [] },
  93. ])
  94. mockGetAiOptInLevel.mockReturnValue('schema')
  95. await getOrgAIDetails({ orgSlug: 'test-org', authorization: AUTH })
  96. expect(mockGetOrganizations).toHaveBeenCalledWith({ headers: HEADERS })
  97. expect(mockGetOrgSubscription).toHaveBeenCalledWith({ orgSlug: 'test-org' }, undefined, HEADERS)
  98. })
  99. it('finds the correct org when multiple orgs are returned', async () => {
  100. mockGetOrganizations.mockResolvedValue([
  101. { id: 1, slug: 'org-1', plan: { id: 'free' }, opt_in_tags: [] },
  102. { id: 2, slug: 'test-org', plan: { id: 'pro' }, opt_in_tags: [] },
  103. ])
  104. mockGetAiOptInLevel.mockReturnValue('schema')
  105. const result = await getOrgAIDetails({ orgSlug: 'test-org', authorization: AUTH })
  106. expect(result.orgId).toBe(2)
  107. expect(result.planId).toBe('pro')
  108. })
  109. })
  110. describe('getProjectAIDetails', () => {
  111. let mockGetProjectDetail: ReturnType<typeof vi.fn>
  112. let mockGetProjectSettings: ReturnType<typeof vi.fn>
  113. beforeEach(async () => {
  114. vi.clearAllMocks()
  115. const projectQuery = await import('@/data/projects/project-detail-query')
  116. const settingsQuery = await import('@/data/config/project-settings-v2-query')
  117. mockGetProjectDetail = vi.mocked(projectQuery.getProjectDetail)
  118. mockGetProjectSettings = vi.mocked(settingsQuery.getProjectSettings)
  119. })
  120. it('returns region and isSensitive', async () => {
  121. mockGetProjectDetail.mockResolvedValue({ ref: 'test-project', region: 'us-east-1' })
  122. mockGetProjectSettings.mockResolvedValue({ is_sensitive: false })
  123. const result = await getProjectAIDetails({ projectRef: 'test-project', authorization: AUTH })
  124. expect(result).toEqual({ region: 'us-east-1', isSensitive: false })
  125. })
  126. it('returns isSensitive true when project is marked sensitive', async () => {
  127. mockGetProjectDetail.mockResolvedValue({ ref: 'test-project', region: 'us-east-1' })
  128. mockGetProjectSettings.mockResolvedValue({ is_sensitive: true })
  129. const result = await getProjectAIDetails({ projectRef: 'test-project', authorization: AUTH })
  130. expect(result.isSensitive).toBe(true)
  131. })
  132. it('returns isSensitive undefined when project settings are unavailable', async () => {
  133. mockGetProjectDetail.mockResolvedValue({ ref: 'test-project', region: 'us-east-1' })
  134. mockGetProjectSettings.mockResolvedValue(undefined)
  135. const result = await getProjectAIDetails({ projectRef: 'test-project', authorization: AUTH })
  136. expect(result.isSensitive).toBeUndefined()
  137. })
  138. it('returns region undefined when project detail is unavailable', async () => {
  139. mockGetProjectDetail.mockResolvedValue(undefined)
  140. mockGetProjectSettings.mockResolvedValue({ is_sensitive: false })
  141. const result = await getProjectAIDetails({ projectRef: 'test-project', authorization: AUTH })
  142. expect(result.region).toBeUndefined()
  143. })
  144. it('forwards authorization headers to all fetches', async () => {
  145. mockGetProjectDetail.mockResolvedValue({ ref: 'test-project', region: 'us-east-1' })
  146. mockGetProjectSettings.mockResolvedValue({ is_sensitive: false })
  147. await getProjectAIDetails({ projectRef: 'test-project', authorization: AUTH })
  148. expect(mockGetProjectDetail).toHaveBeenCalledWith({ ref: 'test-project' }, undefined, HEADERS)
  149. expect(mockGetProjectSettings).toHaveBeenCalledWith(
  150. { projectRef: 'test-project' },
  151. undefined,
  152. HEADERS
  153. )
  154. })
  155. })