mirror of
https://github.com/supabase/supabase.git
synced 2026-05-06 22:18:00 +08:00
## Problem Foreign wrapper forms still use `formik` but we now use `react-hook-form` everywhere and we'd like to reduce our dependencies. ## Solution - [x] Write e2e tests for wrappers - [x] Migrate to `react-hook-form` ## Notes I tried to cover the 3 cases I identified for foreign wrappers with e2e tests: - Add all available tables to a new schema (stripe) - Add selected tables to a new table (stripe) - Create dynamic columns (s3 wrapper) However, they are not exhaustive as I can't test the integration actually works, only that it was created successfully. Besides, I can't test the Iceberg wrapper case as it needs actual S3 buckets. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced column-type selector with searchable combobox, enum support, icons, and optional recommendation prompts. * **Refactor** * Migrated many wrapper/table/editor forms to a schema-driven form system with stronger validation, dynamic field arrays, and consistent form controls. * Updated input field integration to work with the new form control model. * **Bug Fixes** * Improved handling of missing wrapper/error states during wrapper loading. * **Tests** * Added unit tests for form schemas and end-to-end tests for wrapper creation flows. * **Chores** * Removed legacy dynamic-columns component. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
143 lines
6.0 KiB
TypeScript
143 lines
6.0 KiB
TypeScript
import { expect } from '@playwright/test'
|
|
|
|
import { env } from '../env.config.js'
|
|
import { query } from '../utils/db/client.js'
|
|
import { test, withSetupCleanup } from '../utils/test.js'
|
|
import { toUrl } from '../utils/to-url.js'
|
|
|
|
const testRunner = env.IS_PLATFORM ? test.describe.serial : test.describe
|
|
testRunner('Stripe', () => {
|
|
test('can create a stripe wrapper with schema', async ({ page, ref }) => {
|
|
const wrapperName = 'stripe_schema'
|
|
const schemaName = 'stripe'
|
|
|
|
await using _ = await withSetupCleanup(
|
|
async () => {
|
|
await query(`
|
|
create schema if not exists extensions;
|
|
|
|
create extension if not exists wrappers
|
|
schema extensions
|
|
version '0.5.7'
|
|
cascade;
|
|
`)
|
|
},
|
|
async () => {
|
|
// Make the request in the page context so that the it can delete wrappers that belongs to supabase_admin
|
|
await page.request.post(toUrl(`/api/platform/pg-meta/${ref}/query`), {
|
|
failOnStatusCode: true,
|
|
data: {
|
|
query: `
|
|
drop foreign data wrapper if exists ${wrapperName} cascade;
|
|
delete from vault.secrets where name = '${wrapperName}_api_key_id';
|
|
drop schema ${schemaName} cascade;`,
|
|
},
|
|
})
|
|
}
|
|
)
|
|
await page.goto(toUrl(`/project/${ref}/integrations/stripe_wrapper/overview`))
|
|
await page.getByRole('button', { name: 'Add new wrapper' }).click()
|
|
|
|
await page.getByRole('textbox', { name: 'Wrapper Name' }).fill(wrapperName)
|
|
await page.getByRole('textbox', { name: 'Stripe Secret Key' }).fill('my secret')
|
|
await page.getByRole('radio', { name: 'Schema' }).click()
|
|
await page
|
|
.getByRole('textbox', { name: 'Specify a new schema to create all wrapper tables in' })
|
|
.fill(schemaName)
|
|
await page.getByRole('button', { name: 'Create wrapper' }).click()
|
|
await expect(page.getByText('Successfully created Stripe foreign data wrapper')).toBeVisible()
|
|
})
|
|
|
|
test('can create a stripe wrapper with tables', async ({ page, ref }) => {
|
|
const wrapperName = 'stripe_tables'
|
|
const tableName = 'stripe_accounts'
|
|
|
|
await using _ = await withSetupCleanup(
|
|
async () => {
|
|
await query(`
|
|
create schema if not exists extensions;
|
|
|
|
create extension if not exists wrappers
|
|
schema extensions
|
|
version '0.5.7'
|
|
cascade;
|
|
`)
|
|
},
|
|
async () => {
|
|
// Make the request in the page context so that the it can delete wrappers that belongs to supabase_admin
|
|
await page.request.post(toUrl(`/api/platform/pg-meta/${ref}/query`), {
|
|
failOnStatusCode: true,
|
|
data: {
|
|
query: `
|
|
drop foreign data wrapper if exists ${wrapperName} cascade;
|
|
delete from vault.secrets where name = '${wrapperName}_api_key_id';
|
|
drop table if exists public.${tableName};`,
|
|
},
|
|
})
|
|
}
|
|
)
|
|
await page.goto(toUrl(`/project/${ref}/integrations/stripe_wrapper/overview`))
|
|
await page.getByRole('button', { name: 'Add new wrapper' }).click()
|
|
|
|
await page.getByRole('textbox', { name: 'Wrapper Name' }).fill(wrapperName)
|
|
await page.getByRole('textbox', { name: 'Stripe Secret Key' }).fill('my secret')
|
|
await page.getByRole('button', { name: 'Add foreign table' }).click()
|
|
await page.getByRole('combobox').click()
|
|
await page.getByRole('option', { name: 'Accounts List of accounts on' }).click()
|
|
await page.getByRole('textbox', { name: 'Table name' }).fill(tableName)
|
|
await page.getByRole('button', { name: 'Save' }).click()
|
|
await page.getByRole('button', { name: 'Create wrapper' }).click()
|
|
await expect(page.getByText('Successfully created Stripe foreign data wrapper')).toBeVisible()
|
|
})
|
|
})
|
|
|
|
testRunner('S3 Wrapper', () => {
|
|
test('can create an S3 wrapper', async ({ page, ref }) => {
|
|
const wrapperName = 'test_s3_wrapper'
|
|
const tableName = 'test_s3_wrapper_table'
|
|
await using _ = await withSetupCleanup(
|
|
async () => {
|
|
await query(`
|
|
create schema if not exists extensions;
|
|
|
|
create extension if not exists wrappers
|
|
schema extensions
|
|
version '0.5.7'
|
|
cascade;
|
|
`)
|
|
},
|
|
async () => {
|
|
// Make the request in the page context so that the it can delete wrappers that belongs to supabase_admin
|
|
await page.request.post(toUrl(`/api/platform/pg-meta/${ref}/query`), {
|
|
failOnStatusCode: true,
|
|
data: {
|
|
query: `
|
|
drop foreign data wrapper if exists ${wrapperName} cascade;
|
|
delete from vault.secrets where name = '${wrapperName}_vault_access_key_id';
|
|
delete from vault.secrets where name = '${wrapperName}_vault_secret_access_key';
|
|
drop table if exists public.${tableName};`,
|
|
},
|
|
})
|
|
}
|
|
)
|
|
await page.goto(toUrl(`/project/${ref}/integrations/s3_wrapper/overview`))
|
|
await page.getByRole('button', { name: 'Add new wrapper' }).click()
|
|
|
|
await page.getByRole('textbox', { name: 'Wrapper Name' }).fill(wrapperName)
|
|
await page.getByRole('textbox', { name: 'Access Key ID' }).fill('s3 access id')
|
|
await page.getByRole('textbox', { name: 'Access Key Secret' }).fill('s3 access secret')
|
|
await page.getByRole('button', { name: 'Add foreign table' }).click()
|
|
await page.getByRole('combobox').click()
|
|
await page.getByRole('option', { name: 'S3 File' }).click()
|
|
await page.getByRole('textbox', { name: 'Table name' }).fill(tableName)
|
|
await page.getByRole('textbox', { name: 'URI' }).fill('s3://bucket/s3_table.csv')
|
|
await page.getByRole('button', { name: 'Add column' }).click()
|
|
// FIXME: Necessary because this component is somehow remounted
|
|
await page.waitForTimeout(500)
|
|
await page.getByRole('textbox', { name: 'Name', exact: true }).fill('s3_column')
|
|
await page.getByRole('button', { name: 'Save' }).click()
|
|
await page.getByRole('button', { name: 'Create wrapper' }).click()
|
|
await expect(page.getByText('Successfully created S3 foreign data wrapper')).toBeVisible()
|
|
})
|
|
})
|