@@ -8,7 +8,7 @@ import {
|
||||
} from '@chakra-ui/react'
|
||||
import { PlusIcon } from '@/components/icons'
|
||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||
import { ButtonItem, ItemIndices, ItemType } from '@typebot.io/schemas'
|
||||
import { ButtonItem, Item, ItemIndices, ItemType } from '@typebot.io/schemas'
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { isNotDefined } from '@typebot.io/lib'
|
||||
|
||||
@@ -26,7 +26,9 @@ export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
||||
const handleInputSubmit = () => {
|
||||
if (itemValue === '') deleteItem(indices)
|
||||
else
|
||||
updateItem(indices, { content: itemValue === '' ? undefined : itemValue })
|
||||
updateItem(indices, {
|
||||
content: itemValue === '' ? undefined : itemValue,
|
||||
} as Item)
|
||||
}
|
||||
|
||||
const handleKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
|
||||
24
apps/builder/src/features/blocks/logic/abTest/abTest.spec.ts
Normal file
24
apps/builder/src/features/blocks/logic/abTest/abTest.spec.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { importTypebotInDatabase } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { getTestAsset } from '@/test/utils/playwright'
|
||||
|
||||
const typebotId = createId()
|
||||
|
||||
test.describe('AB Test block', () => {
|
||||
test('its configuration should work', async ({ page }) => {
|
||||
await importTypebotInDatabase(getTestAsset('typebots/logic/abTest.json'), {
|
||||
id: typebotId,
|
||||
})
|
||||
|
||||
await page.goto(`/typebots/${typebotId}/edit`)
|
||||
await page.getByText('A 50%').click()
|
||||
await page.getByLabel('Percent of users to follow A:').fill('100')
|
||||
await expect(page.getByText('A 100%')).toBeVisible()
|
||||
await expect(page.getByText('B 0%')).toBeVisible()
|
||||
await page.getByRole('button', { name: 'Preview' }).click()
|
||||
await expect(
|
||||
page.locator('typebot-standard').getByText('How are you?')
|
||||
).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
import { ShuffleIcon } from '@/components/icons'
|
||||
import { IconProps } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
|
||||
export const AbTestIcon = (props: IconProps) => (
|
||||
<ShuffleIcon color="purple.500" {...props} />
|
||||
)
|
||||
@@ -0,0 +1,66 @@
|
||||
import React from 'react'
|
||||
import { Flex, Stack, useColorModeValue, Text, Tag } from '@chakra-ui/react'
|
||||
import { AbTestBlock } from '@typebot.io/schemas'
|
||||
import { SourceEndpoint } from '@/features/graph/components/endpoints/SourceEndpoint'
|
||||
|
||||
type Props = {
|
||||
block: AbTestBlock
|
||||
}
|
||||
|
||||
export const AbTestNodeBody = ({ block }: Props) => {
|
||||
const borderColor = useColorModeValue('gray.200', 'gray.700')
|
||||
const bg = useColorModeValue('white', undefined)
|
||||
|
||||
return (
|
||||
<Stack spacing={2} w="full">
|
||||
<Flex
|
||||
pos="relative"
|
||||
align="center"
|
||||
shadow="sm"
|
||||
rounded="md"
|
||||
bg={bg}
|
||||
borderWidth={'1px'}
|
||||
borderColor={borderColor}
|
||||
w="full"
|
||||
>
|
||||
<Text p="3">
|
||||
A <Tag>{block.options.aPercent}%</Tag>
|
||||
</Text>
|
||||
<SourceEndpoint
|
||||
source={{
|
||||
groupId: block.groupId,
|
||||
blockId: block.id,
|
||||
itemId: block.items[0].id,
|
||||
}}
|
||||
pos="absolute"
|
||||
right="-49px"
|
||||
pointerEvents="all"
|
||||
/>
|
||||
</Flex>
|
||||
<Flex
|
||||
pos="relative"
|
||||
align="center"
|
||||
shadow="sm"
|
||||
rounded="md"
|
||||
bg={bg}
|
||||
borderWidth={'1px'}
|
||||
borderColor={borderColor}
|
||||
w="full"
|
||||
>
|
||||
<Text p="3">
|
||||
B <Tag>{100 - block.options.aPercent}%</Tag>
|
||||
</Text>
|
||||
<SourceEndpoint
|
||||
source={{
|
||||
groupId: block.groupId,
|
||||
blockId: block.id,
|
||||
itemId: block.items[1].id,
|
||||
}}
|
||||
pos="absolute"
|
||||
right="-49px"
|
||||
pointerEvents="all"
|
||||
/>
|
||||
</Flex>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Stack } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { AbTestBlock } from '@typebot.io/schemas'
|
||||
import { NumberInput } from '@/components/inputs'
|
||||
|
||||
type Props = {
|
||||
options: AbTestBlock['options']
|
||||
onOptionsChange: (options: AbTestBlock['options']) => void
|
||||
}
|
||||
|
||||
export const AbTestSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const updateAPercent = (aPercent?: number) =>
|
||||
isDefined(aPercent) ? onOptionsChange({ ...options, aPercent }) : null
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<NumberInput
|
||||
defaultValue={options.aPercent}
|
||||
onValueChange={updateAPercent}
|
||||
withVariableButton={false}
|
||||
label="Percent of users to follow A:"
|
||||
direction="column"
|
||||
max={100}
|
||||
min={0}
|
||||
/>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user