2
0

📦 Upgrade packages

This commit is contained in:
Baptiste Arnaud
2022-11-02 19:45:46 +01:00
committed by GitHub
parent 48285479cc
commit 2c66c59dfc
64 changed files with 2518 additions and 3158 deletions

View File

@ -119,12 +119,12 @@
"graphCoordinates": { "x": 639, "y": 142 }
},
{
"id": "q5dAhqSTCaNdiGSJm9B9Rw",
"id": "group1",
"blocks": [
{
"id": "sgtE2Sy7cKykac9B223Kq9R",
"type": "text",
"groupId": "q5dAhqSTCaNdiGSJm9B9Rw",
"groupId": "group1",
"content": {
"html": "<div>What&#x27;s your name?</div>",
"richText": [
@ -134,9 +134,9 @@
}
},
{
"id": "sqEsMo747LTDnY9FjQcEwUv",
"id": "block1",
"type": "text input",
"groupId": "q5dAhqSTCaNdiGSJm9B9Rw",
"groupId": "group1",
"options": {
"isLong": false,
"labels": {

View File

@ -1,14 +0,0 @@
import { FullConfig } from '@playwright/test'
import { setupDatabase, teardownDatabase } from 'utils/playwright/databaseSetup'
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('dotenv').config({ path: '.env' })
async function globalSetup(config: FullConfig) {
const { baseURL } = config.projects[0].use
if (!baseURL) throw new Error('baseURL is missing')
await teardownDatabase()
await setupDatabase()
}
export default globalSetup

View File

@ -10,7 +10,7 @@ import { proWorkspaceId } from 'utils/playwright/databaseSetup'
const prisma = new PrismaClient()
const stripe = new Stripe(process.env.STRIPE_TEST_SECRET_KEY ?? '', {
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', {
apiVersion: '2022-08-01',
})

View File

@ -21,7 +21,7 @@ test('should display user info properly', async ({ page }) => {
await expect(page.locator('img >> nth=1')).toHaveAttribute(
'src',
new RegExp(
`http://localhost:9000/typebot/public/users/${userId}/avatar`,
`${process.env.S3_ENDPOINT}/${process.env.S3_BUCKET}/public/users/${userId}/avatar`,
'gm'
)
)

View File

@ -1,7 +1,10 @@
import test, { expect } from '@playwright/test'
import cuid from 'cuid'
import path from 'path'
import { importTypebotInDatabase } from 'utils/playwright/databaseActions'
import {
importTypebotInDatabase,
injectFakeResults,
} from 'utils/playwright/databaseActions'
import { starterWorkspaceId } from 'utils/playwright/databaseSetup'
test('analytics are not available for non-pro workspaces', async ({ page }) => {
@ -13,6 +16,7 @@ test('analytics are not available for non-pro workspaces', async ({ page }) => {
workspaceId: starterWorkspaceId,
}
)
await injectFakeResults({ typebotId, count: 10 })
await page.goto(`/typebots/${typebotId}/results/analytics`)
const firstDropoffBox = page.locator('text="%" >> nth=0')
await firstDropoffBox.hover()

View File

@ -227,7 +227,7 @@ test('should display invoices', async ({ page }) => {
await page.click('text=Settings & Members')
await page.click('text=Billing & Usage')
await expect(page.locator('text="Invoices"')).toBeVisible()
await expect(page.locator('tr')).toHaveCount(2)
await expect(page.locator('tr')).toHaveCount(3)
await expect(page.locator('text="€39.00"')).toBeVisible()
})

View File

@ -33,7 +33,7 @@ test.describe.parallel('Image bubble block', () => {
await expect(page.locator('img')).toHaveAttribute(
'src',
new RegExp(
`http://localhost:9000/typebot/public/typebots/${typebotId}/avatar.jpg`,
`${process.env.S3_ENDPOINT}/${process.env.S3_BUCKET}/public/typebots/${typebotId}/avatar.jpg`,
'gm'
)
)

View File

@ -26,19 +26,19 @@ test.describe('Payment input block', () => {
await page.fill('[placeholder="Typebot"]', 'My Stripe Account')
await page.fill(
'[placeholder="sk_test_..."]',
process.env.STRIPE_TEST_SECRET_KEY ?? ''
process.env.STRIPE_SECRET_KEY ?? ''
)
await page.fill(
'[placeholder="sk_live_..."]',
process.env.STRIPE_TEST_SECRET_KEY ?? ''
process.env.STRIPE_SECRET_KEY ?? ''
)
await page.fill(
'[placeholder="pk_test_..."]',
process.env.STRIPE_TEST_PUBLIC_KEY ?? ''
process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY ?? ''
)
await page.fill(
'[placeholder="pk_live_..."]',
process.env.STRIPE_TEST_PUBLIC_KEY ?? ''
process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY ?? ''
)
await expect(page.locator('button >> text="Connect"')).toBeEnabled()
await page.click('button >> text="Connect"')
@ -66,6 +66,9 @@ test.describe('Payment input block', () => {
await stripePaymentForm(page)
.locator(`[placeholder="1234 1234 1234 1234"]`)
.fill('4242424242424242')
const zipInput = stripePaymentForm(page).getByPlaceholder('90210')
const isZipInputVisible = await zipInput.isVisible()
if (isZipInputVisible) await zipInput.fill('12345')
await typebotViewer(page).locator(`text="Pay 30€"`).click()
await expect(typebotViewer(page).locator(`text="Success"`)).toBeVisible()
})

View File

@ -11,10 +11,9 @@ test.describe('Send email block', () => {
if (
!process.env.SMTP_USERNAME ||
!process.env.SMTP_PORT ||
!process.env.SMTP_SECURE ||
!process.env.SMTP_HOST ||
!process.env.SMTP_PASSWORD ||
!process.env.SMTP_FROM
!process.env.NEXT_PUBLIC_SMTP_FROM
)
throw new Error('SMTP_ env vars are missing')
await importTypebotInDatabase(
@ -29,7 +28,7 @@ test.describe('Send email block', () => {
await page.goto(`/typebots/${typebotId}/edit`)
await page.click('text=Configure...')
await page.click(`text=${process.env.SMTP_FROM}`)
await page.click(`text=notifications@typebot.io`)
await page.click('text=Connect new')
const createButton = page.locator('button >> text=Create')
await expect(createButton).toBeDisabled()
@ -44,7 +43,6 @@ test.describe('Send email block', () => {
process.env.SMTP_USERNAME
)
await page.fill('[type="password"]', process.env.SMTP_PASSWORD)
if (process.env.SMTP_SECURE === 'true') await page.click('text=Use TLS?')
await page.fill('input[role="spinbutton"]', process.env.SMTP_PORT)
await expect(createButton).toBeEnabled()
await createButton.click()

View File

@ -24,7 +24,7 @@ test.describe('Webhook block', () => {
await page.click('text=Configure...')
await page.fill(
'input[placeholder="Paste webhook URL..."]',
`${process.env.PLAYWRIGHT_BUILDER_TEST_BASE_URL}/api/mock/webhook-easy-config`
`${process.env.NEXTAUTH_URL}/api/mock/webhook-easy-config`
)
await page.click('text=Test the request')
await expect(page.locator('div[role="textbox"] >> nth=-1')).toContainText(
@ -46,7 +46,7 @@ test.describe('Webhook block', () => {
await page.click('text=Configure...')
await page.fill(
'input[placeholder="Paste webhook URL..."]',
`${process.env.PLAYWRIGHT_BUILDER_TEST_BASE_URL}/api/mock/webhook`
`${process.env.NEXTAUTH_URL}/api/mock/webhook`
)
await page.click('text=Advanced configuration')
await page.click('text=GET')

View File

@ -1,184 +1,174 @@
import test, { expect, Page } from '@playwright/test'
import cuid from 'cuid'
import { readFileSync } from 'fs'
import { defaultTextInputOptions, InputBlockType } from 'models'
import { parse } from 'papaparse'
import path from 'path'
import {
importTypebotInDatabase,
injectFakeResults,
createTypebots,
} from 'utils/playwright/databaseActions'
import { parseDefaultGroupWithBlock } from 'utils/playwright/databaseHelpers'
import { deleteButtonInConfirmDialog } from '../services/selectorUtils'
const typebotId = cuid()
test('Submission table header should be parsed correctly', async ({ page }) => {
const typebotId = cuid()
test.beforeEach(async () => {
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 injectFakeResults({ typebotId, count: 200, isChronological: true })
await page.goto(`/typebots/${typebotId}/results`)
await expect(page.locator('text=content199')).toBeVisible()
await page.click('[data-testid="checkbox"] >> nth=1')
await page.click('[data-testid="checkbox"] >> nth=2')
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 injectFakeResults({ typebotId, count: 200, isChronological: true })
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 expect(page.locator('text=content199')).toBeVisible()
await page.click('[data-testid="checkbox"] >> nth=1')
await page.click('[data-testid="checkbox"] >> nth=2')
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('Can resize, hide and reorder columns', async ({ page }) => {
const typebotId = cuid()
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/results/submissionHeader.json'),
{
id: typebotId,
}
)
test('Results', async ({ page }) => {
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)
await test.step('Check header format', async () => {
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()
})
// 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()
await test.step('Resize columns', async () => {
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)
})
// 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')
await test.step('Hide columns', async () => {
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()
})
// 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')
await test.step('Reorder columns', async () => {
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')
})
await test.step('Preferences should be persisted', async () => {
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')
})
await test.step('Infinite scroll', async () => {
await expect(page.locator('text=content199')).toBeVisible()
await expect(page.locator('text=content149')).toBeHidden()
await scrollToBottom(page)
await expect(page.locator('text=content149')).toBeVisible()
await expect(page.locator('text=content99')).toBeHidden()
await scrollToBottom(page)
await expect(page.locator('text=content99')).toBeVisible()
await expect(page.locator('text=content49')).toBeHidden()
await scrollToBottom(page)
await expect(page.locator('text=content49')).toBeVisible()
await expect(page.locator('text=content0')).toBeVisible()
})
await test.step('Export', async () => {
// For some reason, we need to double click on checkboxes to check them
await getNthCheckbox(page, 1).dblclick()
await getNthCheckbox(page, 2).dblclick()
const [download] = await Promise.all([
page.waitForEvent('download'),
page.getByRole('button', { name: 'Export 2' }).click(),
])
const path = await download.path()
expect(path).toBeDefined()
const file = readFileSync(path as string).toString()
const { data } = parse(file)
validateExportSelection(data)
await getNthCheckbox(page, 0).click()
const [downloadAll] = await Promise.all([
page.waitForEvent('download'),
page.getByRole('button', { name: 'Export 200' }).click(),
])
const pathAll = await downloadAll.path()
expect(pathAll).toBeDefined()
const fileAll = readFileSync(pathAll as string).toString()
const { data: dataAll } = parse(fileAll)
validateExportAll(dataAll)
await getNthCheckbox(page, 0).click()
})
await test.step('Delete', async () => {
await getNthCheckbox(page, 1).click()
await getNthCheckbox(page, 2).click()
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()
})
})
const validateExportSelection = (data: unknown[]) => {
expect(data).toHaveLength(3)
expect((data[1] as unknown[])[1]).toBe('content199')
expect((data[2] as unknown[])[1]).toBe('content198')
expect((data[1] as unknown[])[3]).toBe('content199')
expect((data[2] as unknown[])[3]).toBe('content198')
}
const validateExportAll = (data: unknown[]) => {
expect(data).toHaveLength(201)
expect((data[1] as unknown[])[1]).toBe('content199')
expect((data[200] as unknown[])[1]).toBe('content0')
expect((data[1] as unknown[])[3]).toBe('content199')
expect((data[200] as unknown[])[3]).toBe('content0')
}
const scrollToBottom = (page: Page) =>
page.evaluate(() => {
const tableWrapper = document.querySelector('.table-wrapper')
if (!tableWrapper) return
tableWrapper.scrollTo(0, tableWrapper.scrollHeight)
})
const saveAndReload = async (page: Page) => {
await page.click('text="Theme"')
await page.waitForTimeout(2000)
await page.goto(`/typebots/${typebotId}/results`)
}
const getNthCheckbox = (page: Page, n: number) =>
page.getByTestId('checkbox').nth(n)

View File

@ -6,17 +6,19 @@ import { importTypebotInDatabase } from 'utils/playwright/databaseActions'
import { freeWorkspaceId } from 'utils/playwright/databaseSetup'
import { typebotViewer } from 'utils/playwright/testHelpers'
const typebotId = cuid()
test.describe.parallel('Settings page', () => {
test.beforeAll(async () => {
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/settings.json'),
{
id: typebotId,
}
)
})
test.describe('General', () => {
test('should reflect change in real-time', async ({ page }) => {
const typebotId = cuid()
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/settings.json'),
{
id: typebotId,
}
)
await page.goto(`/typebots/${typebotId}/settings`)
await expect(
typebotViewer(page).locator('a:has-text("Made with Typebot")')
@ -134,7 +136,6 @@ test.describe.parallel('Settings page', () => {
await expect(
typebotViewer(page).locator('text="What\'s your name?"')
).toBeVisible()
await page.click('button:has-text("General")')
await expect(
page.locator('[data-testid="starter-lock-tag"]')
).toBeVisible()

View File

@ -91,7 +91,7 @@ test('can manage members', async ({ page }) => {
await page.goto('/typebots')
await page.click('text=Settings & Members')
await page.click('text="Members"')
await expect(page.locator('text="user@email.com"')).toBeVisible()
await expect(page.locator('text="user@email.com"').nth(1)).toBeVisible()
await expect(page.locator('button >> text="Invite"')).toBeEnabled()
await page.fill(
'input[placeholder="colleague@company.com"]',