2
0

feat(results): Brand new Results table

- Resizable columns
- Hide / Show columns
- Reorganize columns
- Expand result
This commit is contained in:
Baptiste Arnaud
2022-07-01 17:08:35 +02:00
parent cf6e8a21be
commit d84f99074d
34 changed files with 1427 additions and 738 deletions

View File

@ -16,121 +16,172 @@ import { deleteButtonInConfirmDialog } from '../services/selectorUtils'
const typebotId = cuid()
test.describe('Results page', () => {
test('Submission table header should be parsed correctly', async ({
page,
}) => {
const typebotId = cuid()
await importTypebotInDatabase(
path.join(
__dirname,
'../fixtures/typebots/results/submissionHeader.json'
),
{
id: typebotId,
}
)
await page.goto(`/typebots/${typebotId}/results`)
await expect(page.locator('text=Submitted at')).toBeVisible()
await expect(page.locator('text=Welcome')).toBeVisible()
await expect(page.locator('text=Email')).toBeVisible()
await expect(page.locator('text=Name')).toBeVisible()
await expect(page.locator('text=Services')).toBeVisible()
await expect(page.locator('text=Additional information')).toBeVisible()
await expect(page.locator('text=utm_source')).toBeVisible()
await expect(page.locator('text=utm_userid')).toBeVisible()
})
test('Submission table header should be parsed correctly', async ({ page }) => {
const typebotId = cuid()
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/results/submissionHeader.json'),
{
id: typebotId,
}
)
await page.goto(`/typebots/${typebotId}/results`)
await expect(page.locator('text=Submitted at')).toBeVisible()
await expect(page.locator('text=Welcome')).toBeVisible()
await expect(page.locator('text=Email')).toBeVisible()
await expect(page.locator('text=Name')).toBeVisible()
await expect(page.locator('text=Services')).toBeVisible()
await expect(page.locator('text=Additional information')).toBeVisible()
await expect(page.locator('text=utm_source')).toBeVisible()
await expect(page.locator('text=utm_userid')).toBeVisible()
})
test('results should be deletable', async ({ page }) => {
await createTypebots([
{
id: typebotId,
...parseDefaultGroupWithBlock({
type: InputBlockType.TEXT,
options: defaultTextInputOptions,
}),
},
])
await createResults({ typebotId })
await page.goto(`/typebots/${typebotId}/results`)
await selectFirstResults(page)
await page.click('button:has-text("Delete2")')
await deleteButtonInConfirmDialog(page).click()
await expect(page.locator('text=content199')).toBeHidden()
await expect(page.locator('text=content198')).toBeHidden()
await page.waitForTimeout(1000)
await page.click('[data-testid="checkbox"] >> nth=0')
await page.click('button:has-text("Delete198")')
await deleteButtonInConfirmDialog(page).click()
await page.waitForTimeout(1000)
expect(await page.locator('tr').count()).toBe(1)
})
test('results should be deletable', async ({ page }) => {
await createTypebots([
{
id: typebotId,
...parseDefaultGroupWithBlock({
type: InputBlockType.TEXT,
options: defaultTextInputOptions,
}),
},
])
await createResults({ typebotId })
await page.goto(`/typebots/${typebotId}/results`)
await selectFirstResults(page)
await page.click('text="Delete"')
await deleteButtonInConfirmDialog(page).click()
await expect(page.locator('text=content199')).toBeHidden()
await expect(page.locator('text=content198')).toBeHidden()
await page.waitForTimeout(1000)
await page.click('[data-testid="checkbox"] >> nth=0')
await page.click('text="Delete"')
await deleteButtonInConfirmDialog(page).click()
await page.waitForTimeout(1000)
expect(await page.locator('tr').count()).toBe(1)
await expect(page.locator('text="Delete"')).toBeHidden()
})
test('submissions table should have infinite scroll', async ({ page }) => {
const scrollToBottom = () =>
page.evaluate(() => {
const tableWrapper = document.querySelector('.table-wrapper')
if (!tableWrapper) return
tableWrapper.scrollTo(0, tableWrapper.scrollHeight)
})
await createResults({ typebotId })
await page.goto(`/typebots/${typebotId}/results`)
await expect(page.locator('text=content199')).toBeVisible()
await expect(page.locator('text=content149')).toBeHidden()
await scrollToBottom()
await expect(page.locator('text=content149')).toBeVisible()
await expect(page.locator('text=content99')).toBeHidden()
await scrollToBottom()
await expect(page.locator('text=content99')).toBeVisible()
await expect(page.locator('text=content49')).toBeHidden()
await scrollToBottom()
await expect(page.locator('text=content49')).toBeVisible()
await expect(page.locator('text=content0')).toBeVisible()
})
test('should correctly export selection in CSV', async ({ page }) => {
await page.goto(`/typebots/${typebotId}/results`)
await selectFirstResults(page)
const [download] = await Promise.all([
page.waitForEvent('download'),
page.locator('button:has-text("Export2")').click(),
])
const path = await download.path()
expect(path).toBeDefined()
const file = readFileSync(path as string).toString()
const { data } = parse(file)
validateExportSelection(data)
await page.click('[data-testid="checkbox"] >> nth=0')
const [downloadAll] = await Promise.all([
page.waitForEvent('download'),
page.locator('button:has-text("Export200")').click(),
])
const pathAll = await downloadAll.path()
expect(pathAll).toBeDefined()
const fileAll = readFileSync(pathAll as string).toString()
const { data: dataAll } = parse(fileAll)
validateExportAll(dataAll)
})
test.describe('Free user', async () => {
test.use({
storageState: path.join(__dirname, '../freeUser.json'),
})
test("Incomplete results shouldn't be displayed", async ({ page }) => {
await prisma.typebot.update({
where: { id: typebotId },
data: { workspaceId: freeWorkspaceId },
})
await page.goto(`/typebots/${typebotId}/results`)
await page.click('text=Unlock')
await expect(page.locator('text=For solo creator')).toBeVisible()
test('submissions table should have infinite scroll', async ({ page }) => {
const scrollToBottom = () =>
page.evaluate(() => {
const tableWrapper = document.querySelector('.table-wrapper')
if (!tableWrapper) return
tableWrapper.scrollTo(0, tableWrapper.scrollHeight)
})
await createResults({ typebotId })
await page.goto(`/typebots/${typebotId}/results`)
await expect(page.locator('text=content199')).toBeVisible()
await expect(page.locator('text=content149')).toBeHidden()
await scrollToBottom()
await expect(page.locator('text=content149')).toBeVisible()
await expect(page.locator('text=content99')).toBeHidden()
await scrollToBottom()
await expect(page.locator('text=content99')).toBeVisible()
await expect(page.locator('text=content49')).toBeHidden()
await scrollToBottom()
await expect(page.locator('text=content49')).toBeVisible()
await expect(page.locator('text=content0')).toBeVisible()
})
test('should correctly export selection in CSV', async ({ page }) => {
await page.goto(`/typebots/${typebotId}/results`)
await selectFirstResults(page)
const [download] = await Promise.all([
page.waitForEvent('download'),
page.locator('text="Export"').click(),
])
const path = await download.path()
expect(path).toBeDefined()
const file = readFileSync(path as string).toString()
const { data } = parse(file)
validateExportSelection(data)
await page.click('[data-testid="checkbox"] >> nth=0')
const [downloadAll] = await Promise.all([
page.waitForEvent('download'),
page.locator('text="Export"').click(),
])
const pathAll = await downloadAll.path()
expect(pathAll).toBeDefined()
const fileAll = readFileSync(pathAll as string).toString()
const { data: dataAll } = parse(fileAll)
validateExportAll(dataAll)
})
test.describe('Free user', async () => {
test.use({
storageState: path.join(__dirname, '../freeUser.json'),
})
test("Incomplete results shouldn't be displayed", async ({ page }) => {
await prisma.typebot.update({
where: { id: typebotId },
data: { workspaceId: freeWorkspaceId },
})
await page.goto(`/typebots/${typebotId}/results`)
await page.click('text=Unlock')
await expect(page.locator('text=For solo creator')).toBeVisible()
})
})
test('Can resize, hide and reorder columns', async ({ page }) => {
const typebotId = cuid()
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/results/submissionHeader.json'),
{
id: typebotId,
}
)
await page.goto(`/typebots/${typebotId}/results`)
// Resize
expect((await page.locator('th >> nth=4').boundingBox())?.width).toBe(200)
await page.waitForTimeout(500)
await page.dragAndDrop(
'[data-testid="resize-handle"] >> nth=3',
'[data-testid="resize-handle"] >> nth=3',
{ targetPosition: { x: 150, y: 0 }, force: true }
)
await page.waitForTimeout(500)
expect((await page.locator('th >> nth=4').boundingBox())?.width).toBe(345)
// Hide
await expect(
page.locator('[data-testid="Submitted at header"]')
).toBeVisible()
await expect(page.locator('[data-testid="Email header"]')).toBeVisible()
await page.click('button >> text="Columns"')
await page.click('[aria-label="Hide column"] >> nth=0')
await page.click('[aria-label="Hide column"] >> nth=1')
await expect(page.locator('[data-testid="Submitted at header"]')).toBeHidden()
await expect(page.locator('[data-testid="Email header"]')).toBeHidden()
// Reorder
await expect(page.locator('th >> nth=1')).toHaveText('Welcome')
await expect(page.locator('th >> nth=2')).toHaveText('Name')
await page.dragAndDrop(
'[aria-label="Drag"] >> nth=0',
'[aria-label="Drag"] >> nth=0',
{ targetPosition: { x: 0, y: 80 }, force: true }
)
await expect(page.locator('th >> nth=1')).toHaveText('Name')
await expect(page.locator('th >> nth=2')).toHaveText('Welcome')
// Preferences should be persisted
const saveAndReload = async (page: Page) => {
await page.click('text="Theme"')
await page.waitForTimeout(2000)
await page.goto(`/typebots/${typebotId}/results`)
}
await saveAndReload(page)
expect((await page.locator('th >> nth=1').boundingBox())?.width).toBe(345)
await expect(page.locator('[data-testid="Submitted at header"]')).toBeHidden()
await expect(page.locator('[data-testid="Email header"]')).toBeHidden()
await expect(page.locator('th >> nth=1')).toHaveText('Name')
await expect(page.locator('th >> nth=2')).toHaveText('Welcome')
})
const validateExportSelection = (data: unknown[]) => {