fix(studio): respect deselected columns in CSV import compatibility check (#44497)

This commit is contained in:
Ali Waseem
2026-04-02 12:59:19 -06:00
committed by GitHub
parent 73d972ba29
commit a1c8587808
4 changed files with 63 additions and 1 deletions
@@ -29,6 +29,7 @@ const SpreadsheetImportConfiguration = ({
<p className="text-sm">Configure import data</p>
<Button
type="text"
aria-label="Toggle import configuration"
icon={
<ChevronDown
size={18}
@@ -71,6 +72,8 @@ const SpreadsheetImportConfiguration = ({
<Button
key={header}
type={isSelected ? 'primary' : 'default'}
aria-label={`Toggle column ${header}`}
aria-pressed={isSelected}
className={cn('transition', isSelected ? 'opacity-100' : 'opacity-75')}
onClick={() => onToggleHeader(header)}
>
@@ -56,7 +56,11 @@ export const SpreadsheetImport = ({
const selectedTableColumns = (selectedTable?.columns ?? []).map((column) => column.name)
const csvHeaders =
state._tag === 'file_parsed' || state._tag === 'text_parsed' ? state.data.headers : []
const incompatibleHeaders = csvHeaders.filter((header) => !selectedTableColumns.includes(header))
const selectedHeaders =
state._tag === 'file_parsed' || state._tag === 'text_parsed' ? state.selectedHeaders : []
const incompatibleHeaders = selectedHeaders.filter(
(header) => !selectedTableColumns.includes(header)
)
const isCompatible = !selectedTable || incompatibleHeaders.length === 0
const { mutate: sendEvent } = useSendEventMutation()
@@ -0,0 +1,4 @@
id,pw_column,extra_column
1,value 1,extra 1
2,value 2,extra 2
3,value 3,extra 3
1 id pw_column extra_column
2 1 value 1 extra 1
3 2 value 2 extra 2
4 3 value 3 extra 3
+51
View File
@@ -1234,6 +1234,57 @@ testRunner('table editor', () => {
await expect(page.getByRole('gridcell', { name: 'drag drop value 1' })).toBeVisible()
})
test('CSV import with extra column succeeds after deselecting incompatible header', async ({
page,
ref,
}) => {
const tableName = 'pw_table_csv_extra_col'
await using _ = await withSetupCleanup(
async () => {
await createTableWithRLS(tableName, 'pw_column')
},
async () => {
await dropTable(tableName)
}
)
await page.goto(toUrl(`/project/${ref}/editor?schema=public`))
await page.getByRole('button', { name: `View ${tableName}`, exact: true }).click()
await page.waitForURL(/\/editor\/\d+\?schema=public$/)
// Upload a CSV that has an extra column not in the table
const csvFilePath = path.join(
import.meta.dirname,
'files',
'table-editor-import-extra-column.csv'
)
await page.getByRole('button', { name: 'Import data from CSV' }).click()
await page.getByRole('tab', { name: 'Upload CSV' }).click()
await page.setInputFiles('input[type="file"]', csvFilePath)
// The "Data incompatible" badge should be visible because of the extra column
await expect(page.getByText('Data incompatible')).toBeVisible()
// Expand the configuration section and deselect the extra column
await page.getByRole('button', { name: 'Toggle import configuration' }).click()
await expect(page.getByText('Select which columns to import')).toBeVisible()
await page.getByRole('button', { name: 'Toggle column extra_column' }).click()
// After deselecting, the incompatible badge should disappear
await expect(page.getByText('Data incompatible')).not.toBeVisible()
// Import should succeed now
const waitForCsvInsert = createApiResponseWaiter(page, 'pg-meta', ref, 'query?key=', {
method: 'POST',
})
await page.getByRole('button', { name: 'Import data' }).click()
await waitForCsvInsert
await waitForGridDataToLoad(page, ref)
await expect(page.getByText('3 records')).toBeVisible()
await expect(page.getByRole('gridcell', { name: 'value 1' })).toBeVisible()
})
test('row insert via side panel saves immediately', async ({ page, ref }) => {
const tableName = 'pw_table_row_insert'
const columnName = 'name'