📦 Upgrade packages
This commit is contained in:
13
.github/workflows/auto-move-project-card.yml
vendored
13
.github/workflows/auto-move-project-card.yml
vendored
@ -1,13 +0,0 @@
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, ready_for_review, synchronize]
|
||||
|
||||
jobs:
|
||||
move-linked-issues:
|
||||
runs-on: ubuntu-latest
|
||||
name: Move linked issues to In Review column
|
||||
steps:
|
||||
- uses: rharter/github-move-linked-project-cards@v0.1.0
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
column: Reviewing 👀
|
41
.github/workflows/playwright.yml
vendored
41
.github/workflows/playwright.yml
vendored
@ -1,41 +0,0 @@
|
||||
name: Playwright Tests
|
||||
|
||||
on:
|
||||
deployment_status:
|
||||
|
||||
jobs:
|
||||
test-builder:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.deployment_status.state == 'success' && contains(github.event.deployment_status.environment, 'builder')}}
|
||||
steps:
|
||||
- name: Log Info
|
||||
run: echo ${{ github.event.deployment_status.target_url }} && echo ${{ github.event.deployment }} && echo ${{ github.event.deployment_status.environment }}
|
||||
- uses: actions/checkout@v2
|
||||
- uses: pnpm/action-setup@v2.2.2
|
||||
- name: Install dependencies
|
||||
run: pnpm i --frozen-lockfile
|
||||
- name: Build dependencies
|
||||
run: pnpm turbo run build --filter="builder^..."
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
- name: Run tests
|
||||
working-directory: ./apps/builder
|
||||
run: pnpm test
|
||||
env:
|
||||
PLAYWRIGHT_BUILDER_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
|
||||
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
|
||||
SMTP_HOST: smtp.ethereal.email
|
||||
SMTP_PORT: 587
|
||||
SMTP_SECURE: false
|
||||
SMTP_USERNAME: tobin.tillman65@ethereal.email
|
||||
SMTP_PASSWORD: Ty9BcwCBrK6w8AG2hx
|
||||
STRIPE_TEST_PUBLIC_KEY: pk_test_fYwf5fyL66hiRIkFVcpStukl00K1MTPPmG
|
||||
STRIPE_TEST_SECRET_KEY: ${{ secrets.STRIPE_TEST_SECRET_KEY }}
|
||||
ENCRYPTION_SECRET: ${{ secrets.ENCRYPTION_SECRET }}
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: playwright-results
|
||||
path: ./apps/builder/playwright-report
|
56
.github/workflows/publish_docker_images.yml
vendored
56
.github/workflows/publish_docker_images.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: Publish Docker images
|
||||
name: Build Docker images
|
||||
|
||||
on:
|
||||
create:
|
||||
@ -9,32 +9,34 @@ on:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
push_builder:
|
||||
name: Builder
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
app: ['builder', 'viewer']
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Extract Builder meta
|
||||
id: builder-meta
|
||||
- name: Extract existing image metadata
|
||||
id: ${{ matrix.app }}-meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: baptistearno/typebot-builder
|
||||
images: baptistearno/typebot-${{ matrix.app }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
if: github.event_name != 'pull_request'
|
||||
- if: github.event_name != 'pull_request'
|
||||
name: Log in to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push builder image
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
@ -42,38 +44,4 @@ jobs:
|
||||
tags: ${{ steps.builder-meta.outputs.tags }}
|
||||
labels: ${{ steps.builder-meta.outputs.labels }}
|
||||
build-args: |
|
||||
SCOPE=builder
|
||||
push_viewer:
|
||||
name: Viewer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Extract Viewer meta
|
||||
id: viewer-meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: baptistearno/typebot-viewer
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push viewer image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.viewer-meta.outputs.tags }}
|
||||
labels: ${{ steps.viewer-meta.outputs.labels }}
|
||||
build-args: |
|
||||
SCOPE=viewer
|
||||
SCOPE=${{ matrix.app }}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { NextChakraLink } from '../nextChakra/NextChakraLink'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { TextLink } from 'components/shared/TextLink'
|
||||
|
||||
type Props = {
|
||||
type: 'register' | 'signin'
|
||||
@ -10,16 +10,11 @@ export const AuthSwitcher = ({ type }: Props) => (
|
||||
{type === 'signin' ? (
|
||||
<Text>
|
||||
Don't have an account?{' '}
|
||||
<NextChakraLink href="/register" color="blue.500" textDecor="underline">
|
||||
Sign up for free
|
||||
</NextChakraLink>
|
||||
<TextLink href="/register">Sign up for free</TextLink>
|
||||
</Text>
|
||||
) : (
|
||||
<Text>
|
||||
Already have an account?{' '}
|
||||
<NextChakraLink href="/signin" color="blue.500" textDecor="underline">
|
||||
Sign in
|
||||
</NextChakraLink>
|
||||
Already have an account? <TextLink href="/signin">Sign in</TextLink>
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
|
@ -19,9 +19,9 @@ import {
|
||||
import { DividerWithText } from './DividerWithText'
|
||||
import { SocialLoginButtons } from './SocialLoginButtons'
|
||||
import { useRouter } from 'next/router'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { BuiltInProviderType } from 'next-auth/providers'
|
||||
import { useToast } from 'components/shared/hooks/useToast'
|
||||
import { TextLink } from 'components/shared/TextLink'
|
||||
|
||||
type Props = {
|
||||
defaultEmail?: string
|
||||
@ -76,14 +76,12 @@ export const SignInForm = ({
|
||||
return (
|
||||
<Text>
|
||||
You need to{' '}
|
||||
<NextChakraLink
|
||||
<TextLink
|
||||
href="https://docs.typebot.io/self-hosting/configuration"
|
||||
isExternal
|
||||
color="blue.400"
|
||||
textDecor="underline"
|
||||
>
|
||||
configure at least one auth provider
|
||||
</NextChakraLink>{' '}
|
||||
</TextLink>{' '}
|
||||
(Email, Google, GitHub, Facebook or Azure AD).
|
||||
</Text>
|
||||
)
|
||||
|
@ -12,7 +12,6 @@ import {
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react'
|
||||
import { TypebotLogo } from 'assets/logos'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import {
|
||||
ChevronLeftIcon,
|
||||
HardDriveIcon,
|
||||
@ -27,6 +26,7 @@ import { EmojiOrImageIcon } from 'components/shared/EmojiOrImageIcon'
|
||||
import { WorkspaceSettingsModal } from './WorkspaceSettingsModal'
|
||||
import { isNotDefined } from 'utils'
|
||||
import { PlanTag } from 'components/shared/PlanTag'
|
||||
import Link from 'next/link'
|
||||
|
||||
export const DashboardHeader = () => {
|
||||
const { user } = useUser()
|
||||
@ -52,13 +52,9 @@ export const DashboardHeader = () => {
|
||||
maxW="1000px"
|
||||
flex="1"
|
||||
>
|
||||
<NextChakraLink
|
||||
className="w-24"
|
||||
href="/typebots"
|
||||
data-testid="typebot-logo"
|
||||
>
|
||||
<Link href="/typebots" data-testid="typebot-logo">
|
||||
<TypebotLogo w="30px" />
|
||||
</NextChakraLink>
|
||||
</Link>
|
||||
<HStack>
|
||||
{user && workspace && (
|
||||
<WorkspaceSettingsModal
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Button } from '@chakra-ui/react'
|
||||
import { ChevronLeftIcon } from 'assets/icons'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { useTypebotDnd } from 'contexts/TypebotDndContext'
|
||||
import Link from 'next/link'
|
||||
import React, { useMemo } from 'react'
|
||||
|
||||
export const BackButton = ({ id }: { id: string | null }) => {
|
||||
@ -17,7 +17,7 @@ export const BackButton = ({ id }: { id: string | null }) => {
|
||||
const handleMouseLeave = () => setMouseOverFolderId(undefined)
|
||||
return (
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={id ? `/typebots/folders/${id}` : '/typebots'}
|
||||
leftIcon={<ChevronLeftIcon />}
|
||||
variant={'outline'}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { HStack, Stack, Text } from '@chakra-ui/react'
|
||||
import { StripeClimateLogo } from 'assets/logos/StripeClimateLogo'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { ChangePlanForm } from 'components/shared/ChangePlanForm'
|
||||
import { TextLink } from 'components/shared/TextLink'
|
||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||
import { Plan } from 'db'
|
||||
import React from 'react'
|
||||
@ -33,13 +33,9 @@ export const BillingContent = () => {
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
Typebot is contributing 1% of your subscription to remove CO₂ from
|
||||
the atmosphere.{' '}
|
||||
<NextChakraLink
|
||||
href="https://climate.stripe.com/5VCRAq"
|
||||
isExternal
|
||||
textDecor="underline"
|
||||
>
|
||||
<TextLink href="https://climate.stripe.com/5VCRAq" isExternal>
|
||||
More info.
|
||||
</NextChakraLink>
|
||||
</TextLink>
|
||||
</Text>
|
||||
</HStack>
|
||||
{workspace.plan !== Plan.CUSTOM &&
|
||||
|
@ -14,8 +14,8 @@ import {
|
||||
Text,
|
||||
} from '@chakra-ui/react'
|
||||
import { DownloadIcon, FileIcon } from 'assets/icons'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { Workspace } from 'db'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { useInvoicesQuery } from './queries/useInvoicesQuery'
|
||||
|
||||
@ -54,12 +54,12 @@ export const InvoicesList = ({ workspace }: Props) => {
|
||||
<Td>{getFormattedPrice(invoice.amount, invoice.currency)}</Td>
|
||||
<Td>
|
||||
<IconButton
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
size="xs"
|
||||
icon={<DownloadIcon />}
|
||||
variant="outline"
|
||||
href={invoice.url}
|
||||
isExternal
|
||||
target="_blank"
|
||||
aria-label={'Download invoice'}
|
||||
/>
|
||||
</Td>
|
||||
|
@ -1,47 +0,0 @@
|
||||
import { PropsWithChildren } from 'react'
|
||||
import NextLink from 'next/link'
|
||||
import { LinkProps as NextLinkProps } from 'next/dist/client/link'
|
||||
import {
|
||||
Link as ChakraLink,
|
||||
LinkProps as ChakraLinkProps,
|
||||
} from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
|
||||
export type NextChakraLinkProps = PropsWithChildren<
|
||||
NextLinkProps & Omit<ChakraLinkProps, 'href'>
|
||||
>
|
||||
|
||||
export const NextChakraLink = React.forwardRef<
|
||||
HTMLAnchorElement,
|
||||
NextChakraLinkProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
href,
|
||||
replace,
|
||||
scroll,
|
||||
shallow,
|
||||
prefetch,
|
||||
children,
|
||||
locale,
|
||||
...chakraProps
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<NextLink
|
||||
passHref={true}
|
||||
href={href}
|
||||
replace={replace}
|
||||
scroll={scroll}
|
||||
shallow={shallow}
|
||||
prefetch={prefetch}
|
||||
locale={locale}
|
||||
>
|
||||
<ChakraLink ref={ref} {...chakraProps}>
|
||||
{children}
|
||||
</ChakraLink>
|
||||
</NextLink>
|
||||
)
|
||||
}
|
||||
)
|
@ -248,10 +248,9 @@ const IndeterminateCheckbox = React.forwardRef(
|
||||
const resolvedRef: any = ref || defaultRef
|
||||
|
||||
return (
|
||||
<Flex justify="center" data-testid="checkbox">
|
||||
<Flex justify="center" data-testid="checkbox" {...rest}>
|
||||
<Checkbox
|
||||
ref={resolvedRef}
|
||||
{...rest}
|
||||
isIndeterminate={indeterminate}
|
||||
isChecked={checked}
|
||||
/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Stack, HStack, Text } from '@chakra-ui/react'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { useUser } from 'contexts/UserContext'
|
||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||
import { Plan } from 'db'
|
||||
import { useToast } from '../hooks/useToast'
|
||||
import { TextLink } from '../TextLink'
|
||||
import { ProPlanContent } from './ProPlanContent'
|
||||
import { pay } from './queries/updatePlan'
|
||||
import { useCurrentSubscriptionInfo } from './queries/useCurrentSubscriptionInfo'
|
||||
@ -89,13 +89,9 @@ export const ChangePlanForm = () => {
|
||||
</HStack>
|
||||
<Text color="gray.500">
|
||||
Need custom limits? Specific features?{' '}
|
||||
<NextChakraLink
|
||||
href={'https://typebot.io/enterprise-lead-form'}
|
||||
isExternal
|
||||
textDecor="underline"
|
||||
>
|
||||
<TextLink href={'https://typebot.io/enterprise-lead-form'} isExternal>
|
||||
Let's chat!
|
||||
</NextChakraLink>
|
||||
</TextLink>
|
||||
</Text>
|
||||
</Stack>
|
||||
)
|
||||
|
@ -13,9 +13,9 @@ import {
|
||||
Flex,
|
||||
} from '@chakra-ui/react'
|
||||
import { GoogleLogo } from 'assets/logos'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { Info } from 'components/shared/Info'
|
||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { getGoogleSheetsConsentScreenUrl } from 'services/integrations'
|
||||
|
||||
@ -53,7 +53,7 @@ export const GoogleSheetConnectModal = ({
|
||||
/>
|
||||
<Flex>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
leftIcon={<GoogleLogo />}
|
||||
data-testid="google"
|
||||
isLoading={['loading', 'authenticated'].includes(status)}
|
||||
|
@ -18,12 +18,11 @@ import { CredentialsType, StripeCredentialsData } from 'models'
|
||||
import React, { useState } from 'react'
|
||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||
import { Input } from 'components/shared/Textbox'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { MoreInfoTooltip } from 'components/shared/MoreInfoTooltip'
|
||||
import { ExternalLinkIcon } from 'assets/icons'
|
||||
import { createCredentials } from 'services/credentials'
|
||||
import { omit } from 'utils'
|
||||
import { useToast } from 'components/shared/hooks/useToast'
|
||||
import { TextLink } from 'components/shared/TextLink'
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean
|
||||
@ -157,13 +156,9 @@ export const StripeConfigModal = ({
|
||||
|
||||
<Text>
|
||||
(You can find your keys{' '}
|
||||
<NextChakraLink
|
||||
href="https://dashboard.stripe.com/apikeys"
|
||||
isExternal
|
||||
textDecor="underline"
|
||||
>
|
||||
here <ExternalLinkIcon />
|
||||
</NextChakraLink>
|
||||
<TextLink href="https://dashboard.stripe.com/apikeys" isExternal>
|
||||
here
|
||||
</TextLink>
|
||||
)
|
||||
</Text>
|
||||
</Stack>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { HStack, IconButton, Input } from '@chakra-ui/react'
|
||||
import { ExternalLinkIcon } from 'assets/icons'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { useToast } from 'components/shared/hooks/useToast'
|
||||
import { SearchableDropdown } from 'components/shared/SearchableDropdown'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMemo } from 'react'
|
||||
import { useTypebots } from 'services/typebots'
|
||||
@ -54,7 +54,7 @@ export const TypebotsDropdown = ({
|
||||
<IconButton
|
||||
aria-label="Navigate to typebot"
|
||||
icon={<ExternalLinkIcon />}
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={`/typebots/${currentTypebot?.id}/edit?parentId=${query.typebotId}`}
|
||||
/>
|
||||
)}
|
||||
|
37
apps/builder/components/shared/TextLink.tsx
Normal file
37
apps/builder/components/shared/TextLink.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import Link, { LinkProps } from 'next/link'
|
||||
import React from 'react'
|
||||
import { chakra, HStack, TextProps } from '@chakra-ui/react'
|
||||
import { ExternalLinkIcon } from 'assets/icons'
|
||||
|
||||
type TextLinkProps = LinkProps & TextProps & { isExternal?: boolean }
|
||||
|
||||
export const TextLink = ({
|
||||
children,
|
||||
href,
|
||||
shallow,
|
||||
replace,
|
||||
scroll,
|
||||
prefetch,
|
||||
isExternal,
|
||||
...textProps
|
||||
}: TextLinkProps) => (
|
||||
<Link
|
||||
href={href}
|
||||
shallow={shallow}
|
||||
replace={replace}
|
||||
scroll={scroll}
|
||||
prefetch={prefetch}
|
||||
target={isExternal ? '_blank' : undefined}
|
||||
>
|
||||
<chakra.span textDecor="underline" display="inline-block" {...textProps}>
|
||||
{isExternal ? (
|
||||
<HStack spacing={1}>
|
||||
<chakra.span>{children}</chakra.span>
|
||||
<ExternalLinkIcon />
|
||||
</HStack>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</chakra.span>
|
||||
</Link>
|
||||
)
|
@ -8,7 +8,6 @@ import {
|
||||
Text,
|
||||
} from '@chakra-ui/react'
|
||||
import { BuoyIcon, ChevronLeftIcon, RedoIcon, UndoIcon } from 'assets/icons'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { RightPanel, useEditor } from 'contexts/EditorContext'
|
||||
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||
import { useRouter } from 'next/router'
|
||||
@ -20,6 +19,7 @@ import { CollaborationMenuButton } from './CollaborationMenuButton'
|
||||
import { EditableTypebotName } from './EditableTypebotName'
|
||||
import { getBubbleActions } from 'typebot-js'
|
||||
import { isCloudProdInstance } from 'services/utils'
|
||||
import Link from 'next/link'
|
||||
|
||||
export const headerHeight = 56
|
||||
|
||||
@ -71,7 +71,7 @@ export const TypebotHeader = () => {
|
||||
right={{ base: 280, xl: 0 }}
|
||||
>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={`/typebots/${typebot?.id}/edit`}
|
||||
colorScheme={router.pathname.includes('/edit') ? 'blue' : 'gray'}
|
||||
variant={router.pathname.includes('/edit') ? 'outline' : 'ghost'}
|
||||
@ -80,7 +80,7 @@ export const TypebotHeader = () => {
|
||||
Flow
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={`/typebots/${typebot?.id}/theme`}
|
||||
colorScheme={router.pathname.endsWith('theme') ? 'blue' : 'gray'}
|
||||
variant={router.pathname.endsWith('theme') ? 'outline' : 'ghost'}
|
||||
@ -89,7 +89,7 @@ export const TypebotHeader = () => {
|
||||
Theme
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={`/typebots/${typebot?.id}/settings`}
|
||||
colorScheme={router.pathname.endsWith('settings') ? 'blue' : 'gray'}
|
||||
variant={router.pathname.endsWith('settings') ? 'outline' : 'ghost'}
|
||||
@ -98,7 +98,7 @@ export const TypebotHeader = () => {
|
||||
Settings
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={`/typebots/${typebot?.id}/share`}
|
||||
colorScheme={router.pathname.endsWith('share') ? 'blue' : 'gray'}
|
||||
variant={router.pathname.endsWith('share') ? 'outline' : 'ghost'}
|
||||
@ -108,7 +108,7 @@ export const TypebotHeader = () => {
|
||||
</Button>
|
||||
{typebot?.publishedTypebotId && (
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
href={`/typebots/${typebot?.id}/results`}
|
||||
colorScheme={router.pathname.includes('results') ? 'blue' : 'gray'}
|
||||
variant={router.pathname.includes('results') ? 'outline' : 'ghost'}
|
||||
@ -127,7 +127,7 @@ export const TypebotHeader = () => {
|
||||
>
|
||||
<HStack alignItems="center" spacing={3}>
|
||||
<IconButton
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
aria-label="Navigate back"
|
||||
icon={<ChevronLeftIcon fontSize={25} />}
|
||||
href={
|
||||
|
@ -8,59 +8,59 @@
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"test": "pnpm playwright test",
|
||||
"test:open": "NO_RETRIES=1 pnpm playwright test --debug"
|
||||
"test:report": "pnpm playwright show-report"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/css-reset": "2.0.8",
|
||||
"@chakra-ui/react": "2.3.5",
|
||||
"@codemirror/lang-css": "6.0.0",
|
||||
"@codemirror/lang-html": "6.1.2",
|
||||
"@codemirror/lang-javascript": "6.1.0",
|
||||
"@codemirror/lang-json": "6.0.0",
|
||||
"@chakra-ui/react": "2.3.6",
|
||||
"@codemirror/lang-css": "6.0.1",
|
||||
"@codemirror/lang-html": "6.1.3",
|
||||
"@codemirror/lang-javascript": "6.1.1",
|
||||
"@codemirror/lang-json": "6.0.1",
|
||||
"@codemirror/lint": "6.0.0",
|
||||
"@codemirror/state": "6.1.2",
|
||||
"@dnd-kit/core": "6.0.5",
|
||||
"@dnd-kit/sortable": "7.0.1",
|
||||
"@dnd-kit/utilities": "3.2.0",
|
||||
"@emotion/react": "11.10.4",
|
||||
"@emotion/styled": "11.10.4",
|
||||
"@emotion/react": "11.10.5",
|
||||
"@emotion/styled": "11.10.5",
|
||||
"@giphy/js-fetch-api": "4.4.0",
|
||||
"@giphy/js-types": "4.2.1",
|
||||
"@giphy/react-components": "6.2.0",
|
||||
"@googleapis/drive": "3.0.1",
|
||||
"@sentry/nextjs": "7.15.0",
|
||||
"@stripe/stripe-js": "1.41.0",
|
||||
"@tanstack/react-table": "8.5.15",
|
||||
"@udecode/plate-basic-marks": "18.2.0",
|
||||
"@googleapis/drive": "4.0.0",
|
||||
"@sentry/nextjs": "7.17.3",
|
||||
"@stripe/stripe-js": "1.42.1",
|
||||
"@tanstack/react-table": "8.5.22",
|
||||
"@udecode/plate-basic-marks": "18.7.0",
|
||||
"@udecode/plate-common": "^7.0.2",
|
||||
"@udecode/plate-core": "18.2.0",
|
||||
"@udecode/plate-link": "18.2.0",
|
||||
"@udecode/plate-serializer-html": "18.2.0",
|
||||
"@udecode/plate-ui-link": "18.2.0",
|
||||
"@udecode/plate-ui-toolbar": "18.2.0",
|
||||
"aws-sdk": "2.1233.0",
|
||||
"@udecode/plate-core": "18.7.0",
|
||||
"@udecode/plate-link": "18.7.0",
|
||||
"@udecode/plate-serializer-html": "18.7.0",
|
||||
"@udecode/plate-ui-link": "18.7.0",
|
||||
"@udecode/plate-ui-toolbar": "18.7.0",
|
||||
"aws-sdk": "2.1245.0",
|
||||
"bot-engine": "workspace:*",
|
||||
"browser-image-compression": "2.0.0",
|
||||
"canvas-confetti": "1.5.1",
|
||||
"canvas-confetti": "1.6.0",
|
||||
"codemirror": "6.0.1",
|
||||
"cuid": "2.1.8",
|
||||
"deep-object-diff": "1.1.7",
|
||||
"dequal": "2.0.3",
|
||||
"emojilib": "3.0.7",
|
||||
"focus-visible": "5.2.0",
|
||||
"framer-motion": "7.5.3",
|
||||
"google-auth-library": "8.5.2",
|
||||
"framer-motion": "7.6.4",
|
||||
"google-auth-library": "8.6.0",
|
||||
"google-spreadsheet": "3.3.0",
|
||||
"got": "12.5.2",
|
||||
"htmlparser2": "8.0.1",
|
||||
"immer": "9.0.15",
|
||||
"immer": "9.0.16",
|
||||
"js-video-url-parser": "0.5.1",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"kbar": "0.1.0-beta.36",
|
||||
"micro": "9.4.1",
|
||||
"micro-cors": "0.1.1",
|
||||
"minio": "7.0.32",
|
||||
"next": "12.3.1",
|
||||
"next": "13.0.1",
|
||||
"next-auth": "4.12.3",
|
||||
"nodemailer": "6.8.0",
|
||||
"nprogress": "0.2.0",
|
||||
@ -74,7 +74,7 @@
|
||||
"slate-history": "0.66.0",
|
||||
"slate-hyperscript": "0.77.0",
|
||||
"slate-react": "0.83.2",
|
||||
"stripe": "10.14.0",
|
||||
"stripe": "10.15.0",
|
||||
"styled-components": "5.3.6",
|
||||
"svg-round-corners": "0.4.1",
|
||||
"swr": "1.3.0",
|
||||
@ -85,7 +85,7 @@
|
||||
"@faire/mjml-react": "2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.19.3",
|
||||
"@babel/core": "7.19.6",
|
||||
"@chakra-ui/styled-system": "2.3.4",
|
||||
"@playwright/test": "1.27.1",
|
||||
"@types/canvas-confetti": "1.4.3",
|
||||
@ -93,24 +93,25 @@
|
||||
"@types/jsonwebtoken": "8.5.9",
|
||||
"@types/micro-cors": "0.1.2",
|
||||
"@types/minio": "7.0.14",
|
||||
"@types/node": "18.11.0",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/nodemailer": "6.4.6",
|
||||
"@types/nprogress": "0.2.0",
|
||||
"@types/papaparse": "5.3.5",
|
||||
"@types/prettier": "2.7.1",
|
||||
"@types/qs": "6.9.7",
|
||||
"@types/react": "18.0.21",
|
||||
"@types/react": "18.0.24",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"@typescript-eslint/eslint-plugin": "5.40.0",
|
||||
"@typescript-eslint/parser": "5.40.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.0",
|
||||
"@typescript-eslint/parser": "5.42.0",
|
||||
"db": "workspace:*",
|
||||
"dotenv": "16.0.3",
|
||||
"eslint": "8.25.0",
|
||||
"eslint-config-next": "12.3.1",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.1",
|
||||
"eslint-plugin-react": "7.31.10",
|
||||
"models": "workspace:*",
|
||||
"next-transpile-modules": "9.1.0",
|
||||
"next-transpile-modules": "10.0.0",
|
||||
"typescript": "4.8.4",
|
||||
"utils": "workspace:*"
|
||||
"utils": "workspace:*",
|
||||
"configs": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import { Seo } from 'components/Seo'
|
||||
import { TypebotHeader } from 'components/shared/TypebotHeader'
|
||||
import React, { useMemo } from 'react'
|
||||
import { HStack, Button, Tag, Flex, Text } from '@chakra-ui/react'
|
||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||
import { ResultsContent } from 'components/results/ResultsContent'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||
@ -14,6 +13,7 @@ import { ResultsProvider } from 'contexts/ResultsProvider'
|
||||
import { UnlockPlanInfo } from 'components/shared/Info'
|
||||
import { getChatsLimit, getStorageLimit } from 'utils'
|
||||
import { useUsage } from 'components/dashboard/WorkspaceSettingsModal/BillingContent/UsageContent/useUsage'
|
||||
import Link from 'next/link'
|
||||
|
||||
const ALERT_CHATS_PERCENT_THRESHOLD = 80
|
||||
const ALERT_STORAGE_PERCENT_THRESHOLD = 80
|
||||
@ -130,7 +130,7 @@ const ResultsPage = () => {
|
||||
>
|
||||
<HStack maxW="1600px" w="full" px="4">
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
colorScheme={!isAnalytics ? 'blue' : 'gray'}
|
||||
variant={!isAnalytics ? 'outline' : 'ghost'}
|
||||
size="sm"
|
||||
@ -144,7 +144,7 @@ const ResultsPage = () => {
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
as={NextChakraLink}
|
||||
as={Link}
|
||||
colorScheme={isAnalytics ? 'blue' : 'gray'}
|
||||
variant={isAnalytics ? 'outline' : 'ghost'}
|
||||
href={`/typebots/${typebot?.id}/results/analytics`}
|
||||
|
@ -1,35 +1,22 @@
|
||||
import { devices, PlaywrightTestConfig } from '@playwright/test'
|
||||
import { PlaywrightTestConfig } from '@playwright/test'
|
||||
import path from 'path'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('dotenv').config({
|
||||
path: path.join(__dirname, 'playwright/.env'),
|
||||
})
|
||||
import { playwrightBaseConfig } from 'configs/playwright'
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
globalSetup: require.resolve(path.join(__dirname, 'playwright/global-setup')),
|
||||
...playwrightBaseConfig,
|
||||
testDir: path.join(__dirname, 'playwright/tests'),
|
||||
retries: process.env.NO_RETRIES ? 0 : 2,
|
||||
workers: process.env.CI ? 1 : 3,
|
||||
reporter: 'html',
|
||||
maxFailures: process.env.CI ? 10 : undefined,
|
||||
webServer: process.env.CI
|
||||
? {
|
||||
...(playwrightBaseConfig.webServer as { command: string }),
|
||||
port: 3000,
|
||||
}
|
||||
: undefined,
|
||||
use: {
|
||||
actionTimeout: 0,
|
||||
baseURL: process.env.PLAYWRIGHT_BUILDER_TEST_BASE_URL,
|
||||
trace: 'on-first-retry',
|
||||
...playwrightBaseConfig.use,
|
||||
baseURL: process.env.NEXTAUTH_URL,
|
||||
storageState: path.join(__dirname, 'playwright/firstUser.json'),
|
||||
video: 'retain-on-failure',
|
||||
locale: 'en-US',
|
||||
},
|
||||
outputDir: path.join(__dirname, 'playwright/test-results/'),
|
||||
projects: [
|
||||
{
|
||||
name: 'Chrome',
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
viewport: { width: 1400, height: 1000 },
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default config
|
||||
|
@ -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's your name?</div>",
|
||||
"richText": [
|
||||
@ -134,9 +134,9 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sqEsMo747LTDnY9FjQcEwUv",
|
||||
"id": "block1",
|
||||
"type": "text input",
|
||||
"groupId": "q5dAhqSTCaNdiGSJm9B9Rw",
|
||||
"groupId": "group1",
|
||||
"options": {
|
||||
"isLong": false,
|
||||
"labels": {
|
||||
|
@ -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
|
@ -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',
|
||||
})
|
||||
|
||||
|
@ -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'
|
||||
)
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
})
|
||||
|
||||
|
@ -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'
|
||||
)
|
||||
)
|
||||
|
@ -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()
|
||||
})
|
||||
|
@ -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()
|
||||
|
@ -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')
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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"]',
|
||||
|
@ -15,14 +15,14 @@
|
||||
"update-search": "docker run -it --rm --env-file=.env -e \"CONFIG=$(cat docsearch-scrapper-config.json | jq -r tostring)\" algolia/docsearch-scraper"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "2.1.0",
|
||||
"@docusaurus/preset-classic": "2.1.0",
|
||||
"@docusaurus/theme-search-algolia": "2.1.0",
|
||||
"@docusaurus/theme-common": "2.1.0",
|
||||
"@docusaurus/core": "2.2.0",
|
||||
"@docusaurus/preset-classic": "2.2.0",
|
||||
"@docusaurus/theme-search-algolia": "2.2.0",
|
||||
"@docusaurus/theme-common": "2.2.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"@mdx-js/react": "1.6.22",
|
||||
"@svgr/webpack": "6.5.0",
|
||||
"@svgr/webpack": "6.5.1",
|
||||
"clsx": "1.2.1",
|
||||
"file-loader": "6.2.0",
|
||||
"prism-react-renderer": "1.3.5",
|
||||
|
@ -36,8 +36,8 @@ export const Testimonial = (props: TestimonialProps) => {
|
||||
src={image}
|
||||
alt={name}
|
||||
placeholder="blur"
|
||||
width="80px"
|
||||
height="80px"
|
||||
width={80}
|
||||
height={80}
|
||||
className="rounded-full"
|
||||
/>
|
||||
<Box>
|
||||
|
@ -9,35 +9,35 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/icon": "3.0.11",
|
||||
"@chakra-ui/react": "2.3.5",
|
||||
"@emotion/react": "11.10.4",
|
||||
"@emotion/styled": "11.10.4",
|
||||
"@chakra-ui/react": "2.3.6",
|
||||
"@emotion/react": "11.10.5",
|
||||
"@emotion/styled": "11.10.5",
|
||||
"aos": "2.3.4",
|
||||
"bot-engine": "workspace:*",
|
||||
"focus-visible": "5.2.0",
|
||||
"framer-motion": "7.5.3",
|
||||
"framer-motion": "7.6.4",
|
||||
"models": "workspace:*",
|
||||
"next": "12.3.1",
|
||||
"next": "13.0.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"utils": "workspace:*",
|
||||
"db": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.19.3",
|
||||
"@babel/core": "7.19.6",
|
||||
"@chakra-ui/styled-system": "2.3.4",
|
||||
"@next/bundle-analyzer": "12.3.1",
|
||||
"@next/bundle-analyzer": "13.0.1",
|
||||
"@types/aos": "3.0.4",
|
||||
"@types/node": "18.11.0",
|
||||
"@types/react": "18.0.21",
|
||||
"@typescript-eslint/eslint-plugin": "5.40.0",
|
||||
"@typescript-eslint/parser": "5.40.0",
|
||||
"autoprefixer": "10.4.12",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/react": "18.0.24",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.0",
|
||||
"@typescript-eslint/parser": "5.42.0",
|
||||
"autoprefixer": "10.4.13",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "8.25.0",
|
||||
"eslint-config-next": "12.3.1",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.1",
|
||||
"eslint-plugin-react": "7.31.10",
|
||||
"next-transpile-modules": "9.1.0",
|
||||
"next-transpile-modules": "10.0.0",
|
||||
"postcss": "8.4.18",
|
||||
"prettier": "2.7.1",
|
||||
"typescript": "4.8.4"
|
||||
|
@ -5,27 +5,27 @@
|
||||
"scripts": {
|
||||
"dev": "ENVSH_ENV=.env.local bash ../../env.sh next dev -p 3001",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"start": "next start -p 3001",
|
||||
"lint": "next lint",
|
||||
"test": "pnpm playwright test",
|
||||
"test:open": "PWDEBUG=1 pnpm playwright test"
|
||||
"test:report": "pnpm playwright show-report"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/nextjs": "7.15.0",
|
||||
"aws-sdk": "2.1233.0",
|
||||
"@sentry/nextjs": "7.17.3",
|
||||
"aws-sdk": "2.1245.0",
|
||||
"bot-engine": "*",
|
||||
"cors": "2.8.5",
|
||||
"cuid": "2.1.8",
|
||||
"db": "workspace:*",
|
||||
"google-spreadsheet": "3.3.0",
|
||||
"got": "12.5.2",
|
||||
"next": "12.3.1",
|
||||
"next": "13.0.1",
|
||||
"nodemailer": "6.8.0",
|
||||
"qs": "6.11.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"sanitize-html": "2.7.2",
|
||||
"stripe": "10.14.0"
|
||||
"sanitize-html": "2.7.3",
|
||||
"stripe": "10.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "7.19.4",
|
||||
@ -33,26 +33,27 @@
|
||||
"@playwright/test": "1.27.1",
|
||||
"@types/cors": "2.8.12",
|
||||
"@types/google-spreadsheet": "3.3.0",
|
||||
"@types/node": "18.11.0",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/nodemailer": "6.4.6",
|
||||
"@types/papaparse": "5.3.5",
|
||||
"@types/qs": "6.9.7",
|
||||
"@types/react": "18.0.21",
|
||||
"@types/react": "18.0.24",
|
||||
"@types/sanitize-html": "2.6.2",
|
||||
"@typescript-eslint/eslint-plugin": "5.40.0",
|
||||
"@typescript-eslint/parser": "5.40.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.0",
|
||||
"@typescript-eslint/parser": "5.42.0",
|
||||
"dotenv": "16.0.3",
|
||||
"emails": "workspace:*",
|
||||
"eslint": "8.25.0",
|
||||
"eslint-config-next": "12.3.1",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.1",
|
||||
"eslint-plugin-react": "7.31.10",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"google-auth-library": "8.5.2",
|
||||
"google-auth-library": "8.6.0",
|
||||
"models": "workspace:*",
|
||||
"next-transpile-modules": "9.1.0",
|
||||
"next-transpile-modules": "10.0.0",
|
||||
"node-fetch": "^3.2.10",
|
||||
"papaparse": "5.3.2",
|
||||
"typescript": "4.8.4",
|
||||
"utils": "workspace:*"
|
||||
"utils": "workspace:*",
|
||||
"configs": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,21 @@
|
||||
import { devices, PlaywrightTestConfig } from '@playwright/test'
|
||||
import { PlaywrightTestConfig } from '@playwright/test'
|
||||
import path from 'path'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('dotenv').config({
|
||||
path: path.join(__dirname, 'playwright/.env'),
|
||||
})
|
||||
import { playwrightBaseConfig } from 'configs/playwright'
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
globalSetup: require.resolve(path.join(__dirname, 'playwright/global-setup')),
|
||||
...playwrightBaseConfig,
|
||||
testDir: path.join(__dirname, 'playwright/tests'),
|
||||
timeout: 10 * 2000,
|
||||
expect: {
|
||||
timeout: 5000,
|
||||
},
|
||||
retries: process.env.NO_RETRIES ? 0 : 1,
|
||||
workers: process.env.CI ? 1 : 3,
|
||||
reporter: 'html',
|
||||
maxFailures: process.env.CI ? 10 : undefined,
|
||||
webServer: process.env.CI
|
||||
? {
|
||||
...(playwrightBaseConfig.webServer as { command: string }),
|
||||
port: 3001,
|
||||
}
|
||||
: undefined,
|
||||
use: {
|
||||
actionTimeout: 0,
|
||||
baseURL: process.env.VIEWER_URL,
|
||||
trace: 'on-first-retry',
|
||||
video: 'retain-on-failure',
|
||||
locale: 'en-US',
|
||||
...playwrightBaseConfig.use,
|
||||
baseURL: process.env.NEXT_PUBLIC_VIEWER_URL,
|
||||
},
|
||||
outputDir: path.join(__dirname, 'playwright/test-results/'),
|
||||
projects: [
|
||||
{
|
||||
name: 'Chrome',
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
viewport: { width: 1400, height: 1000 },
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default config
|
||||
|
@ -1,4 +0,0 @@
|
||||
VIEWER_URL=http://localhost:3001
|
||||
BUILDER_URL=http://localhost:3000
|
||||
DATABASE_URL=postgresql://postgres:typebot@localhost:5432/typebot
|
||||
ENCRYPTION_SECRET=SgVkYp2s5v8y/B?E(H+MbQeThWmZq4t6 #256-bits secret (can be generated here: https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx)
|
@ -1,7 +1,7 @@
|
||||
import { CredentialsType, SmtpCredentialsData } from 'models'
|
||||
import { PrismaClient } from 'db'
|
||||
import { encrypt } from 'utils/api'
|
||||
import { freeWorkspaceId } from 'utils/playwright/databaseSetup'
|
||||
import { proWorkspaceId } from 'utils/playwright/databaseSetup'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
@ -17,7 +17,7 @@ export const createSmtpCredentials = (
|
||||
iv,
|
||||
name: smtpData.from.email as string,
|
||||
type: CredentialsType.SMTP,
|
||||
workspaceId: freeWorkspaceId,
|
||||
workspaceId: proWorkspaceId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ test('should work as expected', async ({ page, browser }) => {
|
||||
await expect(
|
||||
typebotViewer(page).locator(`text="3 files uploaded"`)
|
||||
).toBeVisible()
|
||||
await page.goto(`${process.env.BUILDER_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text="api.json"')).toHaveAttribute(
|
||||
'href',
|
||||
/.+\/api\.json/
|
||||
@ -52,7 +52,7 @@ test('should work as expected', async ({ page, browser }) => {
|
||||
const file = readFileSync(downloadPath as string).toString()
|
||||
const { data } = parse(file)
|
||||
expect(data).toHaveLength(2)
|
||||
expect((data[1] as unknown[])[1]).toContain('http://localhost:9000')
|
||||
expect((data[1] as unknown[])[1]).toContain(process.env.S3_ENDPOINT)
|
||||
|
||||
const urls = (
|
||||
await Promise.all(
|
||||
@ -72,17 +72,7 @@ test('should work as expected', async ({ page, browser }) => {
|
||||
await page.locator('button >> text="Delete" >> nth=1').click()
|
||||
await expect(page.locator('text="api.json"')).toBeHidden()
|
||||
await page2.goto(urls[0])
|
||||
await expect(
|
||||
page2.locator('span:has-text("The specified key does not exist.")')
|
||||
).toBeVisible()
|
||||
await page2.goto(urls[1])
|
||||
await expect(
|
||||
page2.locator('span:has-text("The specified key does not exist.")')
|
||||
).toBeVisible()
|
||||
await page2.goto(urls[2])
|
||||
await expect(
|
||||
page2.locator('span:has-text("The specified key does not exist.")')
|
||||
).toBeVisible()
|
||||
await expect(page2.locator('pre')).toBeHidden()
|
||||
})
|
||||
|
||||
// TODO: uncomment on 1st of November
|
||||
@ -124,7 +114,7 @@ test('should work as expected', async ({ page, browser }) => {
|
||||
// await page.evaluate(() =>
|
||||
// window.localStorage.setItem('workspaceId', 'starterWorkspace')
|
||||
// )
|
||||
// await page.goto(`${process.env.BUILDER_URL}/typebots/${typebotId}/results`)
|
||||
// await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
// await expect(page.locator('text="150%"')).toBeVisible()
|
||||
// await expect(page.locator('text="api.json"')).toBeHidden()
|
||||
// })
|
||||
|
@ -16,7 +16,7 @@ test('should work as expected', async ({ page }) => {
|
||||
await typebotViewer(page).locator('input').fill('26')
|
||||
await typebotViewer(page).locator('input').press('Enter')
|
||||
await typebotViewer(page).locator('button >> text=Yes').click()
|
||||
await page.goto(`${process.env.BUILDER_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text="Baptiste"')).toBeVisible()
|
||||
await expect(page.locator('text="26"')).toBeVisible()
|
||||
await expect(page.locator('text="Yes"')).toBeVisible()
|
||||
|
@ -17,10 +17,17 @@ const mockSmtpCredentials: SmtpCredentialsData = {
|
||||
password: 'yXZChpPy25Qa5yBbeH',
|
||||
}
|
||||
|
||||
test.beforeAll(async () => {
|
||||
try {
|
||||
const credentialsId = 'send-email-credentials'
|
||||
await createSmtpCredentials(credentialsId, mockSmtpCredentials)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
|
||||
test('should send an email', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
const credentialsId = 'send-email-credentials'
|
||||
await createSmtpCredentials(credentialsId, mockSmtpCredentials)
|
||||
await importTypebotInDatabase(
|
||||
path.join(__dirname, '../fixtures/typebots/sendEmail.json'),
|
||||
{ id: typebotId, publicId: `${typebotId}-public` }
|
||||
@ -41,7 +48,7 @@ test('should send an email', async ({ page }) => {
|
||||
await expect(
|
||||
page.locator('text="<baptiste.arnaud95@gmail.com>" >> nth=0')
|
||||
).toBeVisible()
|
||||
await page.goto(`${process.env.BUILDER_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await page.click('text="See logs"')
|
||||
await expect(page.locator('text="Email successfully sent"')).toBeVisible()
|
||||
})
|
||||
|
@ -3,18 +3,25 @@ import path from 'path'
|
||||
import { importTypebotInDatabase } from 'utils/playwright/databaseActions'
|
||||
import { typebotViewer } from 'utils/playwright/testHelpers'
|
||||
|
||||
test('should work as expected', async ({ page }) => {
|
||||
const typebotId = 'cl0ibhi7s0018n21aarlmg0cm'
|
||||
const linkedTypebotId = 'cl0ibhv8d0130n21aw8doxhj5'
|
||||
await importTypebotInDatabase(
|
||||
path.join(__dirname, '../fixtures/typebots/linkTypebots/1.json'),
|
||||
{ id: typebotId, publicId: `${typebotId}-public` }
|
||||
)
|
||||
await importTypebotInDatabase(
|
||||
path.join(__dirname, '../fixtures/typebots/linkTypebots/2.json'),
|
||||
{ id: linkedTypebotId, publicId: `${linkedTypebotId}-public` }
|
||||
)
|
||||
const typebotId = 'cl0ibhi7s0018n21aarlmg0cm'
|
||||
const linkedTypebotId = 'cl0ibhv8d0130n21aw8doxhj5'
|
||||
|
||||
test.beforeAll(async () => {
|
||||
try {
|
||||
await importTypebotInDatabase(
|
||||
path.join(__dirname, '../fixtures/typebots/linkTypebots/1.json'),
|
||||
{ id: typebotId, publicId: `${typebotId}-public` }
|
||||
)
|
||||
await importTypebotInDatabase(
|
||||
path.join(__dirname, '../fixtures/typebots/linkTypebots/2.json'),
|
||||
{ id: linkedTypebotId, publicId: `${linkedTypebotId}-public` }
|
||||
)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
|
||||
test('should work as expected', async ({ page }) => {
|
||||
await page.goto(`/${typebotId}-public`)
|
||||
await typebotViewer(page).locator('input').fill('Hello there!')
|
||||
await Promise.all([
|
||||
@ -26,6 +33,6 @@ test('should work as expected', async ({ page }) => {
|
||||
),
|
||||
typebotViewer(page).locator('input').press('Enter'),
|
||||
])
|
||||
await page.goto(`${process.env.BUILDER_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text=Hello there!')).toBeVisible()
|
||||
})
|
||||
|
@ -4,12 +4,15 @@ import path from 'path'
|
||||
import { HttpMethod } from 'models'
|
||||
import {
|
||||
createWebhook,
|
||||
deleteTypebots,
|
||||
deleteWebhooks,
|
||||
importTypebotInDatabase,
|
||||
} from 'utils/playwright/databaseActions'
|
||||
import { typebotViewer } from 'utils/playwright/testHelpers'
|
||||
|
||||
test('should execute webhooks properly', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
const typebotId = cuid()
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await importTypebotInDatabase(
|
||||
path.join(__dirname, '../fixtures/typebots/webhook.json'),
|
||||
{ id: typebotId, publicId: `${typebotId}-public` }
|
||||
@ -38,7 +41,18 @@ test('should execute webhooks properly', async ({ page }) => {
|
||||
method: HttpMethod.POST,
|
||||
body: `{{Full body}}`,
|
||||
})
|
||||
})
|
||||
|
||||
test.afterEach(async () => {
|
||||
await deleteTypebots([typebotId])
|
||||
await deleteWebhooks([
|
||||
'failing-webhook',
|
||||
'partial-body-webhook',
|
||||
'full-body-webhook',
|
||||
])
|
||||
})
|
||||
|
||||
test('should execute webhooks properly', async ({ page }) => {
|
||||
await page.goto(`/${typebotId}-public`)
|
||||
await typebotViewer(page).locator('text=Send failing webhook').click()
|
||||
await typebotViewer(page)
|
||||
|
15
package.json
15
package.json
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "2.8.2",
|
||||
"version": "2.8.3",
|
||||
"name": "typebot-os",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-or-later",
|
||||
@ -12,23 +12,24 @@
|
||||
"docker:nuke": "docker compose -f docker-compose.dev.yml down --volumes --remove-orphans",
|
||||
"dev": "pnpm docker:up && NEXT_PUBLIC_E2E_TEST=false turbo run dev --filter=builder... --filter=viewer... --parallel --no-cache",
|
||||
"dev:mocking": "pnpm docker:up && NEXT_PUBLIC_E2E_TEST=true turbo run dev --filter=builder... --filter=viewer... --parallel --no-cache",
|
||||
"build": "pnpm docker:up && turbo run build",
|
||||
"build:builder": "turbo run build --filter=builder... && ENVSH_ENV=./apps/builder/.env.docker ENVSH_OUTPUT=./apps/builder/public/__env.js bash env.sh",
|
||||
"build:viewer": "turbo run build --filter=viewer... && ENVSH_ENV=./apps/viewer/.env.docker ENVSH_OUTPUT=./apps/viewer/public/__env.js bash env.sh",
|
||||
"build": "pnpm docker:up && TURBO_CI_VENDOR_ENV_KEY=NEXT_PUBLIC_ turbo run build",
|
||||
"build:builder": "TURBO_CI_VENDOR_ENV_KEY=NEXT_PUBLIC_ turbo run build --filter=builder... && ENVSH_ENV=./apps/builder/.env.docker ENVSH_OUTPUT=./apps/builder/public/__env.js bash env.sh",
|
||||
"build:viewer": "TURBO_CI_VENDOR_ENV_KEY=NEXT_PUBLIC_ turbo run build --filter=viewer... && ENVSH_ENV=./apps/viewer/.env.docker ENVSH_OUTPUT=./apps/viewer/public/__env.js bash env.sh",
|
||||
"build:landing-page": "turbo run build --filter=landing-page... && ENVSH_ENV=./apps/landing-page/.env.docker ENVSH_OUTPUT=./apps/landing-page/public/__env.js bash env.sh",
|
||||
"test:builder": "cd apps/builder && pnpm test",
|
||||
"lint": "turbo run lint",
|
||||
"test:viewer": "cd apps/viewer && pnpm test",
|
||||
"db:migrate": "cd packages/db && pnpm migration:deploy",
|
||||
"build:ci": "turbo run build --filter=builder... --filter=viewer... && ENVSH_ENV=./apps/builder/.env.docker ENVSH_OUTPUT=./apps/builder/public/__env.js bash env.sh && ENVSH_ENV=./apps/viewer/.env.docker ENVSH_OUTPUT=./apps/viewer/public/__env.js bash env.sh",
|
||||
"generate-change-log": "pnpx gitmoji-changelog"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cz-emoji": "1.3.2-canary.2",
|
||||
"turbo": "1.5.6"
|
||||
"turbo": "1.6.3"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-emoji"
|
||||
}
|
||||
},
|
||||
"packageManager": "pnpm@7.12.2"
|
||||
"packageManager": "pnpm@7.14.0"
|
||||
}
|
||||
|
@ -11,30 +11,30 @@
|
||||
"lint": "eslint --fix -c ./.eslintrc.js \"./src/**/*.ts*\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@stripe/react-stripe-js": "1.13.0",
|
||||
"@stripe/stripe-js": "1.41.0",
|
||||
"@stripe/react-stripe-js": "1.14.1",
|
||||
"@stripe/stripe-js": "1.42.1",
|
||||
"prop-types": "15.8.1",
|
||||
"qs": "6.11.0",
|
||||
"react-frame-component": "5.2.3",
|
||||
"react-phone-number-input": "3.2.11",
|
||||
"react-scroll": "1.8.7",
|
||||
"react-phone-number-input": "3.2.12",
|
||||
"react-scroll": "1.8.8",
|
||||
"react-transition-group": "4.4.5",
|
||||
"resize-observer": "1.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.11.0",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/qs": "6.9.7",
|
||||
"@types/react": "18.0.21",
|
||||
"@types/react": "18.0.24",
|
||||
"@types/react-phone-number-input": "3.0.14",
|
||||
"@types/react-scroll": "1.8.4",
|
||||
"@types/react-transition-group": "4.4.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.40.0",
|
||||
"@typescript-eslint/parser": "5.40.0",
|
||||
"autoprefixer": "10.4.12",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.0",
|
||||
"@typescript-eslint/parser": "5.42.0",
|
||||
"autoprefixer": "10.4.13",
|
||||
"baptistearno-tsup": "^0.1.0",
|
||||
"db": "workspace:*",
|
||||
"eslint": "8.25.0",
|
||||
"eslint-config-next": "12.3.1",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.1",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"eslint-plugin-react": "7.31.10",
|
||||
@ -43,7 +43,7 @@
|
||||
"prettier": "2.7.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"tailwindcss": "3.1.8",
|
||||
"tailwindcss": "3.2.1",
|
||||
"typescript": "4.8.4",
|
||||
"utils": "workspace:*"
|
||||
},
|
||||
|
@ -35,7 +35,7 @@ export const InputChatBlock = ({
|
||||
) => void
|
||||
onSkip: () => void
|
||||
}) => {
|
||||
const { typebot } = useTypebot()
|
||||
const { typebot, isLoading } = useTypebot()
|
||||
const { addAnswer } = useAnswers()
|
||||
const [answer, setAnswer] = useState<string>()
|
||||
const [isEditting, setIsEditting] = useState(false)
|
||||
@ -66,6 +66,8 @@ export const InputChatBlock = ({
|
||||
setIsEditting(true)
|
||||
}
|
||||
|
||||
if (isLoading) return null
|
||||
|
||||
if (answer) {
|
||||
const avatarUrl = typebot.theme.chat.guestAvatar?.url
|
||||
return (
|
||||
|
14
packages/configs/package.json
Normal file
14
packages/configs/package.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "configs",
|
||||
"version": "1.0.0",
|
||||
"main": "./index.ts",
|
||||
"types": "./index.ts",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.27.1",
|
||||
"@types/node": "18.11.9",
|
||||
"dotenv": "16.0.3",
|
||||
"utils": "workspace:*"
|
||||
}
|
||||
}
|
47
packages/configs/playwright/baseConfig.ts
Normal file
47
packages/configs/playwright/baseConfig.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { PlaywrightTestConfig } from '@playwright/test'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
const builderLocalEnvPath = path.join(
|
||||
__dirname,
|
||||
'../../../apps/builder/.env.local'
|
||||
)
|
||||
const localViewerEnvPath = path.join(
|
||||
__dirname,
|
||||
'../../../apps/viewer/.env.local'
|
||||
)
|
||||
if (fs.existsSync(builderLocalEnvPath))
|
||||
require('dotenv').config({
|
||||
path: builderLocalEnvPath,
|
||||
})
|
||||
|
||||
if (fs.existsSync(localViewerEnvPath))
|
||||
require('dotenv').config({
|
||||
path: localViewerEnvPath,
|
||||
})
|
||||
|
||||
export const playwrightBaseConfig: PlaywrightTestConfig = {
|
||||
globalSetup: require.resolve(path.join(__dirname, 'globalSetup')),
|
||||
timeout: process.env.CI ? 50 * 1000 : 20 * 1000,
|
||||
expect: {
|
||||
timeout: process.env.CI ? 10 * 1000 : 5 * 1000,
|
||||
},
|
||||
retries: process.env.NO_RETRIES ? 0 : 1,
|
||||
workers: process.env.CI ? 2 : 3,
|
||||
reporter: [[process.env.CI ? 'github' : 'list'], ['html']],
|
||||
maxFailures: process.env.CI ? 10 : undefined,
|
||||
webServer: process.env.CI
|
||||
? {
|
||||
command: 'pnpm run start',
|
||||
timeout: 60_000,
|
||||
reuseExistingServer: true,
|
||||
}
|
||||
: undefined,
|
||||
use: {
|
||||
trace: 'on-first-retry',
|
||||
video: 'retain-on-failure',
|
||||
locale: 'en-US',
|
||||
browserName: 'chromium',
|
||||
viewport: { width: 1400, height: 1000 },
|
||||
},
|
||||
}
|
1
packages/configs/playwright/index.ts
Normal file
1
packages/configs/playwright/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { playwrightBaseConfig } from './baseConfig'
|
6
packages/configs/tsconfig.json
Normal file
6
packages/configs/tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
"main": "./index.ts",
|
||||
"types": "./index.ts",
|
||||
"scripts": {
|
||||
"dev": "dotenv -e ../../apps/builder/.env.local prisma db push && pnpm generate:schema && pnpm start:sutdio ",
|
||||
"dev": "dotenv -e ../../apps/builder/.env.local prisma db push && pnpm generate:schema",
|
||||
"build": "pnpm generate:schema",
|
||||
"start:sutdio": "dotenv -e ../../apps/builder/.env.local -v BROWSER=none prisma studio",
|
||||
"generate:schema": "dotenv -e ../../apps/builder/.env.local prisma generate",
|
||||
@ -16,10 +16,10 @@
|
||||
"migration:deploy": "prisma migrate deploy"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "4.4.0"
|
||||
"@prisma/client": "4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prisma": "4.4.0",
|
||||
"prisma": "4.5.0",
|
||||
"typescript": "4.8.4",
|
||||
"dotenv-cli": "6.0.0"
|
||||
}
|
||||
|
@ -14,15 +14,15 @@
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@faire/mjml-react": "2.1.4",
|
||||
"@types/node": "18.11.0",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/nodemailer": "6.4.6",
|
||||
"@types/react": "18.0.21",
|
||||
"concurrently": "7.4.0",
|
||||
"@types/react": "18.0.24",
|
||||
"concurrently": "7.5.0",
|
||||
"http-server": "14.1.1",
|
||||
"nodemailer": "6.8.0",
|
||||
"react": "18.2.0",
|
||||
"serve": "14.0.1",
|
||||
"tsx": "3.10.1",
|
||||
"tsx": "3.11.0",
|
||||
"utils": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -10,7 +10,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "4.8.4",
|
||||
"next": "12.3.1",
|
||||
"next": "13.0.1",
|
||||
"db": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -5,17 +5,19 @@
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start:local": "ts-node index.ts",
|
||||
"start:staging": "NODE_ENV=staging ts-node index.ts",
|
||||
"start:prod": "NODE_ENV=production ts-node index.ts"
|
||||
"start:local": "tsx index.ts",
|
||||
"start:staging": "NODE_ENV=staging tsx index.ts",
|
||||
"start:prod": "NODE_ENV=production tsx index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.11.0",
|
||||
"@types/node": "18.11.9",
|
||||
"axios": "^1.1.3",
|
||||
"db": "workspace:*",
|
||||
"emails": "workspace:*",
|
||||
"got": "12.5.2",
|
||||
"models": "workspace:*",
|
||||
"ts-node": "10.9.1",
|
||||
"tsx": "3.11.0",
|
||||
"typescript": "4.8.4",
|
||||
"utils": "workspace:*",
|
||||
"emails": "workspace:*"
|
||||
"utils": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
@ -11,16 +11,16 @@
|
||||
"test": "pnpm jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.1.2",
|
||||
"@typescript-eslint/eslint-plugin": "5.40.0",
|
||||
"@typescript-eslint/parser": "5.40.0",
|
||||
"@types/jest": "29.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.0",
|
||||
"@typescript-eslint/parser": "5.42.0",
|
||||
"baptistearno-tsup": "^0.1.0",
|
||||
"eslint": "8.25.0",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-plugin-functional": "4.4.1",
|
||||
"eslint-plugin-jest": "27.1.2",
|
||||
"eslint-plugin-jest": "27.1.3",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"jest": "29.2.0",
|
||||
"jest-environment-jsdom": "29.2.0",
|
||||
"jest": "29.2.2",
|
||||
"jest-environment-jsdom": "29.2.2",
|
||||
"prettier": "2.7.1",
|
||||
"ts-jest": "29.0.3",
|
||||
"typescript": "4.8.4"
|
||||
|
@ -8,11 +8,11 @@
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.27.1",
|
||||
"@types/nodemailer": "6.4.6",
|
||||
"aws-sdk": "2.1233.0",
|
||||
"aws-sdk": "2.1245.0",
|
||||
"cuid": "2.1.8",
|
||||
"db": "workspace:*",
|
||||
"models": "workspace:*",
|
||||
"next": "12.3.1",
|
||||
"next": "13.0.1",
|
||||
"nodemailer": "6.8.0",
|
||||
"typescript": "4.8.4"
|
||||
},
|
||||
|
@ -62,7 +62,7 @@ const createAnswers = ({
|
||||
resultId: `${resultIdPrefix}-result${idx}`,
|
||||
content: `content${idx}`,
|
||||
blockId: 'block1',
|
||||
groupId: 'block1',
|
||||
groupId: 'group1',
|
||||
storageUsed: fakeStorage ? Math.round(fakeStorage / count) : null,
|
||||
})),
|
||||
],
|
||||
@ -95,6 +95,24 @@ export const deleteWorkspaces = async (workspaceIds: string[]) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteTypebots = async (typebotIds: string[]) => {
|
||||
await prisma.typebot.deleteMany({
|
||||
where: { id: { in: typebotIds } },
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteCredentials = async (credentialIds: string[]) => {
|
||||
await prisma.credentials.deleteMany({
|
||||
where: { id: { in: credentialIds } },
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteWebhooks = async (webhookIds: string[]) => {
|
||||
await prisma.webhook.deleteMany({
|
||||
where: { id: { in: webhookIds } },
|
||||
})
|
||||
}
|
||||
|
||||
export const createWorkspaces = async (workspaces: Partial<Workspace>[]) => {
|
||||
const workspaceIds = workspaces.map((workspace) => workspace.id ?? cuid())
|
||||
await prisma.workspace.createMany({
|
||||
|
@ -6,7 +6,7 @@
|
||||
"author": "baptisteArno",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"devDependencies": {
|
||||
"@prettier/plugin-php": "0.19.1",
|
||||
"@prettier/plugin-php": "0.19.2",
|
||||
"prettier": "2.7.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
4496
pnpm-lock.yaml
generated
4496
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "VERCEL_GIT_COMMIT_REF: $VERCEL_GIT_COMMIT_REF"
|
||||
|
||||
if [[ "$VERCEL_GIT_COMMIT_REF" == "dev" || "$VERCEL_GIT_COMMIT_REF" == "main" ]] ; then
|
||||
echo "✅ - Build can proceed"
|
||||
exit 1;
|
||||
|
||||
else
|
||||
echo "🛑 - Build cancelled"
|
||||
exit 0;
|
||||
fi
|
10
turbo.json
10
turbo.json
@ -9,15 +9,9 @@
|
||||
"db#build": {
|
||||
"cache": false
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": [],
|
||||
"outputs": []
|
||||
},
|
||||
"lint": {
|
||||
"outputs": []
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["^dev"]
|
||||
"dependsOn": ["^dev"],
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user