chore(bubbles): ✅ Add e2e tests
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
|||||||
useEventListener,
|
useEventListener,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import React, { useEffect, useMemo, useState } from 'react'
|
import React, { useEffect, useMemo, useState } from 'react'
|
||||||
import { Block, Step, StepType } from 'models'
|
import { Block, Step } from 'models'
|
||||||
import { SourceEndpoint } from './SourceEndpoint'
|
import { SourceEndpoint } from './SourceEndpoint'
|
||||||
import { useGraph } from 'contexts/GraphContext'
|
import { useGraph } from 'contexts/GraphContext'
|
||||||
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
|
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
|
||||||
@@ -19,6 +19,7 @@ import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
|||||||
import { ContextMenu } from 'components/shared/ContextMenu'
|
import { ContextMenu } from 'components/shared/ContextMenu'
|
||||||
import { StepNodeContextMenu } from './RightClickMenu'
|
import { StepNodeContextMenu } from './RightClickMenu'
|
||||||
import { SettingsPopoverContent } from './SettingsPopoverContent'
|
import { SettingsPopoverContent } from './SettingsPopoverContent'
|
||||||
|
import { isStepText } from 'services/typebots'
|
||||||
|
|
||||||
export const StepNode = ({
|
export const StepNode = ({
|
||||||
step,
|
step,
|
||||||
@@ -41,7 +42,9 @@ export const StepNode = ({
|
|||||||
const [isConnecting, setIsConnecting] = useState(false)
|
const [isConnecting, setIsConnecting] = useState(false)
|
||||||
const [mouseDownEvent, setMouseDownEvent] =
|
const [mouseDownEvent, setMouseDownEvent] =
|
||||||
useState<{ absolute: Coordinates; relative: Coordinates }>()
|
useState<{ absolute: Coordinates; relative: Coordinates }>()
|
||||||
const [isEditing, setIsEditing] = useState<boolean | undefined>(undefined)
|
const [isEditing, setIsEditing] = useState<boolean>(
|
||||||
|
isStepText(step) && step.content.plainText === ''
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsConnecting(
|
setIsConnecting(
|
||||||
@@ -139,9 +142,7 @@ export const StepNode = ({
|
|||||||
connectingIds?.target?.blockId,
|
connectingIds?.target?.blockId,
|
||||||
])
|
])
|
||||||
|
|
||||||
return step.type === StepType.TEXT &&
|
return isEditing && isStepText(step) ? (
|
||||||
(isEditing ||
|
|
||||||
(isEditing === undefined && step.content.plainText === '')) ? (
|
|
||||||
<TextEditor
|
<TextEditor
|
||||||
stepId={step.id}
|
stepId={step.id}
|
||||||
initialValue={step.content.richText}
|
initialValue={step.content.richText}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export const TextEditor = ({
|
|||||||
edge: 'end',
|
edge: 'end',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
'aria-label': 'Text editor',
|
||||||
}}
|
}}
|
||||||
initialValue={
|
initialValue={
|
||||||
initialValue.length === 0
|
initialValue.length === 0
|
||||||
|
|||||||
@@ -22,18 +22,24 @@ export const ToolBar = (props: StackProps) => {
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<Button size="sm">Variables</Button>
|
<Button size="sm">Variables</Button>
|
||||||
<MarkToolbarButton
|
<span data-testid="bold-button">
|
||||||
type={getPluginType(editor, MARK_BOLD)}
|
<MarkToolbarButton
|
||||||
icon={<BoldIcon />}
|
type={getPluginType(editor, MARK_BOLD)}
|
||||||
/>
|
icon={<BoldIcon />}
|
||||||
<MarkToolbarButton
|
/>
|
||||||
type={getPluginType(editor, MARK_ITALIC)}
|
</span>
|
||||||
icon={<ItalicIcon />}
|
<span data-testid="italic-button">
|
||||||
/>
|
<MarkToolbarButton
|
||||||
<MarkToolbarButton
|
type={getPluginType(editor, MARK_ITALIC)}
|
||||||
type={getPluginType(editor, MARK_UNDERLINE)}
|
icon={<ItalicIcon />}
|
||||||
icon={<UnderlineIcon />}
|
/>
|
||||||
/>
|
</span>
|
||||||
|
<span data-testid="underline-button">
|
||||||
|
<MarkToolbarButton
|
||||||
|
type={getPluginType(editor, MARK_UNDERLINE)}
|
||||||
|
icon={<UnderlineIcon />}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
<LinkToolbarButton icon={<LinkIcon />} />
|
<LinkToolbarButton icon={<LinkIcon />} />
|
||||||
</HStack>
|
</HStack>
|
||||||
)
|
)
|
||||||
|
|||||||
78
apps/builder/cypress/tests/bubbles.ts
Normal file
78
apps/builder/cypress/tests/bubbles.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { parseTestTypebot } from 'cypress/plugins/utils'
|
||||||
|
import { StepType } from 'models'
|
||||||
|
|
||||||
|
describe('Text bubbles', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.task('seed')
|
||||||
|
cy.task(
|
||||||
|
'createTypebot',
|
||||||
|
parseTestTypebot({
|
||||||
|
id: 'typebot3',
|
||||||
|
name: 'Typebot #3',
|
||||||
|
ownerId: 'test2',
|
||||||
|
steps: {
|
||||||
|
byId: {
|
||||||
|
step1: {
|
||||||
|
id: 'step1',
|
||||||
|
blockId: 'block1',
|
||||||
|
type: StepType.TEXT,
|
||||||
|
content: { html: '', plainText: '', richText: [] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
allIds: ['step1'],
|
||||||
|
},
|
||||||
|
blocks: {
|
||||||
|
byId: {
|
||||||
|
block1: {
|
||||||
|
id: 'block1',
|
||||||
|
graphCoordinates: { x: 400, y: 200 },
|
||||||
|
title: 'Block #1',
|
||||||
|
stepIds: ['step1'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
allIds: ['block1'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
cy.signOut()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('rich text features should work', () => {
|
||||||
|
cy.signIn('test2@gmail.com')
|
||||||
|
cy.visit('/typebots/typebot3/edit')
|
||||||
|
cy.findByTestId('bold-button').click()
|
||||||
|
cy.findByRole('textbox', { name: 'Text editor' }).type('Bold text{enter}')
|
||||||
|
cy.findByTestId('bold-button').click()
|
||||||
|
cy.findByTestId('italic-button').click()
|
||||||
|
cy.findByRole('textbox', { name: 'Text editor' }).type('Italic text{enter}')
|
||||||
|
cy.findByTestId('italic-button').click()
|
||||||
|
cy.findByTestId('underline-button').click()
|
||||||
|
cy.findByRole('textbox', { name: 'Text editor' }).type(
|
||||||
|
'Underlined text{enter}'
|
||||||
|
)
|
||||||
|
cy.findByTestId('bold-button').click()
|
||||||
|
cy.findByTestId('italic-button').click()
|
||||||
|
cy.findByRole('textbox', { name: 'Text editor' }).type('Everything text')
|
||||||
|
cy.findByRole('button', { name: 'Preview' }).click()
|
||||||
|
getIframeBody()
|
||||||
|
.get('span.slate-bold')
|
||||||
|
.should('exist')
|
||||||
|
.should('contain.text', 'Bold text')
|
||||||
|
getIframeBody()
|
||||||
|
.get('span.slate-italic')
|
||||||
|
.should('exist')
|
||||||
|
.should('contain.text', 'Italic text')
|
||||||
|
getIframeBody()
|
||||||
|
.get('span.slate-underline')
|
||||||
|
.should('exist')
|
||||||
|
.should('contain.text', 'Underlined text')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const getIframeBody = () => {
|
||||||
|
return cy
|
||||||
|
.get('#typebot-iframe')
|
||||||
|
.its('0.contentDocument.body')
|
||||||
|
.should('not.be.empty')
|
||||||
|
.then(cy.wrap)
|
||||||
|
}
|
||||||
@@ -83,5 +83,5 @@ const blockContainsInput = (
|
|||||||
stepIsInput(typebot.steps.byId[stepId])
|
stepIsInput(typebot.steps.byId[stepId])
|
||||||
)
|
)
|
||||||
|
|
||||||
const stepIsInput = (step: Step): step is InputStep =>
|
export const stepIsInput = (step: Step): step is InputStep =>
|
||||||
step.type === StepType.TEXT_INPUT
|
step.type === StepType.TEXT_INPUT
|
||||||
|
|||||||
@@ -211,3 +211,6 @@ export const parseNewTypebot = ({
|
|||||||
settings,
|
settings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isStepText = (step: Step): step is TextStep =>
|
||||||
|
step.type === StepType.TEXT
|
||||||
|
|||||||
Reference in New Issue
Block a user