🚑 (bot) Fix set variable number computation
This commit is contained in:
@@ -1,33 +1,32 @@
|
|||||||
{
|
{
|
||||||
"id": "ckz8hovd511021no1apuuyjv7b",
|
"id": "cl9d7ruqe00093b6o0m9a6l0d",
|
||||||
"createdAt": "2022-02-04T14:15:06.953Z",
|
"createdAt": "2022-10-17T20:13:24.182Z",
|
||||||
"updatedAt": "2022-02-04T14:15:06.953Z",
|
"updatedAt": "2022-10-17T20:14:48.231Z",
|
||||||
"name": "My typebot",
|
"icon": null,
|
||||||
|
"name": "My typebot copy",
|
||||||
"publishedTypebotId": null,
|
"publishedTypebotId": null,
|
||||||
"folderId": null,
|
"folderId": null,
|
||||||
"groups": [
|
"groups": [
|
||||||
{
|
{
|
||||||
"id": "jvbBpKifJ3ssvKQxPqhBiD",
|
"id": "cl9d7ruqe00023b6op792zght",
|
||||||
|
"title": "Start",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "rqecLJCZT7gP2JgBhRpb3a",
|
"id": "rqecLJCZT7gP2JgBhRpb3a",
|
||||||
"type": "start",
|
"type": "start",
|
||||||
"label": "Start",
|
"label": "Start",
|
||||||
"groupId": "jvbBpKifJ3ssvKQxPqhBiD",
|
"groupId": "cl9d7ruqe00023b6op792zght",
|
||||||
"outgoingEdgeId": "qnD38SqA7sYEh7efPZgDoR"
|
"outgoingEdgeId": "cl9d7ruqe00063b6o98bpn80p"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "Start",
|
|
||||||
"graphCoordinates": { "x": 0, "y": 0 }
|
"graphCoordinates": { "x": 0, "y": 0 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "roD9feCwx6jTDuVCThgzM2",
|
"id": "cl9d7ruqe00033b6oe5nzpeub",
|
||||||
"graphCoordinates": { "x": 200, "y": 171 },
|
|
||||||
"title": "Group #1",
|
"title": "Group #1",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "souEkLukHsYU9jrN2rAP7YT",
|
"id": "souEkLukHsYU9jrN2rAP7YT",
|
||||||
"groupId": "roD9feCwx6jTDuVCThgzM2",
|
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"html": "<div>How old are you?</div>",
|
"html": "<div>How old are you?</div>",
|
||||||
@@ -35,88 +34,103 @@
|
|||||||
{ "type": "p", "children": [{ "text": "How old are you?" }] }
|
{ "type": "p", "children": [{ "text": "How old are you?" }] }
|
||||||
],
|
],
|
||||||
"plainText": "How old are you?"
|
"plainText": "How old are you?"
|
||||||
}
|
},
|
||||||
|
"groupId": "cl9d7ruqe00033b6oe5nzpeub"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "skfn5McXVrTNpi2e62RtEEY",
|
"id": "skfn5McXVrTNpi2e62RtEEY",
|
||||||
"groupId": "roD9feCwx6jTDuVCThgzM2",
|
|
||||||
"type": "number input",
|
"type": "number input",
|
||||||
|
"groupId": "cl9d7ruqe00033b6oe5nzpeub",
|
||||||
"options": {
|
"options": {
|
||||||
"labels": { "button": "Send", "placeholder": "Type a number..." }
|
"labels": { "button": "Send", "placeholder": "Type a number..." }
|
||||||
},
|
},
|
||||||
"outgoingEdgeId": "5ZYDLyR1CUF6B8ESHrFXwK"
|
"outgoingEdgeId": "cl9d7ruqe00073b6oumb3wdq8"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"graphCoordinates": { "x": 200, "y": 171 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "tFFeBrrWxY4tvr11C8rjTw",
|
"id": "cl9d7ruqe00043b6o74n47tpt",
|
||||||
"graphCoordinates": { "x": 526, "y": 283 },
|
|
||||||
"title": "Group #2",
|
"title": "Group #2",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "spgqbyvunY91Ct5kVgeLLkz",
|
"id": "spgqbyvunY91Ct5kVgeLLkz",
|
||||||
"groupId": "tFFeBrrWxY4tvr11C8rjTw",
|
|
||||||
"type": "Set variable",
|
"type": "Set variable",
|
||||||
|
"groupId": "cl9d7ruqe00043b6o74n47tpt",
|
||||||
"options": {}
|
"options": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "skeKC71L8C8wpfeuV4TTLCD",
|
"id": "skeKC71L8C8wpfeuV4TTLCD",
|
||||||
"groupId": "tFFeBrrWxY4tvr11C8rjTw",
|
"type": "Set variable",
|
||||||
|
"groupId": "cl9d7ruqe00043b6o74n47tpt",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cl9d7srh8000e3b6okmpf5165",
|
||||||
|
"groupId": "cl9d7ruqe00043b6o74n47tpt",
|
||||||
"type": "Set variable",
|
"type": "Set variable",
|
||||||
"options": {},
|
"options": {},
|
||||||
"outgoingEdgeId": "7A4BD2vJT87grt3xFw86bn"
|
"outgoingEdgeId": "cl9d7svig000f3b6o5v0wlsxw"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"graphCoordinates": { "x": 526, "y": 283 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "k6jFuKuSwy29LVwKxMWasv",
|
"id": "cl9d7ruqe00053b6o8l0h608t",
|
||||||
"graphCoordinates": { "x": 691, "y": 35 },
|
|
||||||
"title": "Group #3",
|
"title": "Group #3",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "svpmd4uNoAXpoKyfYuuXTQe",
|
"id": "svpmd4uNoAXpoKyfYuuXTQe",
|
||||||
"groupId": "k6jFuKuSwy29LVwKxMWasv",
|
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"html": "<div>Total: {{Total}}</div><div>Custom var: {{Custom var}}</div>",
|
"html": "<div>Multiplication: {{Total}}</div><div>Custom var: {{Custom var}}</div><div>Addition: {{Addition}}</div>",
|
||||||
"richText": [
|
"richText": [
|
||||||
{ "type": "p", "children": [{ "text": "Total: {{Total}}" }] },
|
{
|
||||||
|
"type": "p",
|
||||||
|
"children": [{ "text": "Multiplication: {{Total}}" }]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "p",
|
"type": "p",
|
||||||
"children": [{ "text": "Custom var: {{Custom var}}" }]
|
"children": [{ "text": "Custom var: {{Custom var}}" }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "p",
|
||||||
|
"children": [{ "text": "Addition: {{Addition}}" }]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plainText": "Total: {{Total}}Custom var: {{Custom var}}"
|
"plainText": "Multiplication: {{Total}}Custom var: {{Custom var}}Addition: {{Addition}}"
|
||||||
}
|
},
|
||||||
|
"groupId": "cl9d7ruqe00053b6o8l0h608t"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"graphCoordinates": { "x": 697, "y": -23 }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"variables": [],
|
"variables": [],
|
||||||
"edges": [
|
"edges": [
|
||||||
{
|
{
|
||||||
|
"id": "cl9d7ruqe00063b6o98bpn80p",
|
||||||
|
"to": { "groupId": "cl9d7ruqe00033b6oe5nzpeub" },
|
||||||
"from": {
|
"from": {
|
||||||
"groupId": "jvbBpKifJ3ssvKQxPqhBiD",
|
"blockId": "rqecLJCZT7gP2JgBhRpb3a",
|
||||||
"blockId": "rqecLJCZT7gP2JgBhRpb3a"
|
"groupId": "cl9d7ruqe00023b6op792zght"
|
||||||
},
|
}
|
||||||
"to": { "groupId": "roD9feCwx6jTDuVCThgzM2" },
|
},
|
||||||
"id": "qnD38SqA7sYEh7efPZgDoR"
|
{
|
||||||
|
"id": "cl9d7ruqe00073b6oumb3wdq8",
|
||||||
|
"to": { "groupId": "cl9d7ruqe00043b6o74n47tpt" },
|
||||||
|
"from": {
|
||||||
|
"blockId": "skfn5McXVrTNpi2e62RtEEY",
|
||||||
|
"groupId": "cl9d7ruqe00033b6oe5nzpeub"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": {
|
"from": {
|
||||||
"groupId": "roD9feCwx6jTDuVCThgzM2",
|
"groupId": "cl9d7ruqe00043b6o74n47tpt",
|
||||||
"blockId": "skfn5McXVrTNpi2e62RtEEY"
|
"blockId": "cl9d7srh8000e3b6okmpf5165"
|
||||||
},
|
},
|
||||||
"to": { "groupId": "tFFeBrrWxY4tvr11C8rjTw" },
|
"to": { "groupId": "cl9d7ruqe00053b6o8l0h608t" },
|
||||||
"id": "5ZYDLyR1CUF6B8ESHrFXwK"
|
"id": "cl9d7svig000f3b6o5v0wlsxw"
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": {
|
|
||||||
"groupId": "tFFeBrrWxY4tvr11C8rjTw",
|
|
||||||
"blockId": "skeKC71L8C8wpfeuV4TTLCD"
|
|
||||||
},
|
|
||||||
"to": { "groupId": "k6jFuKuSwy29LVwKxMWasv" },
|
|
||||||
"id": "7A4BD2vJT87grt3xFw86bn"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme": {
|
"theme": {
|
||||||
@@ -127,6 +141,10 @@
|
|||||||
"placeholderColor": "#9095A0"
|
"placeholderColor": "#9095A0"
|
||||||
},
|
},
|
||||||
"buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
|
"buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
|
||||||
|
"hostAvatar": {
|
||||||
|
"url": "https://avatars.githubusercontent.com/u/16015833?v=4",
|
||||||
|
"isEnabled": true
|
||||||
|
},
|
||||||
"hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
|
"hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
|
||||||
"guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
|
"guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
|
||||||
},
|
},
|
||||||
@@ -139,5 +157,9 @@
|
|||||||
},
|
},
|
||||||
"typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
|
"typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
|
||||||
},
|
},
|
||||||
"publicId": null
|
"publicId": null,
|
||||||
|
"customDomain": null,
|
||||||
|
"workspaceId": "proWorkspace",
|
||||||
|
"isArchived": false,
|
||||||
|
"isClosed": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,16 +33,27 @@ test.describe('Set variable block', () => {
|
|||||||
await page.click('text=Create "Custom var"')
|
await page.click('text=Create "Custom var"')
|
||||||
await page.fill('textarea', 'Custom value')
|
await page.fill('textarea', 'Custom value')
|
||||||
|
|
||||||
|
await page.click('text=Click to edit...', { force: true })
|
||||||
|
await page.fill(
|
||||||
|
'input[placeholder="Select a variable"] >> nth=-1',
|
||||||
|
'Addition'
|
||||||
|
)
|
||||||
|
await page.click('text=Create "Addition"')
|
||||||
|
await page.fill('textarea', '1000 + {{Total}}')
|
||||||
|
|
||||||
await page.click('text=Preview')
|
await page.click('text=Preview')
|
||||||
await typebotViewer(page)
|
await typebotViewer(page)
|
||||||
.locator('input[placeholder="Type a number..."]')
|
.locator('input[placeholder="Type a number..."]')
|
||||||
.fill('365')
|
.fill('365')
|
||||||
await typebotViewer(page).locator('text=Send').click()
|
await typebotViewer(page).locator('text=Send').click()
|
||||||
await expect(
|
await expect(
|
||||||
typebotViewer(page).locator('text=Total: 365000')
|
typebotViewer(page).locator('text=Multiplication: 365000')
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
await expect(
|
await expect(
|
||||||
typebotViewer(page).locator('text=Custom var: Custom value')
|
typebotViewer(page).locator('text=Custom var: Custom value')
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
|
await expect(
|
||||||
|
typebotViewer(page).locator('text=Addition: 366000')
|
||||||
|
).toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
} from 'models'
|
} from 'models'
|
||||||
import { byId, isDefined, isNotDefined, sendRequest } from 'utils'
|
import { byId, isDefined, isNotDefined, sendRequest } from 'utils'
|
||||||
import { sanitizeUrl } from './utils'
|
import { sanitizeUrl } from './utils'
|
||||||
import { evaluateExpression, parseVariables } from './variable'
|
import { parseCorrectValueType, parseVariables } from './variable'
|
||||||
|
|
||||||
type EdgeId = string
|
type EdgeId = string
|
||||||
|
|
||||||
@@ -69,7 +69,9 @@ const executeSetVariable = (
|
|||||||
): EdgeId | undefined => {
|
): EdgeId | undefined => {
|
||||||
if (!block.options?.variableId) return block.outgoingEdgeId
|
if (!block.options?.variableId) return block.outgoingEdgeId
|
||||||
const evaluatedExpression = block.options.expressionToEvaluate
|
const evaluatedExpression = block.options.expressionToEvaluate
|
||||||
? evaluateExpression(variables)(block.options.expressionToEvaluate)
|
? evaluateSetVariableExpression(variables)(
|
||||||
|
block.options.expressionToEvaluate
|
||||||
|
)
|
||||||
: undefined
|
: undefined
|
||||||
const existingVariable = variables.find(byId(block.options.variableId))
|
const existingVariable = variables.find(byId(block.options.variableId))
|
||||||
if (!existingVariable) return block.outgoingEdgeId
|
if (!existingVariable) return block.outgoingEdgeId
|
||||||
@@ -78,6 +80,21 @@ const executeSetVariable = (
|
|||||||
return block.outgoingEdgeId
|
return block.outgoingEdgeId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const evaluateSetVariableExpression =
|
||||||
|
(variables: Variable[]) =>
|
||||||
|
(str: string): unknown => {
|
||||||
|
const evaluating = parseVariables(variables, { fieldToParse: 'id' })(
|
||||||
|
str.includes('return ') ? str : `return ${str}`
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
const func = Function(...variables.map((v) => v.id), evaluating)
|
||||||
|
return func(...variables.map((v) => parseCorrectValueType(v.value)))
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`Evaluating: ${evaluating}`, err)
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const executeCondition = (
|
const executeCondition = (
|
||||||
block: ConditionBlock,
|
block: ConditionBlock,
|
||||||
{ typebot: { variables } }: LogicContext
|
{ typebot: { variables } }: LogicContext
|
||||||
@@ -161,7 +178,7 @@ const executeCode = async (
|
|||||||
parseVariables(variables, { fieldToParse: 'id' })(block.options.content)
|
parseVariables(variables, { fieldToParse: 'id' })(block.options.content)
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
await func(...variables.map((v) => v.value))
|
await func(...variables.map((v) => parseCorrectValueType(v.value)))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,27 +41,30 @@ export const safeStringify = (val: unknown): string | null => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const parseCorrectValueType = (
|
||||||
|
value: Variable['value']
|
||||||
|
): string | boolean | number | null | undefined => {
|
||||||
|
if (value === null) return null
|
||||||
|
if (value === undefined) return undefined
|
||||||
|
const isNumberStartingWithZero =
|
||||||
|
value.startsWith('0') && !value.startsWith('0.') && value.length > 1
|
||||||
|
if (typeof value === 'string' && isNumberStartingWithZero) return value
|
||||||
|
if (typeof value === 'number') return value
|
||||||
|
if (value === 'true') return true
|
||||||
|
if (value === 'false') return false
|
||||||
|
if (value === 'null') return null
|
||||||
|
if (value === 'undefined') return undefined
|
||||||
|
// isNaN works with strings
|
||||||
|
if (isNaN(value as unknown as number)) return value
|
||||||
|
return Number(value)
|
||||||
|
}
|
||||||
|
|
||||||
const jsonParse = (str: string) =>
|
const jsonParse = (str: string) =>
|
||||||
str
|
str
|
||||||
.replace(/\n/g, `\\n`)
|
.replace(/\n/g, `\\n`)
|
||||||
.replace(/"/g, `\\"`)
|
.replace(/"/g, `\\"`)
|
||||||
.replace(/\\[^n"]/g, `\\\\ `)
|
.replace(/\\[^n"]/g, `\\\\ `)
|
||||||
|
|
||||||
export const evaluateExpression =
|
|
||||||
(variables: Variable[]) =>
|
|
||||||
(str: string): unknown => {
|
|
||||||
const evaluating = parseVariables(variables, { fieldToParse: 'id' })(
|
|
||||||
str.includes('return ') ? str : `return ${str}`
|
|
||||||
)
|
|
||||||
try {
|
|
||||||
const func = Function(...variables.map((v) => v.id), evaluating)
|
|
||||||
return func(...variables.map((v) => v.value))
|
|
||||||
} catch (err) {
|
|
||||||
console.log(`Evaluating: ${evaluating}`, err)
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const parseVariablesInObject = (
|
export const parseVariablesInObject = (
|
||||||
object: { [key: string]: string | number },
|
object: { [key: string]: string | number },
|
||||||
variables: Variable[]
|
variables: Variable[]
|
||||||
|
|||||||
Reference in New Issue
Block a user