InstallIntegrationSheet.test.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import { safeSql } from '@supabase/pg-meta'
  2. import { fireEvent, screen, waitFor } from '@testing-library/dom'
  3. import userEvent from '@testing-library/user-event'
  4. import { mockAnimationsApi } from 'jsdom-testing-mocks'
  5. import { beforeEach, describe, expect, it, vi } from 'vitest'
  6. import { IntegrationDefinition } from '../../Landing/Integrations.constants'
  7. import { InstallIntegrationSheet } from './InstallIntegrationSheet/InstallIntegrationSheet'
  8. import { customRender } from '@/tests/lib/custom-render'
  9. import { routerMock } from '@/tests/lib/route-mock'
  10. mockAnimationsApi()
  11. vi.mock('@/hooks/misc/useSelectedProject', () => ({
  12. useSelectedProjectQuery: () => ({
  13. data: { ref: 'default', connectionString: 'postgres://localhost' },
  14. }),
  15. }))
  16. vi.mock('@/hooks/useProtectedSchemas', () => ({
  17. useProtectedSchemas: () => ({ data: [] }),
  18. }))
  19. const mockExtensions = vi.fn()
  20. vi.mock('@/data/database-extensions/database-extensions-query', () => ({
  21. useDatabaseExtensionsQuery: () => ({ data: mockExtensions(), isSuccess: true }),
  22. }))
  23. vi.mock('@/data/database/schemas-query', () => ({
  24. useSchemasQuery: () => ({ data: [{ id: 1, name: 'public' }] }),
  25. }))
  26. const mockExecuteSql = vi.fn()
  27. vi.mock('@/data/sql/execute-sql-mutation', () => ({
  28. useExecuteSqlMutation: () => ({ mutateAsync: mockExecuteSql }),
  29. }))
  30. vi.mock('@/data/database-extensions/database-extension-enable-mutation', () => ({
  31. useDatabaseExtensionEnableMutation: () => ({ mutateAsync: vi.fn() }),
  32. }))
  33. vi.mock('@/components/interfaces/Database/Extensions/Extensions.constants', () => ({
  34. extensionsWithRecommendedSchemas: {},
  35. }))
  36. vi.mock('./IntegrationOverviewTabV2.utils', () => ({
  37. getEnableExtensionsSQL: () => safeSql`CREATE EXTENSION IF NOT EXISTS pg_net;`,
  38. getExtensionDefaultSchema: () => 'extensions',
  39. }))
  40. const createIntegration = (overrides: Partial<IntegrationDefinition> = {}): IntegrationDefinition =>
  41. ({
  42. id: 'test-integration',
  43. type: 'postgres_extension',
  44. name: 'Test Integration',
  45. requiredExtensions: ['pg_net'],
  46. icon: () => null,
  47. description: 'Test description',
  48. docsUrl: null,
  49. author: { name: 'Test', websiteUrl: 'https://test.com' },
  50. navigate: () => null,
  51. ...overrides,
  52. }) as unknown as any
  53. const getInstallButton = () => {
  54. const buttons = screen.getAllByRole('button', { name: 'Install integration' })
  55. return buttons[buttons.length - 1]
  56. }
  57. describe('InstallIntegrationSheet', () => {
  58. beforeEach(() => {
  59. routerMock.setCurrentUrl('/project/default/integrations/test-integration/overview')
  60. mockExecuteSql.mockReset()
  61. })
  62. it('install button is disabled when extensions are missing even if installationCommand exists', async () => {
  63. mockExtensions.mockReturnValue([])
  64. customRender(
  65. <InstallIntegrationSheet
  66. integration={createIntegration({
  67. installationCommand: vi.fn().mockResolvedValue(undefined),
  68. })}
  69. />
  70. )
  71. await userEvent.click(screen.getByRole('button', { name: 'Install integration' }))
  72. expect(getInstallButton()).toBeDisabled()
  73. })
  74. it('install button is disabled when extensions are missing and no installationCommand', async () => {
  75. mockExtensions.mockReturnValue([])
  76. customRender(
  77. <InstallIntegrationSheet
  78. integration={createIntegration({ installationCommand: undefined })}
  79. />
  80. )
  81. await userEvent.click(screen.getByRole('button', { name: 'Install integration' }))
  82. expect(getInstallButton()).toBeDisabled()
  83. })
  84. it('uses installationCommand instead of SQL when provided', async () => {
  85. mockExtensions.mockReturnValue([
  86. { name: 'pg_net', installed_version: null, default_version: '0.6.0' },
  87. ])
  88. const mockCommand = vi.fn().mockResolvedValue(undefined)
  89. customRender(
  90. <InstallIntegrationSheet
  91. integration={createIntegration({ installationCommand: mockCommand })}
  92. />
  93. )
  94. await userEvent.click(screen.getByRole('button', { name: 'Install integration' }))
  95. // SheetContent renders via a Radix portal, placing the submit button outside
  96. // the <form> in the DOM. jsdom doesn't support the HTML `form` attribute on
  97. // buttons, so we submit the form directly instead of clicking the button.
  98. const form = document.getElementById('installation-settings')!
  99. fireEvent.submit(form)
  100. await waitFor(() => {
  101. expect(mockCommand).toHaveBeenCalledWith(expect.objectContaining({ ref: 'default' }))
  102. })
  103. expect(mockExecuteSql).not.toHaveBeenCalled()
  104. })
  105. })