✨ Add usage-based new pricing plans
This commit is contained in:
committed by
Baptiste Arnaud
parent
6a1eaea700
commit
898367a33b
15
apps/builder/playwright/firstUser.json
Normal file
15
apps/builder/playwright/firstUser.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"cookies": [],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "http://localhost:3000",
|
||||
"localStorage": [
|
||||
{
|
||||
"name": "typebot-20-modal",
|
||||
"value": "hide"
|
||||
},
|
||||
{ "name": "workspaceId", "value": "proWorkspace" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"cookies": [],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "http://localhost:3000",
|
||||
"localStorage": [
|
||||
{
|
||||
"name": "authenticatedUser",
|
||||
"value": "{\"id\":\"freeUser\",\"name\":\"Free user\",\"email\":\"free-user@email.com\",\"emailVerified\":null,\"image\":\"https://avatars.githubusercontent.com/u/16015833?v=4\",\"plan\":\"FREE\",\"stripeId\":null,\"graphNavigation\": \"TRACKPAD\"}"
|
||||
},
|
||||
{
|
||||
"name": "typebot-20-modal",
|
||||
"value": "hide"
|
||||
},
|
||||
{ "name": "workspaceId", "value": "freeWorkspace" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
{
|
||||
"cookies": [],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "http://localhost:3000",
|
||||
"localStorage": [
|
||||
{
|
||||
"name": "authenticatedUser",
|
||||
"value": "{\"id\":\"proUser\",\"name\":\"Pro user\",\"email\":\"pro-user@email.com\",\"emailVerified\":null,\"image\":\"https://avatars.githubusercontent.com/u/16015833?v=4\",\"plan\":\"PRO\",\"stripeId\":null,\"graphNavigation\": \"TRACKPAD\"}"
|
||||
},
|
||||
{
|
||||
"name": "typebot-20-modal",
|
||||
"value": "hide"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
15
apps/builder/playwright/secondUser.json
Normal file
15
apps/builder/playwright/secondUser.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"cookies": [],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "http://localhost:3000",
|
||||
"localStorage": [
|
||||
{
|
||||
"name": "typebot-20-modal",
|
||||
"value": "hide"
|
||||
},
|
||||
{ "name": "workspaceId", "value": "freeWorkspace" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -6,12 +6,12 @@ export const refreshUser = async () => {
|
||||
document.dispatchEvent(event)
|
||||
}
|
||||
|
||||
export const mockSessionApiCalls = (page: Page) =>
|
||||
export const connectedAsOtherUser = async (page: Page) =>
|
||||
page.route('/api/auth/session', (route) => {
|
||||
if (route.request().method() === 'GET') {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
body: '{"user":{"id":"proUser","name":"Pro user","email":"pro-user@email.com","emailVerified":null,"image":"https://avatars.githubusercontent.com/u/16015833?v=4","stripeId":null,"graphNavigation": "TRACKPAD"}}',
|
||||
body: '{"user":{"id":"otherUserId","name":"James Doe","email":"other-user@email.com","emailVerified":null,"image":"https://avatars.githubusercontent.com/u/16015833?v=4","stripeId":null,"graphNavigation": "TRACKPAD"}}',
|
||||
})
|
||||
}
|
||||
return route.continue()
|
||||
|
@ -15,52 +15,129 @@ import {
|
||||
PrismaClient,
|
||||
User,
|
||||
WorkspaceRole,
|
||||
Workspace,
|
||||
} from 'db'
|
||||
import { readFileSync } from 'fs'
|
||||
import { encrypt } from 'utils'
|
||||
import { encrypt, createFakeResults } from 'utils'
|
||||
import Stripe from 'stripe'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
const proWorkspaceId = 'proWorkspace'
|
||||
const stripe = new Stripe(process.env.STRIPE_TEST_SECRET_KEY ?? '', {
|
||||
apiVersion: '2022-08-01',
|
||||
})
|
||||
|
||||
const userId = 'userId'
|
||||
const otherUserId = 'otherUserId'
|
||||
export const freeWorkspaceId = 'freeWorkspace'
|
||||
export const sharedWorkspaceId = 'sharedWorkspace'
|
||||
export const guestWorkspaceId = 'guestWorkspace'
|
||||
export const starterWorkspaceId = 'starterWorkspace'
|
||||
export const proWorkspaceId = 'proWorkspace'
|
||||
const lifetimeWorkspaceId = 'lifetimeWorkspaceId'
|
||||
|
||||
export const teardownDatabase = async () => {
|
||||
const ownerFilter = {
|
||||
where: {
|
||||
workspace: {
|
||||
members: { some: { userId: { in: ['freeUser', 'proUser'] } } },
|
||||
},
|
||||
},
|
||||
}
|
||||
await prisma.workspace.deleteMany({
|
||||
where: {
|
||||
members: {
|
||||
some: { userId: { in: ['freeUser', 'proUser'] } },
|
||||
some: { userId: { in: [userId, otherUserId] } },
|
||||
},
|
||||
},
|
||||
})
|
||||
await prisma.user.deleteMany({
|
||||
where: { id: { in: ['freeUser', 'proUser'] } },
|
||||
where: { id: { in: [userId, otherUserId] } },
|
||||
})
|
||||
return prisma.webhook.deleteMany()
|
||||
}
|
||||
|
||||
export const addSubscriptionToWorkspace = async (
|
||||
workspaceId: string,
|
||||
items: Stripe.SubscriptionCreateParams.Item[],
|
||||
metadata: Pick<
|
||||
Workspace,
|
||||
'additionalChatsIndex' | 'additionalStorageIndex' | 'plan'
|
||||
>
|
||||
) => {
|
||||
const { id: stripeId } = await stripe.customers.create({
|
||||
email: 'test-user@gmail.com',
|
||||
name: 'Test User',
|
||||
})
|
||||
const { id: paymentId } = await stripe.paymentMethods.create({
|
||||
card: {
|
||||
number: '4242424242424242',
|
||||
exp_month: 12,
|
||||
exp_year: 2022,
|
||||
cvc: '123',
|
||||
},
|
||||
type: 'card',
|
||||
})
|
||||
await stripe.paymentMethods.attach(paymentId, { customer: stripeId })
|
||||
await stripe.subscriptions.create({
|
||||
customer: stripeId,
|
||||
items,
|
||||
default_payment_method: paymentId,
|
||||
currency: 'usd',
|
||||
})
|
||||
await prisma.workspace.update({
|
||||
where: { id: workspaceId },
|
||||
data: {
|
||||
stripeId,
|
||||
...metadata,
|
||||
},
|
||||
})
|
||||
await prisma.webhook.deleteMany()
|
||||
await prisma.credentials.deleteMany(ownerFilter)
|
||||
await prisma.dashboardFolder.deleteMany(ownerFilter)
|
||||
return prisma.typebot.deleteMany(ownerFilter)
|
||||
}
|
||||
|
||||
export const setupDatabase = async () => {
|
||||
await createWorkspaces()
|
||||
await createUsers()
|
||||
return createCredentials()
|
||||
}
|
||||
|
||||
export const createWorkspaces = async () =>
|
||||
prisma.workspace.createMany({
|
||||
data: [
|
||||
{
|
||||
id: freeWorkspaceId,
|
||||
name: 'Free workspace',
|
||||
plan: Plan.FREE,
|
||||
},
|
||||
{
|
||||
id: starterWorkspaceId,
|
||||
name: 'Starter workspace',
|
||||
stripeId: 'cus_LnPDugJfa18N41',
|
||||
plan: Plan.STARTER,
|
||||
},
|
||||
{
|
||||
id: proWorkspaceId,
|
||||
name: 'Pro workspace',
|
||||
plan: Plan.PRO,
|
||||
},
|
||||
{
|
||||
id: lifetimeWorkspaceId,
|
||||
name: 'Lifetime workspace',
|
||||
plan: Plan.LIFETIME,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export const createWorkspace = async (workspace: Partial<Workspace>) => {
|
||||
const { id: workspaceId } = await prisma.workspace.create({
|
||||
data: {
|
||||
name: 'Free workspace',
|
||||
plan: Plan.FREE,
|
||||
...workspace,
|
||||
},
|
||||
})
|
||||
await prisma.memberInWorkspace.create({
|
||||
data: { userId, workspaceId, role: WorkspaceRole.ADMIN },
|
||||
})
|
||||
return workspaceId
|
||||
}
|
||||
|
||||
export const createUsers = async () => {
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
id: 'proUser',
|
||||
email: 'pro-user@email.com',
|
||||
name: 'Pro user',
|
||||
id: userId,
|
||||
email: 'user@email.com',
|
||||
name: 'John Doe',
|
||||
graphNavigation: GraphNavigation.TRACKPAD,
|
||||
apiTokens: {
|
||||
createMany: {
|
||||
@ -83,69 +160,34 @@ export const createUsers = async () => {
|
||||
],
|
||||
},
|
||||
},
|
||||
workspaces: {
|
||||
create: {
|
||||
role: WorkspaceRole.ADMIN,
|
||||
workspace: {
|
||||
create: {
|
||||
id: proWorkspaceId,
|
||||
name: "Pro user's workspace",
|
||||
plan: Plan.TEAM,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
id: 'freeUser',
|
||||
email: 'free-user@email.com',
|
||||
name: 'Free user',
|
||||
graphNavigation: GraphNavigation.TRACKPAD,
|
||||
workspaces: {
|
||||
create: {
|
||||
role: WorkspaceRole.ADMIN,
|
||||
workspace: {
|
||||
create: {
|
||||
id: 'free',
|
||||
name: "Free user's workspace",
|
||||
plan: Plan.FREE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
data: { id: otherUserId, email: 'other-user@email.com', name: 'James Doe' },
|
||||
})
|
||||
await prisma.workspace.create({
|
||||
data: {
|
||||
id: freeWorkspaceId,
|
||||
name: 'Free Shared workspace',
|
||||
plan: Plan.FREE,
|
||||
members: {
|
||||
createMany: {
|
||||
data: [
|
||||
{ role: WorkspaceRole.MEMBER, userId: 'proUser' },
|
||||
{ role: WorkspaceRole.ADMIN, userId: 'freeUser' },
|
||||
],
|
||||
},
|
||||
return prisma.memberInWorkspace.createMany({
|
||||
data: [
|
||||
{
|
||||
role: WorkspaceRole.ADMIN,
|
||||
userId,
|
||||
workspaceId: freeWorkspaceId,
|
||||
},
|
||||
},
|
||||
})
|
||||
return prisma.workspace.create({
|
||||
data: {
|
||||
id: sharedWorkspaceId,
|
||||
name: 'Shared workspace',
|
||||
plan: Plan.TEAM,
|
||||
members: {
|
||||
createMany: {
|
||||
data: [
|
||||
{ role: WorkspaceRole.MEMBER, userId: 'proUser' },
|
||||
{ role: WorkspaceRole.ADMIN, userId: 'freeUser' },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: WorkspaceRole.ADMIN,
|
||||
userId,
|
||||
workspaceId: starterWorkspaceId,
|
||||
},
|
||||
},
|
||||
{
|
||||
role: WorkspaceRole.ADMIN,
|
||||
userId,
|
||||
workspaceId: proWorkspaceId,
|
||||
},
|
||||
{
|
||||
role: WorkspaceRole.ADMIN,
|
||||
userId,
|
||||
workspaceId: lifetimeWorkspaceId,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
@ -173,12 +215,12 @@ export const getSignedInUser = (email: string) =>
|
||||
|
||||
export const createTypebots = async (partialTypebots: Partial<Typebot>[]) => {
|
||||
await prisma.typebot.createMany({
|
||||
data: partialTypebots.map(parseTestTypebot) as any[],
|
||||
data: partialTypebots.map(parseTestTypebot),
|
||||
})
|
||||
return prisma.publicTypebot.createMany({
|
||||
data: partialTypebots.map((t) =>
|
||||
parseTypebotToPublicTypebot(t.id + '-public', parseTestTypebot(t))
|
||||
) as any[],
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
@ -217,43 +259,11 @@ export const updateUser = (data: Partial<User>) =>
|
||||
prisma.user.update({
|
||||
data,
|
||||
where: {
|
||||
id: 'proUser',
|
||||
id: userId,
|
||||
},
|
||||
})
|
||||
|
||||
export const createResults = async ({ typebotId }: { typebotId: string }) => {
|
||||
await prisma.result.deleteMany()
|
||||
await prisma.result.createMany({
|
||||
data: [
|
||||
...Array.from(Array(200)).map((_, idx) => {
|
||||
const today = new Date()
|
||||
const rand = Math.random()
|
||||
return {
|
||||
id: `result${idx}`,
|
||||
typebotId,
|
||||
createdAt: new Date(
|
||||
today.setTime(today.getTime() + 1000 * 60 * 60 * 24 * idx)
|
||||
),
|
||||
isCompleted: rand > 0.5,
|
||||
}
|
||||
}),
|
||||
],
|
||||
})
|
||||
return createAnswers()
|
||||
}
|
||||
|
||||
const createAnswers = () => {
|
||||
return prisma.answer.createMany({
|
||||
data: [
|
||||
...Array.from(Array(200)).map((_, idx) => ({
|
||||
resultId: `result${idx}`,
|
||||
content: `content${idx}`,
|
||||
blockId: 'block1',
|
||||
groupId: 'block1',
|
||||
})),
|
||||
],
|
||||
})
|
||||
}
|
||||
export const createResults = createFakeResults(prisma)
|
||||
|
||||
export const createFolder = (workspaceId: string, name: string) =>
|
||||
prisma.dashboardFolder.create({
|
||||
@ -352,6 +362,6 @@ export const importTypebotInDatabase = async (
|
||||
data: parseTypebotToPublicTypebot(
|
||||
updates?.id ? `${updates?.id}-public` : 'publicBot',
|
||||
typebot
|
||||
) as any,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
@ -1,10 +1,6 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
// Can't test the update features because of the auth mocking.
|
||||
test('should display user info properly', async ({ page }) => {
|
||||
await page.goto('/typebots')
|
||||
await page.click('text=Settings & Members')
|
||||
|
175
apps/builder/playwright/tests/billing.spec.ts
Normal file
175
apps/builder/playwright/tests/billing.spec.ts
Normal file
@ -0,0 +1,175 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import cuid from 'cuid'
|
||||
import { Plan } from 'db'
|
||||
import {
|
||||
addSubscriptionToWorkspace,
|
||||
createResults,
|
||||
createTypebots,
|
||||
createWorkspace,
|
||||
starterWorkspaceId,
|
||||
} from '../services/database'
|
||||
|
||||
test('should display valid usage', async ({ page }) => {
|
||||
const starterTypebotId = cuid()
|
||||
createTypebots([{ id: starterTypebotId, workspaceId: starterWorkspaceId }])
|
||||
await page.goto('/typebots')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await expect(page.locator('text="/ 10,000"')).toBeVisible()
|
||||
await expect(page.locator('text="/ 10 GB"')).toBeVisible()
|
||||
await page.click('text=Pro workspace', { force: true })
|
||||
|
||||
await page.click('text=Pro workspace')
|
||||
await page.click('text="Free workspace"')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await expect(page.locator('text="/ 300"')).toBeVisible()
|
||||
await page.click('text=Free workspace', { force: true })
|
||||
|
||||
await createResults({
|
||||
idPrefix: 'usage',
|
||||
count: 10,
|
||||
typebotId: starterTypebotId,
|
||||
isChronological: false,
|
||||
fakeStorage: 1100 * 1024 * 1024,
|
||||
})
|
||||
await page.click('text=Free workspace')
|
||||
await page.click('text="Starter workspace"')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await expect(page.locator('text="/ 2,000"')).toBeVisible()
|
||||
await expect(page.locator('text="/ 2 GB"')).toBeVisible()
|
||||
await expect(page.locator('text="1.07 GB"')).toBeVisible()
|
||||
await expect(page.locator('text="200"')).toBeVisible()
|
||||
await expect(page.locator('[role="progressbar"] >> nth=0')).toHaveAttribute(
|
||||
'aria-valuenow',
|
||||
'10'
|
||||
)
|
||||
await expect(page.locator('[role="progressbar"] >> nth=1')).toHaveAttribute(
|
||||
'aria-valuenow',
|
||||
'54'
|
||||
)
|
||||
|
||||
await createResults({
|
||||
idPrefix: 'usage2',
|
||||
typebotId: starterTypebotId,
|
||||
isChronological: false,
|
||||
count: 900,
|
||||
fakeStorage: 1200 * 1024 * 1024,
|
||||
})
|
||||
await page.click('text="Settings"')
|
||||
await page.click('text="Billing & Usage"')
|
||||
await expect(page.locator('text="/ 2,000"')).toBeVisible()
|
||||
await expect(page.locator('text="1,100"')).toBeVisible()
|
||||
await expect(page.locator('text="/ 2 GB"')).toBeVisible()
|
||||
await expect(page.locator('text="2.25 GB"')).toBeVisible()
|
||||
await expect(page.locator('[aria-valuenow="55"]')).toBeVisible()
|
||||
await expect(page.locator('[aria-valuenow="112"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('plan changes should work', async ({ page }) => {
|
||||
const workspaceId = await createWorkspace({ name: 'Awesome workspace' })
|
||||
|
||||
// Upgrade to STARTER
|
||||
await page.goto('/typebots')
|
||||
await page.click('text=Pro workspace')
|
||||
await page.click('text=Awesome workspace')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await page.click('button >> text="2,000"')
|
||||
await page.click('button >> text="3,500"')
|
||||
await page.click('button >> text="2"')
|
||||
await page.click('button >> text="4"')
|
||||
await expect(page.locator('text="$73"')).toBeVisible()
|
||||
await page.click('button >> text=Upgrade >> nth=0')
|
||||
await page.waitForNavigation()
|
||||
expect(page.url()).toContain('https://checkout.stripe.com')
|
||||
await expect(page.locator('text=$73.00 >> nth=0')).toBeVisible()
|
||||
await expect(page.locator('text=$30.00 >> nth=0')).toBeVisible()
|
||||
await expect(page.locator('text=$4.00 >> nth=0')).toBeVisible()
|
||||
await expect(page.locator('text=user@email.com')).toBeVisible()
|
||||
await addSubscriptionToWorkspace(
|
||||
workspaceId,
|
||||
[
|
||||
{
|
||||
price: process.env.STRIPE_STARTER_PRICE_ID,
|
||||
quantity: 1,
|
||||
},
|
||||
{
|
||||
price: process.env.STRIPE_ADDITIONAL_CHATS_PRICE_ID,
|
||||
quantity: 3,
|
||||
},
|
||||
{
|
||||
price: process.env.STRIPE_ADDITIONAL_STORAGE_PRICE_ID,
|
||||
quantity: 2,
|
||||
},
|
||||
],
|
||||
{ plan: Plan.STARTER, additionalChatsIndex: 3, additionalStorageIndex: 2 }
|
||||
)
|
||||
|
||||
// Update plan with additional quotas
|
||||
await page.goto('/typebots')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await expect(page.locator('text="/ 3,500"')).toBeVisible()
|
||||
await expect(page.locator('text="/ 4 GB"')).toBeVisible()
|
||||
await expect(page.locator('button >> text="3,500"')).toBeVisible()
|
||||
await expect(page.locator('button >> text="4"')).toBeVisible()
|
||||
await expect(page.locator('text="$73"')).toBeVisible()
|
||||
await page.click('button >> text="3,500"')
|
||||
await page.click('button >> text="2,000"')
|
||||
await page.click('button >> text="4"')
|
||||
await page.click('button >> text="6"')
|
||||
await expect(page.locator('text="$47"')).toBeVisible()
|
||||
await page.click('button >> text=Update')
|
||||
await expect(
|
||||
page.locator(
|
||||
'text="Workspace STARTER plan successfully updated 🎉" >> nth=0'
|
||||
)
|
||||
).toBeVisible()
|
||||
|
||||
// Upgrade to PRO
|
||||
await page.click('button >> text="10,000"')
|
||||
await page.click('button >> text="14,000"')
|
||||
await page.click('button >> text="10"')
|
||||
await page.click('button >> text="12"')
|
||||
await expect(page.locator('text="$133"')).toBeVisible()
|
||||
await page.click('button >> text=Upgrade')
|
||||
await expect(
|
||||
page.locator('text="Workspace PRO plan successfully updated 🎉" >> nth=0')
|
||||
).toBeVisible()
|
||||
|
||||
// Go to customer portal
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.click('text="Billing Portal"'),
|
||||
])
|
||||
await expect(page.locator('text="Add payment method"')).toBeVisible()
|
||||
|
||||
// Cancel subscription
|
||||
await page.goto('/typebots')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await expect(page.locator('[data-testid="plan-tag"]')).toHaveText('Pro')
|
||||
await page.click('button >> text="Cancel my subscription"')
|
||||
await expect(page.locator('[data-testid="plan-tag"]')).toHaveText('Free')
|
||||
})
|
||||
|
||||
test('should display invoices', async ({ page }) => {
|
||||
await page.goto('/typebots')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await expect(
|
||||
page.locator('text="No invoices found for this workspace."')
|
||||
).toBeVisible()
|
||||
await page.click('text=Pro workspace', { force: true })
|
||||
|
||||
await page.click('text=Pro workspace')
|
||||
await page.click('text=Starter workspace')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text=Billing & Usage')
|
||||
await expect(page.locator('text="Invoices"')).toBeVisible()
|
||||
await expect(page.locator('text="Wed Jun 01 2022"')).toBeVisible()
|
||||
await expect(page.locator('text="74567541-0001"')).toBeVisible()
|
||||
await expect(page.locator('text="€30.00" >> nth=0')).toBeVisible()
|
||||
})
|
@ -6,13 +6,10 @@ import {
|
||||
import { BubbleBlockType, defaultEmbedBubbleContent } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const pdfSrc = 'https://www.orimi.com/pdf-test.pdf'
|
||||
const siteSrc = 'https://app.cal.com/baptistearno/15min'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Embed bubble block', () => {
|
||||
test.describe('Content settings', () => {
|
||||
test('should import and parse embed correctly', async ({ page }) => {
|
||||
|
@ -7,13 +7,10 @@ import { BubbleBlockType, defaultImageBubbleContent } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import path from 'path'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const unsplashImageSrc =
|
||||
'https://images.unsplash.com/photo-1504297050568-910d24c426d3?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1287&q=80'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Image bubble block', () => {
|
||||
test.describe('Content settings', () => {
|
||||
test('should upload image file correctly', async ({ page }) => {
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { BubbleBlockType, defaultTextBubbleContent } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Text bubble block', () => {
|
||||
test('rich text features should work', async ({ page }) => {
|
||||
|
@ -10,15 +10,12 @@ import {
|
||||
} from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const videoSrc =
|
||||
'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4'
|
||||
const youtubeVideoSrc = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
|
||||
const vimeoVideoSrc = 'https://vimeo.com/649301125'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Video bubble block', () => {
|
||||
test.describe('Content settings', () => {
|
||||
test('should import video url correctly', async ({ page }) => {
|
||||
|
@ -3,7 +3,6 @@ import cuid from 'cuid'
|
||||
import { CollaborationType, Plan, WorkspaceRole } from 'db'
|
||||
import prisma from 'libs/prisma'
|
||||
import { InputBlockType, defaultTextInputOptions } from 'models'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
import {
|
||||
createFolder,
|
||||
createResults,
|
||||
@ -11,8 +10,6 @@ import {
|
||||
parseDefaultGroupWithBlock,
|
||||
} from '../services/database'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Typebot owner', () => {
|
||||
test('Can invite collaborators', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
@ -101,7 +98,7 @@ test.describe('Collaborator', () => {
|
||||
},
|
||||
})
|
||||
await createFolder(guestWorkspaceId, 'Guest folder')
|
||||
await createResults({ typebotId })
|
||||
await createResults({ typebotId, count: 10 })
|
||||
await page.goto(`/typebots`)
|
||||
await page.click("text=Pro user's workspace")
|
||||
await page.click('text=Guest workspace #2')
|
||||
|
@ -2,14 +2,10 @@ import test, { expect } from '@playwright/test'
|
||||
import { InputBlockType, defaultTextInputOptions } from 'models'
|
||||
import {
|
||||
createTypebots,
|
||||
freeWorkspaceId,
|
||||
parseDefaultGroupWithBlock,
|
||||
starterWorkspaceId,
|
||||
} from '../services/database'
|
||||
import path from 'path'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test('should be able to connect custom domain', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
@ -47,16 +43,13 @@ test('should be able to connect custom domain', async ({ page }) => {
|
||||
await expect(page.locator('[aria-label="Remove domain"]')).toBeHidden()
|
||||
})
|
||||
|
||||
test.describe('Free workspace', () => {
|
||||
test.use({
|
||||
storageState: path.join(__dirname, '../freeUser.json'),
|
||||
})
|
||||
test.describe('Starter workspace', () => {
|
||||
test("Add my domain shouldn't be available", async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await createTypebots([
|
||||
{
|
||||
id: typebotId,
|
||||
workspaceId: freeWorkspaceId,
|
||||
workspaceId: starterWorkspaceId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
options: defaultTextInputOptions,
|
||||
|
@ -1,12 +1,9 @@
|
||||
import test, { expect, Page } from '@playwright/test'
|
||||
import cuid from 'cuid'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
import { createFolders, createTypebots } from '../services/database'
|
||||
import { deleteButtonInConfirmDialog } from '../services/selectorUtils'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Dashboard page', () => {
|
||||
test('folders navigation should work', async ({ page }) => {
|
||||
await page.goto('/typebots')
|
||||
@ -79,7 +76,7 @@ test.describe('Dashboard page', () => {
|
||||
|
||||
test.describe('Free user', () => {
|
||||
test.use({
|
||||
storageState: path.join(__dirname, '../freeUser.json'),
|
||||
storageState: path.join(__dirname, '../secondUser.json'),
|
||||
})
|
||||
test("create folder shouldn't be available", async ({ page }) => {
|
||||
await page.goto('/typebots')
|
||||
|
@ -8,9 +8,6 @@ import { defaultTextInputOptions, InputBlockType } from 'models'
|
||||
import path from 'path'
|
||||
import cuid from 'cuid'
|
||||
import { typebotViewer } from '../services/selectorUtils'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Editor', () => {
|
||||
test('Edges connection should work', async ({ page }) => {
|
||||
|
@ -8,9 +8,6 @@ import { defaultChoiceInputOptions, InputBlockType, ItemType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Buttons input block', () => {
|
||||
test('can edit button items', async ({ page }) => {
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { defaultDateInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Date input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { defaultEmailInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Email input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
|
@ -8,9 +8,6 @@ import { defaultFileInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.configure({ mode: 'parallel' })
|
||||
|
||||
@ -61,9 +58,6 @@ test('options should work', async ({ page }) => {
|
||||
})
|
||||
|
||||
test.describe('Free workspace', () => {
|
||||
test.use({
|
||||
storageState: path.join(__dirname, '../../freeUser.json'),
|
||||
})
|
||||
test("shouldn't be able to publish typebot", async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await createTypebots([
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { defaultNumberInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Number input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { defaultPaymentInputOptions, InputBlockType } from 'models'
|
||||
import cuid from 'cuid'
|
||||
import { stripePaymentForm, typebotViewer } from '../../services/selectorUtils'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Payment input block', () => {
|
||||
test('Can configure Stripe account', async ({ page }) => {
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { defaultPhoneInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Phone input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
import { defaultRatingInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const boxSvg = `<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -21,8 +20,6 @@ const boxSvg = `<svg
|
||||
<line x1="12" y1="22.08" x2="12" y2="12"></line>
|
||||
</svg>`
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test('options should work', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await createTypebots([
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { defaultTextInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Text input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
|
@ -6,9 +6,6 @@ import {
|
||||
import { defaultUrlInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Url input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
|
@ -5,9 +5,6 @@ import {
|
||||
} from '../../services/database'
|
||||
import { defaultGoogleAnalyticsOptions, IntegrationBlockType } from 'models'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Google Analytics block', () => {
|
||||
test('its configuration should work', async ({ page }) => {
|
||||
|
@ -3,9 +3,6 @@ import { importTypebotInDatabase } from '../../services/database'
|
||||
import path from 'path'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Google sheets integration', () => {
|
||||
test('Insert row should work', async ({ page }) => {
|
||||
|
@ -3,12 +3,9 @@ import { importTypebotInDatabase } from '../../services/database'
|
||||
import path from 'path'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const typebotId = cuid()
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Send email block', () => {
|
||||
test('its configuration should work', async ({ page }) => {
|
||||
if (
|
||||
|
@ -3,9 +3,6 @@ import { createWebhook, importTypebotInDatabase } from '../../services/database'
|
||||
import path from 'path'
|
||||
import { HttpMethod } from 'models'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Webhook block', () => {
|
||||
test('easy configuration should work', async ({ page }) => {
|
||||
|
@ -3,12 +3,9 @@ import path from 'path'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import { importTypebotInDatabase } from '../../services/database'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const typebotId = cuid()
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Code block', () => {
|
||||
test('code should trigger', async ({ page }) => {
|
||||
await importTypebotInDatabase(
|
||||
|
@ -3,12 +3,9 @@ import path from 'path'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import { importTypebotInDatabase } from '../../services/database'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const typebotId = cuid()
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Condition block', () => {
|
||||
test('its configuration should work', async ({ page }) => {
|
||||
await importTypebotInDatabase(
|
||||
|
@ -3,12 +3,9 @@ import path from 'path'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import { importTypebotInDatabase } from '../../services/database'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const typebotId = cuid()
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Redirect block', () => {
|
||||
test('its configuration should work', async ({ page, context }) => {
|
||||
await importTypebotInDatabase(
|
||||
|
@ -3,12 +3,9 @@ import path from 'path'
|
||||
import { typebotViewer } from '../../services/selectorUtils'
|
||||
import { importTypebotInDatabase } from '../../services/database'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
const typebotId = cuid()
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe('Set variable block', () => {
|
||||
test('its configuration should work', async ({ page }) => {
|
||||
await importTypebotInDatabase(
|
||||
|
@ -3,9 +3,6 @@ import { typebotViewer } from '../../services/selectorUtils'
|
||||
import { importTypebotInDatabase } from '../../services/database'
|
||||
import path from 'path'
|
||||
import cuid from 'cuid'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test('should be configurable', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
|
@ -4,7 +4,6 @@ import { readFileSync } from 'fs'
|
||||
import { defaultTextInputOptions, InputBlockType } from 'models'
|
||||
import { parse } from 'papaparse'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
import {
|
||||
createResults,
|
||||
createTypebots,
|
||||
@ -15,8 +14,6 @@ import { deleteButtonInConfirmDialog } from '../services/selectorUtils'
|
||||
|
||||
const typebotId = cuid()
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test('Submission table header should be parsed correctly', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await importTypebotInDatabase(
|
||||
@ -46,7 +43,7 @@ test('results should be deletable', async ({ page }) => {
|
||||
}),
|
||||
},
|
||||
])
|
||||
await createResults({ typebotId })
|
||||
await createResults({ typebotId, count: 200 })
|
||||
await page.goto(`/typebots/${typebotId}/results`)
|
||||
await selectFirstResults(page)
|
||||
await page.click('text="Delete"')
|
||||
@ -70,7 +67,7 @@ test('submissions table should have infinite scroll', async ({ page }) => {
|
||||
tableWrapper.scrollTo(0, tableWrapper.scrollHeight)
|
||||
})
|
||||
|
||||
await createResults({ typebotId })
|
||||
await createResults({ typebotId, count: 200 })
|
||||
await page.goto(`/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text=content199')).toBeVisible()
|
||||
|
||||
|
@ -2,12 +2,9 @@ import test, { expect } from '@playwright/test'
|
||||
import cuid from 'cuid'
|
||||
import { defaultTextInputOptions } from 'models'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
import { freeWorkspaceId, importTypebotInDatabase } from '../services/database'
|
||||
import { typebotViewer } from '../services/selectorUtils'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Settings page', () => {
|
||||
test.describe('General', () => {
|
||||
test('should reflect change in real-time', async ({ page }) => {
|
||||
@ -123,10 +120,7 @@ test.describe.parallel('Settings page', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Free user', () => {
|
||||
test.use({
|
||||
storageState: path.join(__dirname, '../freeUser.json'),
|
||||
})
|
||||
test.describe('Free workspace', () => {
|
||||
test("can't remove branding", async ({ page }) => {
|
||||
const typebotId = 'free-branding-typebot'
|
||||
await importTypebotInDatabase(
|
||||
|
@ -1,10 +1,7 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
import { typebotViewer } from '../services/selectorUtils'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Templates page', () => {
|
||||
test('From scratch should create a blank typebot', async ({ page }) => {
|
||||
await page.goto('/typebots/create')
|
||||
|
@ -1,7 +1,6 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import cuid from 'cuid'
|
||||
import path from 'path'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
import { importTypebotInDatabase } from '../services/database'
|
||||
import { typebotViewer } from '../services/selectorUtils'
|
||||
|
||||
@ -10,8 +9,6 @@ const hostAvatarUrl =
|
||||
const guestAvatarUrl =
|
||||
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1287&q=80'
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
|
||||
test.describe.parallel('Theme page', () => {
|
||||
test.describe('General', () => {
|
||||
test('should reflect change in real-time', async ({ page }) => {
|
||||
|
@ -1,25 +1,30 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import cuid from 'cuid'
|
||||
import { defaultTextInputOptions, InputBlockType } from 'models'
|
||||
import { mockSessionApiCalls } from 'playwright/services/browser'
|
||||
import { connectedAsOtherUser } from 'playwright/services/browser'
|
||||
import {
|
||||
createTypebots,
|
||||
parseDefaultGroupWithBlock,
|
||||
sharedWorkspaceId,
|
||||
proWorkspaceId,
|
||||
starterWorkspaceId,
|
||||
} from '../services/database'
|
||||
|
||||
const proTypebotId = cuid()
|
||||
const freeTypebotId = cuid()
|
||||
|
||||
test.beforeEach(({ page }) => mockSessionApiCalls(page))
|
||||
const starterTypebotId = cuid()
|
||||
|
||||
test.beforeAll(async () => {
|
||||
await createTypebots([{ id: proTypebotId, name: 'Pro typebot' }])
|
||||
await createTypebots([
|
||||
{
|
||||
id: freeTypebotId,
|
||||
name: 'Shared typebot',
|
||||
workspaceId: sharedWorkspaceId,
|
||||
id: proTypebotId,
|
||||
name: 'Pro typebot',
|
||||
workspaceId: proWorkspaceId,
|
||||
},
|
||||
])
|
||||
await createTypebots([
|
||||
{
|
||||
id: starterTypebotId,
|
||||
name: 'Starter typebot',
|
||||
workspaceId: starterWorkspaceId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
options: {
|
||||
@ -37,38 +42,34 @@ test.beforeAll(async () => {
|
||||
test('can switch between workspaces and access typebot', async ({ page }) => {
|
||||
await page.goto('/typebots')
|
||||
await expect(page.locator('text="Pro typebot"')).toBeVisible()
|
||||
await page.click("text=Pro user's workspace")
|
||||
await page.click('text="Shared workspace"')
|
||||
await page.click('text=Pro workspace')
|
||||
await page.click('text="Starter workspace"')
|
||||
await expect(page.locator('text="Pro typebot"')).toBeHidden()
|
||||
await page.click('text="Shared typebot"')
|
||||
await page.click('text="Starter typebot"')
|
||||
await expect(page.locator('text="Hey there"')).toBeVisible()
|
||||
})
|
||||
|
||||
test('can create and delete a new workspace', async ({ page }) => {
|
||||
await page.goto('/typebots')
|
||||
await page.click("text=Pro user's workspace")
|
||||
await expect(
|
||||
page.locator('text="Pro user\'s workspace" >> nth=1')
|
||||
).toBeHidden()
|
||||
await page.click('text=Pro workspace')
|
||||
await expect(page.locator('text="Pro workspace" >> nth=1')).toBeHidden()
|
||||
await page.click('text=New workspace')
|
||||
await expect(page.locator('text="Pro typebot"')).toBeHidden()
|
||||
await page.click("text=Pro user's workspace")
|
||||
await expect(
|
||||
page.locator('text="Pro user\'s workspace" >> nth=1')
|
||||
).toBeVisible()
|
||||
await page.click("text=John Doe's workspace")
|
||||
await expect(page.locator('text="Pro workspace"')).toBeVisible()
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text="Settings"')
|
||||
await page.click('text="Delete workspace"')
|
||||
await expect(
|
||||
page.locator(
|
||||
"text=Are you sure you want to delete Pro user's workspace workspace?"
|
||||
"text=Are you sure you want to delete John Doe's workspace workspace?"
|
||||
)
|
||||
).toBeVisible()
|
||||
await page.click('text="Delete"')
|
||||
await expect(page.locator('text=Pro typebot')).toBeVisible()
|
||||
await page.click("text=Pro user's workspace")
|
||||
await expect(page.locator('text=Free workspace')).toBeVisible()
|
||||
await page.click('text=Free workspace')
|
||||
await expect(
|
||||
page.locator('text="Pro user\'s workspace" >> nth=1')
|
||||
page.locator('text="John Doe\'s workspace" >> nth=1')
|
||||
).toBeHidden()
|
||||
})
|
||||
|
||||
@ -79,17 +80,14 @@ test('can update workspace info', async ({ page }) => {
|
||||
await page.click('[data-testid="editable-icon"]')
|
||||
await page.fill('input[placeholder="Search..."]', 'building')
|
||||
await page.click('text="🏦"')
|
||||
await page.fill(
|
||||
'input[value="Pro user\'s workspace"]',
|
||||
'My awesome workspace'
|
||||
)
|
||||
await page.fill('input[value="Pro workspace"]', 'My awesome workspace')
|
||||
})
|
||||
|
||||
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="pro-user@email.com"')).toBeVisible()
|
||||
await expect(page.locator('text="user@email.com"')).toBeVisible()
|
||||
await expect(page.locator('button >> text="Invite"')).toBeEnabled()
|
||||
await page.fill(
|
||||
'input[placeholder="colleague@company.com"]',
|
||||
@ -104,7 +102,7 @@ test('can manage members', async ({ page }) => {
|
||||
await expect(page.locator('text="Pending"')).toBeVisible()
|
||||
await page.fill(
|
||||
'input[placeholder="colleague@company.com"]',
|
||||
'free-user@email.com'
|
||||
'other-user@email.com'
|
||||
)
|
||||
await page.click('text="Member" >> nth=0')
|
||||
await page.click('text="Admin"')
|
||||
@ -112,18 +110,15 @@ test('can manage members', async ({ page }) => {
|
||||
await expect(
|
||||
page.locator('input[placeholder="colleague@company.com"]')
|
||||
).toHaveAttribute('value', '')
|
||||
await expect(page.locator('text="free-user@email.com"')).toBeVisible()
|
||||
await expect(page.locator('text="Free user"')).toBeVisible()
|
||||
await expect(page.locator('text="other-user@email.com"')).toBeVisible()
|
||||
await expect(page.locator('text="James Doe"')).toBeVisible()
|
||||
|
||||
// Downgrade admin to member
|
||||
await page.click('text="free-user@email.com"')
|
||||
await page.click('text="other-user@email.com"')
|
||||
await page.click('button >> text="Member"')
|
||||
await expect(page.locator('[data-testid="tag"] >> text="Admin"')).toHaveCount(
|
||||
1
|
||||
)
|
||||
await page.click('text="free-user@email.com"')
|
||||
await page.click('button >> text="Remove"')
|
||||
await expect(page.locator('text="free-user@email.com"')).toBeHidden()
|
||||
await page.click('text="other-user@email.com"')
|
||||
|
||||
await page.click('text="guest@email.com"')
|
||||
await page.click('text="Admin" >> nth=-1')
|
||||
@ -133,19 +128,46 @@ test('can manage members', async ({ page }) => {
|
||||
await page.click('text="guest@email.com"')
|
||||
await page.click('button >> text="Remove"')
|
||||
await expect(page.locator('text="guest@email.com"')).toBeHidden()
|
||||
})
|
||||
|
||||
test("can't edit workspace as a member", async ({ page }) => {
|
||||
await connectedAsOtherUser(page)
|
||||
await page.goto('/typebots')
|
||||
await page.click("text=Pro user's workspace")
|
||||
await page.click('text="Shared workspace"')
|
||||
await page.click('text=Settings & Members')
|
||||
await expect(page.locator('text="Settings"')).toBeHidden()
|
||||
await page.click('text="Members"')
|
||||
await expect(page.locator('text="free-user@email.com"')).toBeVisible()
|
||||
await expect(page.locator('text="other-user@email.com"')).toBeVisible()
|
||||
await expect(
|
||||
page.locator('input[placeholder="colleague@company.com"]')
|
||||
).toBeHidden()
|
||||
await page.click('text="free-user@email.com"')
|
||||
await page.click('text="other-user@email.com"')
|
||||
await expect(page.locator('button >> text="Remove"')).toBeHidden()
|
||||
})
|
||||
|
||||
test("can't add new members when limit is reached", async ({ page }) => {
|
||||
await page.goto('/typebots')
|
||||
await page.click('text="Pro workspace"')
|
||||
await page.click('text="Free workspace"')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text="Members"')
|
||||
await expect(page.locator('button >> text="Invite"')).toBeDisabled()
|
||||
await expect(
|
||||
page.locator(
|
||||
'text="Upgrade your plan to work with more team members, and unlock awesome power features 🚀"'
|
||||
)
|
||||
).toBeVisible()
|
||||
await page.click('text="Free workspace"', { force: true })
|
||||
await page.click('text="Free workspace"')
|
||||
await page.click('text="Starter workspace"')
|
||||
await page.click('text=Settings & Members')
|
||||
await page.click('text="Members"')
|
||||
await page.fill(
|
||||
'input[placeholder="colleague@company.com"]',
|
||||
'guest@email.com'
|
||||
)
|
||||
await page.click('button >> text="Invite"')
|
||||
await expect(
|
||||
page.locator(
|
||||
'text="Upgrade your plan to work with more team members, and unlock awesome power features 🚀"'
|
||||
)
|
||||
).toBeVisible()
|
||||
await expect(page.locator('button >> text="Invite"')).toBeDisabled()
|
||||
})
|
||||
|
Reference in New Issue
Block a user