chore: add final e2e tests for table-editor and sql-editor (#36917)
* chore: add final e2e tests for table-editor and sql-editor * chore: update tests to run in staging * chore: minor updates * chore: fix PR feedback --------- Co-authored-by: Jordi Enric <37541088+jordienr@users.noreply.github.com>
This commit is contained in:
@@ -10,6 +10,8 @@ Edit the `.env.local` file with your credentials and environment.
|
||||
|
||||
### Install the playwright browser
|
||||
|
||||
⚠️ This should be done in the `e2e/studio` directory
|
||||
|
||||
```bash
|
||||
pnpm exec playwright install
|
||||
```
|
||||
|
||||
@@ -1,55 +1,159 @@
|
||||
import { expect } from '@playwright/test'
|
||||
import { env } from '../env.config'
|
||||
import { expect, Page } from '@playwright/test'
|
||||
import { isCLI } from '../utils/is-cli'
|
||||
import { test } from '../utils/test'
|
||||
import { toUrl } from '../utils/to-url'
|
||||
|
||||
test.describe('SQL Editor', () => {
|
||||
test('should check if SQL editor can run simple commands', async ({ page }) => {
|
||||
await page.goto(toUrl(`/project/${env.PROJECT_REF}/sql/new?skip=true`))
|
||||
const deleteQuery = async (page: Page, queryName: string) => {
|
||||
const privateSnippet = page.getByLabel('private-snippets')
|
||||
await privateSnippet.getByText(queryName).first().click({ button: 'right' })
|
||||
await page.getByRole('menuitem', { name: 'Delete query' }).click()
|
||||
await expect(page.getByRole('heading', { name: 'Confirm to delete query' })).toBeVisible()
|
||||
await page.getByRole('button', { name: 'Delete 1 query' }).click()
|
||||
}
|
||||
|
||||
const editor = page.getByRole('code').nth(0)
|
||||
test.describe('SQL Editor', () => {
|
||||
let page: Page
|
||||
const pwTestQueryName = 'pw-test-query'
|
||||
|
||||
test.beforeAll(async ({ browser, ref }) => {
|
||||
test.setTimeout(60000)
|
||||
|
||||
// Create a new table for the tests
|
||||
page = await browser.newPage()
|
||||
await page.goto(toUrl(`/project/${ref}/sql/new?skip=true`))
|
||||
|
||||
await page.evaluate((ref) => {
|
||||
localStorage.removeItem('dashboard-history-default')
|
||||
localStorage.removeItem(`dashboard-history-${ref}`)
|
||||
}, ref)
|
||||
|
||||
// intercept AI title generation to prevent flaky tests
|
||||
await page.route('**/dashboard/api/ai/sql/title-v2', async (route) => {
|
||||
await route.abort()
|
||||
})
|
||||
})
|
||||
|
||||
test.beforeEach(async ({ ref }) => {
|
||||
if ((await page.getByLabel('private-snippets').count()) === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// since in local, we don't have access to the supabase platform, reloading would reload all the sql snippets.
|
||||
if (isCLI()) {
|
||||
await page.reload()
|
||||
}
|
||||
|
||||
// remove sql snippets for - "Untitled query" and "pw test query"
|
||||
const privateSnippet = page.getByLabel('private-snippets')
|
||||
let privateSnippetText = await privateSnippet.textContent()
|
||||
while (privateSnippetText.includes('Untitled query')) {
|
||||
deleteQuery(page, 'Untitled query')
|
||||
|
||||
await page.waitForResponse(
|
||||
(response) =>
|
||||
(response.url().includes(`projects/${ref}/content`) ||
|
||||
response.url().includes('projects/default/content')) &&
|
||||
response.request().method() === 'DELETE'
|
||||
)
|
||||
await expect(
|
||||
page.getByText('Successfully deleted 1 query'),
|
||||
'Delete confirmation toast should be visible'
|
||||
).toBeVisible({
|
||||
timeout: 50000,
|
||||
})
|
||||
await page.waitForTimeout(1000)
|
||||
privateSnippetText =
|
||||
(await page.getByLabel('private-snippets').count()) > 0
|
||||
? await privateSnippet.textContent()
|
||||
: ''
|
||||
}
|
||||
|
||||
while (privateSnippetText.includes(pwTestQueryName)) {
|
||||
deleteQuery(page, pwTestQueryName)
|
||||
await page.waitForResponse(
|
||||
(response) =>
|
||||
(response.url().includes(`projects/${ref}/content`) ||
|
||||
response.url().includes('projects/default/content')) &&
|
||||
response.request().method() === 'DELETE'
|
||||
)
|
||||
await expect(
|
||||
page.getByText('Successfully deleted 1 query'),
|
||||
'Delete confirmation toast should be visible'
|
||||
).toBeVisible({
|
||||
timeout: 50000,
|
||||
})
|
||||
await page.waitForTimeout(1000)
|
||||
privateSnippetText =
|
||||
(await page.getByLabel('private-snippets').count()) > 0
|
||||
? await privateSnippet.textContent()
|
||||
: ''
|
||||
}
|
||||
})
|
||||
|
||||
test('should check if SQL editor can run simple commands', async () => {
|
||||
await page.getByTestId('sql-editor-new-query-button').click()
|
||||
await page.getByRole('menuitem', { name: 'Create a new snippet' }).click()
|
||||
|
||||
// write some sql in the editor
|
||||
// This has to be done since the editor is not editable (input, textarea, etc.)
|
||||
await editor.click()
|
||||
await page.waitForTimeout(1000)
|
||||
const editor = page.getByRole('code').nth(0)
|
||||
await editor.click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.type(`select 'hello world';`)
|
||||
await page.getByTestId('sql-run-button').click()
|
||||
|
||||
await page.getByRole('button', { name: /^Run( CTRL)?$/, exact: false }).click()
|
||||
// verify the result
|
||||
await expect(page.getByRole('gridcell', { name: 'hello world' })).toBeVisible({
|
||||
timeout: 5000,
|
||||
})
|
||||
|
||||
// Should say "Running..."
|
||||
await expect(page.getByText('Running...')).toBeVisible()
|
||||
// SQL written in the editor should not be the previous query.
|
||||
await page.waitForTimeout(1000)
|
||||
await editor.click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.type(`select length('hello');`)
|
||||
await page.getByTestId('sql-run-button').click()
|
||||
|
||||
// Wait until Running... is not visible
|
||||
await expect(page.getByText('Running...')).not.toBeVisible()
|
||||
// verify the result is updated.
|
||||
await expect(page.getByRole('gridcell', { name: '5' })).toBeVisible({
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
// clear the editor
|
||||
test('destructive query would tripper a warning modal', async () => {
|
||||
await page.getByTestId('sql-editor-new-query-button').click()
|
||||
await page.getByRole('menuitem', { name: 'Create a new snippet' }).click()
|
||||
|
||||
// write some sql in the editor
|
||||
// This has to be done since the editor is not editable (input, textarea, etc.)
|
||||
await page.waitForTimeout(1000)
|
||||
const editor = page.getByRole('code').nth(0)
|
||||
await editor.click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.type(`delete table 'test';`)
|
||||
await page.getByTestId('sql-run-button').click()
|
||||
|
||||
// verify warning modal is visible
|
||||
expect(page.getByRole('heading', { name: 'Potential issue detected with' })).toBeVisible()
|
||||
expect(page.getByText('Query has destructive')).toBeVisible()
|
||||
|
||||
// reset test
|
||||
await page.getByRole('button', { name: 'Cancel' }).click()
|
||||
await page.waitForTimeout(500)
|
||||
await editor.click()
|
||||
await page.keyboard.press('ControlOrMeta+KeyA')
|
||||
await page.keyboard.press('Backspace')
|
||||
|
||||
// verify the result
|
||||
const result = page.getByRole('gridcell', { name: 'hello world' })
|
||||
await expect(result).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('SQL Snippets', () => {
|
||||
test('should create and load a new snippet', async ({ page }) => {
|
||||
await page.goto(toUrl(`/project/${env.PROJECT_REF}/sql`))
|
||||
|
||||
const addButton = page.getByTestId('sql-editor-new-query-button')
|
||||
test('should create and load a new snippet', async ({ ref }) => {
|
||||
const runButton = page.getByTestId('sql-run-button')
|
||||
await page.getByRole('button', { name: 'Favorites' }).click()
|
||||
await page.getByRole('button', { name: 'Shared' }).click()
|
||||
await expect(page.getByText('No shared queries')).toBeVisible()
|
||||
await expect(page.getByText('No favorite queries')).toBeVisible()
|
||||
|
||||
// write some sql in the editor
|
||||
await addButton.click()
|
||||
await page.getByTestId('sql-editor-new-query-button').click()
|
||||
await page.getByRole('menuitem', { name: 'Create a new snippet' }).click()
|
||||
|
||||
const editor = page.getByRole('code').nth(0)
|
||||
await page.waitForTimeout(1000)
|
||||
await editor.click()
|
||||
@@ -77,25 +181,52 @@ test.describe('SQL Snippets', () => {
|
||||
await privateSnippet.getByText('Untitled query').click({ button: 'right' })
|
||||
await page.getByRole('menuitem', { name: 'Rename query', exact: true }).click()
|
||||
await expect(page.getByRole('heading', { name: 'Rename' })).toBeVisible()
|
||||
await page.getByRole('textbox', { name: 'Name' }).fill('test snippet')
|
||||
await page.getByRole('textbox', { name: 'Name' }).fill(pwTestQueryName)
|
||||
await page.getByRole('button', { name: 'Rename query', exact: true }).click()
|
||||
|
||||
const privateSnippet2 = privateSnippet.getByText('test snippet', { exact: true })
|
||||
await expect(privateSnippet2).toBeVisible()
|
||||
await page.waitForResponse(
|
||||
(response) =>
|
||||
(response.url().includes(`projects/${ref}/content`) ||
|
||||
response.url().includes('projects/default/content')) &&
|
||||
response.request().method() === 'PUT' &&
|
||||
response.status().toString().startsWith('2')
|
||||
)
|
||||
await expect(privateSnippet.getByText(pwTestQueryName, { exact: true })).toBeVisible({
|
||||
timeout: 50000,
|
||||
})
|
||||
const privateSnippet2 = await privateSnippet.getByText(pwTestQueryName, { exact: true })
|
||||
|
||||
// share with a team
|
||||
await privateSnippet2.click({ button: 'right' })
|
||||
await page.getByRole('menuitem', { name: 'Share query with team' }).click()
|
||||
await expect(page.getByRole('heading', { name: 'Confirm to share query: test' })).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: 'Confirm to share query' })).toBeVisible()
|
||||
await page.getByRole('button', { name: 'Share query', exact: true }).click()
|
||||
await page.waitForResponse(
|
||||
(response) =>
|
||||
(response.url().includes(`projects/${ref}/content`) ||
|
||||
response.url().includes('projects/default/content')) &&
|
||||
response.request().method() === 'PUT' &&
|
||||
response.status().toString().startsWith('2')
|
||||
)
|
||||
const sharedSnippet = await page.getByLabel('project-level-snippets')
|
||||
await expect(sharedSnippet).toContainText('test snippet')
|
||||
await expect(sharedSnippet).toContainText(pwTestQueryName)
|
||||
|
||||
// unshare a snippet
|
||||
await sharedSnippet.getByText('test snippet').click({ button: 'right' })
|
||||
await sharedSnippet.getByText(pwTestQueryName).click({ button: 'right' })
|
||||
await page.getByRole('menuitem', { name: 'Unshare query with team' }).click()
|
||||
await expect(page.getByRole('heading', { name: 'Confirm to unshare query:' })).toBeVisible()
|
||||
await page.getByRole('button', { name: 'Unshare query', exact: true }).click()
|
||||
await expect(sharedSnippet).not.toBeVisible()
|
||||
|
||||
// delete snippet (for non-local environment)
|
||||
if (!isCLI()) {
|
||||
deleteQuery(page, pwTestQueryName)
|
||||
|
||||
await expect(
|
||||
page.getByText('Successfully deleted 1 query'),
|
||||
'Delete confirmation toast should be visible'
|
||||
).toBeVisible({
|
||||
timeout: 50000,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { expect, Page } from '@playwright/test'
|
||||
import fs from 'fs'
|
||||
import { test } from '../utils/test'
|
||||
import { toUrl } from '../utils/to-url'
|
||||
|
||||
@@ -15,8 +16,9 @@ const getSelectors = (tableName: string) => ({
|
||||
saveBtn: (page) => page.getByRole('button', { name: 'Save' }),
|
||||
definitionTab: (page) => page.getByText('definition', { exact: true }),
|
||||
viewLines: (page) => page.locator('div.view-lines'),
|
||||
insertRowBtn: (page) => page.getByTestId('table-editor-insert-new-row'),
|
||||
insertModal: (page) => page.getByText('Insert a new row into'),
|
||||
insertBtn: (page) => page.getByTestId('table-editor-insert-new-row'),
|
||||
insertRow: (page) => page.getByText('Insert a new row into'),
|
||||
insertColumn: (page) => page.getByText('Insert a new column into'),
|
||||
defaultValueInput: (page) => page.getByTestId('defaultValueColumn-input'),
|
||||
actionBarSaveRow: (page) => page.getByTestId('action-bar-save-row'),
|
||||
grid: (page) => page.getByRole('grid'),
|
||||
@@ -61,9 +63,6 @@ const createTable = async (page: Page, tableName: string) => {
|
||||
|
||||
await s.saveBtn(page).click()
|
||||
|
||||
// wait till we see the success toast
|
||||
// Text: Table tableName is good to go!
|
||||
|
||||
await expect(
|
||||
page.getByText(`Table ${tableName} is good to go!`),
|
||||
'Success toast should be visible after table creation'
|
||||
@@ -77,7 +76,7 @@ const createTable = async (page: Page, tableName: string) => {
|
||||
).toBeVisible()
|
||||
}
|
||||
|
||||
const deleteTables = async (page: Page, tableName: string) => {
|
||||
const deleteTable = async (page: Page, tableName: string) => {
|
||||
const s = getSelectors(tableName)
|
||||
|
||||
await page.waitForTimeout(500)
|
||||
@@ -94,11 +93,35 @@ const deleteTables = async (page: Page, tableName: string) => {
|
||||
).toBeVisible()
|
||||
}
|
||||
|
||||
const deleteEnum = async (page: Page, enumName: string, ref: string) => {
|
||||
// give it a second for interactions to load
|
||||
await page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes(`pg-meta/${ref}/types`) ||
|
||||
response.url().includes('pg-meta/default/types')
|
||||
)
|
||||
|
||||
// if enum (test) exists, delete it.
|
||||
const exists = (await page.getByRole('cell', { name: enumName, exact: true }).count()) > 0
|
||||
if (!exists) return
|
||||
|
||||
await page
|
||||
.getByRole('row', { name: `public ${enumName}` })
|
||||
.getByRole('button')
|
||||
.click()
|
||||
await page.getByRole('menuitem', { name: 'Delete type' }).click()
|
||||
await page.getByRole('heading', { name: 'Confirm to delete enumerated' }).click()
|
||||
await page.getByRole('button', { name: 'Confirm delete' }).click()
|
||||
await expect(page.getByText(`Successfully deleted "${enumName}"`)).toBeVisible()
|
||||
}
|
||||
|
||||
test.describe('Table Editor', () => {
|
||||
let page: Page
|
||||
const testTableName = `pw-test-table-editor`
|
||||
const tableNameRlsEnabled = `pw-test-rls-enabled`
|
||||
const tableNameRlsDisabled = `pw-test-rls-disabled`
|
||||
const tableNameEnum = `pw-test-enum`
|
||||
const tableNameCsv = `pw-test-csv`
|
||||
|
||||
test.beforeAll(async ({ browser, ref }) => {
|
||||
test.setTimeout(60000)
|
||||
@@ -111,18 +134,22 @@ test.describe('Table Editor', () => {
|
||||
|
||||
await page.waitForTimeout(2000)
|
||||
// delete table name if it exists
|
||||
await deleteTables(page, testTableName)
|
||||
await deleteTables(page, tableNameRlsEnabled)
|
||||
await deleteTables(page, tableNameRlsDisabled)
|
||||
await deleteTable(page, testTableName)
|
||||
await deleteTable(page, tableNameRlsEnabled)
|
||||
await deleteTable(page, tableNameRlsDisabled)
|
||||
await deleteTable(page, tableNameEnum)
|
||||
await deleteTable(page, tableNameCsv)
|
||||
})
|
||||
|
||||
test.afterAll(async () => {
|
||||
test.setTimeout(60000)
|
||||
|
||||
// delete all tables related to this test
|
||||
await deleteTables(page, testTableName)
|
||||
await deleteTables(page, tableNameRlsEnabled)
|
||||
await deleteTables(page, tableNameRlsDisabled)
|
||||
await deleteTable(page, testTableName)
|
||||
await deleteTable(page, tableNameRlsEnabled)
|
||||
await deleteTable(page, tableNameRlsDisabled)
|
||||
await deleteTable(page, tableNameEnum)
|
||||
await deleteTable(page, tableNameCsv)
|
||||
})
|
||||
|
||||
test('should perform all table operations sequentially', async ({ ref }) => {
|
||||
@@ -143,14 +170,14 @@ test.describe('Table Editor', () => {
|
||||
|
||||
// 2. Insert test data
|
||||
await page.getByRole('button', { name: `View ${testTableName}` }).click()
|
||||
await s.insertRowBtn(page).click()
|
||||
await s.insertModal(page).click()
|
||||
await s.insertBtn(page).click()
|
||||
await s.insertRow(page).click()
|
||||
await s.defaultValueInput(page).fill('100')
|
||||
await s.actionBarSaveRow(page).click()
|
||||
|
||||
await page.getByRole('button', { name: `View ${testTableName}` }).click()
|
||||
await s.insertRowBtn(page).click()
|
||||
await s.insertModal(page).click()
|
||||
await s.insertBtn(page).click()
|
||||
await s.insertRow(page).click()
|
||||
await s.defaultValueInput(page).fill('4')
|
||||
await s.actionBarSaveRow(page).click()
|
||||
|
||||
@@ -225,7 +252,7 @@ test.describe('Table Editor', () => {
|
||||
'Tables list should be visible in public schema'
|
||||
).toBeVisible()
|
||||
|
||||
await deleteTables(page, testTableName)
|
||||
await deleteTable(page, testTableName)
|
||||
})
|
||||
|
||||
test('should show rls accordingly', async () => {
|
||||
@@ -253,7 +280,140 @@ test.describe('Table Editor', () => {
|
||||
await page.getByRole('button', { name: `View ${tableNameRlsDisabled}` }).click()
|
||||
await expect(page.getByRole('button', { name: 'RLS disabled' })).toBeVisible()
|
||||
|
||||
await deleteTables(page, tableNameRlsEnabled)
|
||||
await deleteTables(page, tableNameRlsDisabled)
|
||||
await deleteTable(page, tableNameRlsEnabled)
|
||||
await deleteTable(page, tableNameRlsDisabled)
|
||||
})
|
||||
|
||||
test('add enums and show enums on table', async ({ ref }) => {
|
||||
const ENUM_NAME = 'test_enum'
|
||||
const ENUM_COLUMN_NAME = 'test_column'
|
||||
|
||||
// clear local storage, as it might result in some flakiness
|
||||
await page.evaluate((ref) => {
|
||||
localStorage.removeItem('dashboard-history-default')
|
||||
localStorage.removeItem(`dashboard-history-${ref}`)
|
||||
}, ref)
|
||||
await page.goto(toUrl(`/project/${ref}/database/types?schema=public`))
|
||||
|
||||
// delete enum if it exists
|
||||
await deleteEnum(page, ENUM_NAME, ref)
|
||||
|
||||
// create a new enum
|
||||
await page.getByRole('button', { name: 'Create type' }).click()
|
||||
await page.getByRole('textbox', { name: 'Name' }).fill(ENUM_NAME)
|
||||
await page.locator('input[name="values.0.value"]').fill('value1')
|
||||
await page.getByRole('button', { name: 'Add value' }).click()
|
||||
await page.locator('input[name="values.1.value"]').fill('value2')
|
||||
await page.getByRole('button', { name: 'Create type' }).click()
|
||||
|
||||
// Wait for enum response to be completed
|
||||
await page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes(`pg-meta/${ref}/types`) ||
|
||||
response.url().includes('pg-meta/default/types')
|
||||
)
|
||||
|
||||
// verify enum is created
|
||||
await expect(page.getByRole('cell', { name: ENUM_NAME, exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('cell', { name: 'value1, value2', exact: true })).toBeVisible()
|
||||
|
||||
// create a new table with new column for enums
|
||||
await page.goto(toUrl(`/project/${ref}/editor`))
|
||||
|
||||
const s = getSelectors(tableNameEnum)
|
||||
await s.newTableBtn(page).click()
|
||||
await s.tableNameInput(page).fill(tableNameEnum)
|
||||
await s.createdAtExtraOptions(page).click()
|
||||
await page.getByText('Is Nullable').click()
|
||||
await s.createdAtExtraOptions(page).click()
|
||||
await s.addColumnBtn(page).click()
|
||||
await s.columnNameInput(page).fill(ENUM_COLUMN_NAME)
|
||||
await page.getByRole('combobox').filter({ hasText: 'Choose a column type...' }).click()
|
||||
await page.getByPlaceholder('Search types...').fill(ENUM_NAME)
|
||||
await page.getByRole('option', { name: ENUM_NAME }).click()
|
||||
await s.saveBtn(page).click()
|
||||
|
||||
await expect(
|
||||
page.getByText(`Table ${tableNameEnum} is good to go!`),
|
||||
'Success toast should be visible after table creation'
|
||||
).toBeVisible({
|
||||
timeout: 50000,
|
||||
})
|
||||
|
||||
// Wait for the grid to be visible and data to be loaded
|
||||
await expect(s.grid(page), 'Grid should be visible after inserting data').toBeVisible()
|
||||
await expect(page.getByRole('columnheader', { name: ENUM_NAME })).toBeVisible()
|
||||
|
||||
// insert row with enum value
|
||||
await s.insertBtn(page).click()
|
||||
await s.insertRow(page).click()
|
||||
await page.getByRole('combobox').selectOption('value1')
|
||||
await s.actionBarSaveRow(page).click()
|
||||
await expect(page.getByRole('gridcell', { name: 'value1' })).toBeVisible()
|
||||
|
||||
// insert row with another enum value
|
||||
await s.insertBtn(page).click()
|
||||
await s.insertRow(page).click()
|
||||
await page.getByRole('combobox').selectOption('value2')
|
||||
await s.actionBarSaveRow(page).click()
|
||||
await expect(page.getByRole('gridcell', { name: 'value2' })).toBeVisible()
|
||||
|
||||
// delete enum and enum table
|
||||
await deleteTable(page, tableNameEnum)
|
||||
await page.goto(toUrl(`/project/${ref}/database/types?schema=public`))
|
||||
await deleteEnum(page, ENUM_NAME, ref)
|
||||
|
||||
// should end at the init link
|
||||
// clear local storage, as it might result in some flakiness
|
||||
await page.evaluate((ref) => {
|
||||
localStorage.removeItem('dashboard-history-default')
|
||||
localStorage.removeItem(`dashboard-history-${ref}`)
|
||||
}, ref)
|
||||
await page.goto(toUrl(`/project/${ref}/editor`))
|
||||
})
|
||||
|
||||
test('csv import works properly', async () => {
|
||||
// create a new table and insert some data
|
||||
await createTable(page, tableNameCsv)
|
||||
const s = getSelectors(tableNameCsv)
|
||||
await page.getByRole('button', { name: `View ${tableNameCsv}` }).click()
|
||||
await s.insertBtn(page).click()
|
||||
await s.insertRow(page).click()
|
||||
await s.defaultValueInput(page).fill('123')
|
||||
await s.actionBarSaveRow(page).click()
|
||||
await s.insertBtn(page).click()
|
||||
await s.insertRow(page).click()
|
||||
await s.defaultValueInput(page).fill('456')
|
||||
await s.actionBarSaveRow(page).click()
|
||||
await s.insertBtn(page).click()
|
||||
await s.insertRow(page).click()
|
||||
await s.defaultValueInput(page).fill('789')
|
||||
await s.actionBarSaveRow(page).click()
|
||||
|
||||
// download csv
|
||||
const tableBtn = await page.getByRole('button', { name: 'View pw-test-csv' })
|
||||
await tableBtn.getByRole('button').last().click()
|
||||
await page.getByRole('menuitem', { name: 'Export data' }).click()
|
||||
const downloadPromise = page.waitForEvent('download')
|
||||
await page.getByRole('menuitem', { name: 'Export table as CSV' }).click()
|
||||
const download = await downloadPromise
|
||||
expect(download.suggestedFilename()).toContain('.csv')
|
||||
const downloadPath = await download.path()
|
||||
|
||||
// verify file contents
|
||||
const csvContent = fs.readFileSync(downloadPath, 'utf-8').replace(/\r?\n/g, '\n')
|
||||
const rows = csvContent.trim().split('\n')
|
||||
const defaultColumnValues = rows.map((row) => {
|
||||
const columns = row.split(',')
|
||||
return columns[2].trim()
|
||||
})
|
||||
const expectedDefaultColumnValues = ['defaultValueColumn', '123', '456', '789']
|
||||
defaultColumnValues.forEach((expectedValue) => {
|
||||
expect(expectedDefaultColumnValues).toContain(expectedValue)
|
||||
})
|
||||
|
||||
// remove the downloaded file + clean up tables
|
||||
fs.unlinkSync(downloadPath)
|
||||
await deleteTable(page, tableNameCsv)
|
||||
})
|
||||
})
|
||||
|
||||
11
e2e/studio/utils/is-cli.ts
Normal file
11
e2e/studio/utils/is-cli.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { env } from '../env.config'
|
||||
|
||||
/**
|
||||
* Returns true if running in CLI/self-hosted mode (IS_PLATFORM=false),
|
||||
* false if running in hosted mode (IS_PLATFORM=true).
|
||||
*/
|
||||
export function isCLI(): boolean {
|
||||
// IS_PLATFORM=true = hosted mode
|
||||
// IS_PLATFORM=false = CLI/self-hosted mode
|
||||
return env.IS_PLATFORM === 'false'
|
||||
}
|
||||
Reference in New Issue
Block a user