Skip to content

Commit

Permalink
Add e2e tests for account
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Dec 28, 2021
1 parent e10fe1a commit 8c826fc
Show file tree
Hide file tree
Showing 13 changed files with 321 additions and 302 deletions.
8 changes: 6 additions & 2 deletions apps/builder/components/account/BillingSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Stack, Heading, HStack, Button, Text } from '@chakra-ui/react'
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
import { useUser } from 'contexts/UserContext'
import { Plan } from 'db'
import React from 'react'
import { SubscriptionTag } from './SubscriptionTag'

Expand All @@ -17,10 +18,13 @@ export const BillingSection = () => {
<SubscriptionTag plan={user?.plan} />
</HStack>
{user?.stripeId && (
<Button as={NextChakraLink} href="test">
Billing portal
<Button as={NextChakraLink} href="/api/stripe/customer-portal">
Manage my subscription
</Button>
)}
{user?.plan === Plan.FREE && (
<Button colorScheme="blue">Upgrade</Button>
)}
</Stack>
</Stack>
)
Expand Down
Binary file added apps/builder/cypress/fixtures/avatar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 22 additions & 45 deletions apps/builder/cypress/plugins/database.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PrismaClient } from '.prisma/client'
import { Block, StartBlock, StepType } from 'bot-engine'
import { parseNewTypebot } from 'bot-engine'
import { Plan, PrismaClient } from 'db'

const prisma = new PrismaClient()

Expand All @@ -16,7 +16,13 @@ const createUsers = () =>
prisma.user.createMany({
data: [
{ id: 'test1', email: 'test1@gmail.com', emailVerified: new Date() },
{ id: 'test2', email: 'test2@gmail.com', emailVerified: new Date() },
{
id: 'test2',
email: 'test2@gmail.com',
emailVerified: new Date(),
plan: Plan.PRO,
stripeId: 'stripe-test2',
},
],
})

Expand All @@ -26,52 +32,23 @@ const createFolders = () =>
})

const createTypebots = () => {
const startBlock: StartBlock = {
graphCoordinates: { x: 0, y: 0 },
id: 'start-block',
steps: [
{
id: 'start-step',
blockId: 'start-block',
type: StepType.START,
label: 'Start',
},
],
title: 'Home',
}
const blocks: Block[] = [
{
id: 'block1',
title: 'Block1',
graphCoordinates: { x: 150, y: 150 },
steps: [
{ id: 'step1', blockId: 'block1', type: StepType.TEXT, content: '' },
{
id: 'step2',
blockId: 'block1',
type: StepType.DATE_PICKER,
content: '',
},
],
},
{
id: 'block2',
title: 'Block2',
graphCoordinates: { x: 300, y: 300 },
steps: [
{ id: 'step1', blockId: 'block2', type: StepType.TEXT, content: '' },
],
},
]
return prisma.typebot.createMany({
data: [
{ id: 'typebot1', name: 'Typebot #1', ownerId: 'test2', startBlock },
{
...parseNewTypebot({
name: 'Typebot #1',
ownerId: 'test2',
folderId: null,
}),
id: 'typebot1',
},
{
...parseNewTypebot({
name: 'Typebot #2',
ownerId: 'test2',
folderId: null,
}),
id: 'typebot2',
name: 'Typebot #2',
ownerId: 'test2',
startBlock,
blocks,
},
],
})
Expand Down
1 change: 1 addition & 0 deletions apps/builder/cypress/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ declare global {

// Import commands.js using ES2015 syntax:
import '@testing-library/cypress/add-commands'
import 'cypress-file-upload'
import './commands'

// Alternatively you can use CommonJS syntax:
Expand Down
67 changes: 67 additions & 0 deletions apps/builder/cypress/tests/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
describe('Dashboard page', () => {
before(() => {
cy.intercept({
url: 'https://s3.eu-west-3.amazonaws.com/typebot',
method: 'POST',
}).as('postImage')
cy.intercept({ url: '/api/auth/session?update', method: 'GET' }).as(
'getUpdatedSession'
)
})

beforeEach(() => {
cy.task('seed')
cy.signOut()
})

it('should edit user info properly', () => {
cy.signIn('test1@gmail.com')
cy.visit('/account')
cy.findByRole('button', { name: 'Save' }).should('not.exist')
cy.findByRole('textbox', { name: 'Email address' }).should(
'have.attr',
'disabled'
)
cy.findByRole('textbox', { name: 'Name' })
.should('have.value', '')
.type('John Doe')

cy.findByRole('img').should('not.have.attr', 'src')
cy.findByLabelText('Change photo').attachFile('avatar.jpg')
cy.wait('@postImage')
cy.findByRole('img')
.should('have.attr', 'src')
.should(
'include',
'https://s3.eu-west-3.amazonaws.com/typebot/test1/avatar'
)
cy.findByRole('button', { name: 'Save' }).should('exist').click()
cy.wait('@getUpdatedSession')
cy.reload()
cy.findByRole('textbox', { name: 'Name' }).should('have.value', 'John Doe')
cy.findByRole('img')
.should('have.attr', 'src')
.should(
'include',
'https://s3.eu-west-3.amazonaws.com/typebot/test1/avatar'
)
cy.findByRole('button', { name: 'Save' }).should('not.exist')
})

it('should display valid plans', () => {
cy.signIn('test1@gmail.com')
cy.visit('/account')
cy.findByText('Free plan').should('exist')
cy.findByRole('link', { name: 'Manage my subscription' }).should(
'not.exist'
)
cy.findByRole('button', { name: 'Upgrade' }).should('exist')
cy.signOut()
cy.signIn('test2@gmail.com')
cy.visit('/account')
cy.findByText('Pro plan').should('exist')
cy.findByRole('link', { name: 'Manage my subscription' })
.should('have.attr', 'href')
.should('include', 'customer-portal')
})
})
2 changes: 1 addition & 1 deletion apps/builder/cypress/tests/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('BoardPage', () => {

it('steps should be droppable', () => {
cy.signIn('test2@gmail.com')
cy.visit('/typebots/typebot1')
cy.visit('/typebots/typebot1/edit')
// Can't find an easy way to implement this
})
})
2 changes: 1 addition & 1 deletion apps/builder/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"include": ["**/*.ts"],
"exclude": [],
"compilerOptions": {
"types": ["cypress", "@testing-library/cypress"],
"types": ["cypress", "@testing-library/cypress", "cypress-file-upload"],
"lib": ["es2015", "dom"],
"target": "es5",
"isolatedModules": false,
Expand Down
1 change: 1 addition & 0 deletions apps/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"@types/testing-library__cypress": "^5.0.9",
"@typescript-eslint/eslint-plugin": "^5.8.0",
"cypress": "^9.2.0",
"cypress-file-upload": "^5.0.8",
"cypress-social-logins": "^1.13.0",
"eslint": "<8.0.0",
"eslint-config-next": "12.0.7",
Expand Down
32 changes: 32 additions & 0 deletions apps/builder/pages/api/stripe/customer-portal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { User } from 'db'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import Stripe from 'stripe'

const createCheckoutSession = async (
req: NextApiRequest,
res: NextApiResponse
) => {
const session = await getSession({ req })
if (!session?.user)
return res.status(401).json({ message: 'Not authenticated' })
const user = session.user as User
if (!user.stripeId)
return res.status(401).json({ message: 'Not authenticated' })
if (req.method === 'GET') {
if (!process.env.STRIPE_SECRET_KEY)
throw Error('STRIPE_SECRET_KEY var is missing')
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2020-08-27',
})
const session = await stripe.billingPortal.sessions.create({
customer: user.stripeId,
return_url: `${req.headers.origin}/account`,
})
res.status(201).redirect(session.url)
}
return methodNotAllowed(res)
}

export default createCheckoutSession
40 changes: 4 additions & 36 deletions apps/builder/pages/api/typebots.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import {
BackgroundType,
Settings,
StartBlock,
StepType,
Theme,
} from 'bot-engine'
import { Typebot, User } from 'db'
import { parseNewTypebot } from 'bot-engine'
import { User } from 'db'
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
Expand All @@ -30,35 +24,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
return res.send({ typebots })
}
if (req.method === 'POST') {
const data = JSON.parse(req.body) as Typebot
const startBlock: StartBlock = {
id: 'start-block',
title: 'Start',
graphCoordinates: { x: 0, y: 0 },
steps: [
{
id: 'start-step',
blockId: 'start-block',
label: 'Form starts here',
type: StepType.START,
},
],
}
const theme: Theme = {
general: {
font: 'Open Sans',
background: { type: BackgroundType.NONE, content: '#ffffff' },
},
}
const settings: Settings = {
typingEmulation: {
enabled: true,
speed: 300,
maxDelay: 1.5,
},
}
const data = JSON.parse(req.body)
const typebot = await prisma.typebot.create({
data: { ...data, ownerId: user.id, startBlock, theme, settings },
data: parseNewTypebot({ ownerId: user.id, ...data }),
})
return res.send(typebot)
}
Expand Down
1 change: 1 addition & 0 deletions packages/bot-engine/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './components/TypebotViewer'
export * from './models'
export { parseNewTypebot } from './services/utils'
50 changes: 49 additions & 1 deletion packages/bot-engine/src/services/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,55 @@
import { Step, TextStep, StepType, TextInputStep } from '../models'
import { Prisma } from 'db'
import {
Step,
TextStep,
StepType,
TextInputStep,
BackgroundType,
Settings,
StartBlock,
Theme,
} from '../models'

export const isTextStep = (step: Step): step is TextStep =>
step.type === StepType.TEXT

export const isTextInputStep = (step: Step): step is TextInputStep =>
step.type === StepType.TEXT_INPUT

export const parseNewTypebot = ({
ownerId,
folderId,
name,
}: {
ownerId: string
folderId: string | null
name: string
}): Prisma.TypebotUncheckedCreateInput => {
const startBlock: StartBlock = {
id: 'start-block',
title: 'Start',
graphCoordinates: { x: 0, y: 0 },
steps: [
{
id: 'start-step',
blockId: 'start-block',
label: 'Form starts here',
type: StepType.START,
},
],
}
const theme: Theme = {
general: {
font: 'Open Sans',
background: { type: BackgroundType.NONE, content: '#ffffff' },
},
}
const settings: Settings = {
typingEmulation: {
enabled: true,
speed: 300,
maxDelay: 1.5,
},
}
return { folderId, name, ownerId, startBlock, theme, settings }
}
Loading

0 comments on commit 8c826fc

Please sign in to comment.