2
0

feat(lib): 🎨 Ask for URL instead of publishId

This commit is contained in:
Baptiste Arnaud
2022-03-14 14:57:10 +01:00
parent d6b94130cb
commit 5a2df9fe72
10 changed files with 384 additions and 375 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "typebot-js", "name": "typebot-js",
"version": "2.1.4", "version": "2.2.0",
"main": "dist/index.js", "main": "dist/index.js",
"unpkg": "dist/index.umd.min.js", "unpkg": "dist/index.umd.min.js",
"license": "MIT", "license": "MIT",

View File

@@ -3,18 +3,16 @@ import './style.css'
export const createIframe = ({ export const createIframe = ({
backgroundColor, backgroundColor,
viewerHost = 'https://typebot-viewer.vercel.app', url,
isV1,
...iframeParams ...iframeParams
}: IframeParams): HTMLIFrameElement => { }: IframeParams): HTMLIFrameElement => {
const { publishId, loadWhenVisible, hiddenVariables } = iframeParams const { loadWhenVisible, hiddenVariables } = iframeParams
const host = isV1 ? `https://bot.typebot.io` : viewerHost const iframeUrl = `${url}${parseQueryParams(hiddenVariables)}`
const iframeUrl = `${host}/${publishId}${parseQueryParams(hiddenVariables)}`
const iframe = document.createElement('iframe') const iframe = document.createElement('iframe')
iframe.setAttribute(loadWhenVisible ? 'data-src' : 'src', iframeUrl) iframe.setAttribute(loadWhenVisible ? 'data-src' : 'src', iframeUrl)
iframe.setAttribute('data-id', iframeParams.publishId) iframe.setAttribute('data-id', url)
const randomThreeLettersId = Math.random().toString(36).substring(7) const randomThreeLettersId = Math.random().toString(36).substring(7)
const uniqueId = `${publishId}-${randomThreeLettersId}` const uniqueId = `${url}-${randomThreeLettersId}`
iframe.setAttribute('id', uniqueId) iframe.setAttribute('id', uniqueId)
if (backgroundColor) iframe.style.backgroundColor = backgroundColor if (backgroundColor) iframe.style.backgroundColor = backgroundColor
iframe.classList.add('typebot-iframe') iframe.classList.add('typebot-iframe')

View File

@@ -1,7 +1,5 @@
export type IframeParams = { export type IframeParams = {
publishId: string url: string
isV1?: boolean
viewerHost?: string
backgroundColor?: string backgroundColor?: string
hiddenVariables?: { [key: string]: string | undefined } hiddenVariables?: { [key: string]: string | undefined }
customDomain?: string customDomain?: string

View File

@@ -1,40 +1,40 @@
import * as Typebot from "../../src"; import * as Typebot from '../../src'
beforeEach(() => { beforeEach(() => {
document.body.innerHTML = ""; document.body.innerHTML = ''
}); })
it("should have the corresponding custom color", () => { it('should have the corresponding custom color', () => {
expect.assertions(1); expect.assertions(1)
Typebot.initBubble({ Typebot.initBubble({
button: { color: "#222222" }, button: { color: '#222222' },
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
const buttonElement = document.querySelector( const buttonElement = document.querySelector(
"#typebot-bubble > button" '#typebot-bubble > button'
) as HTMLElement; ) as HTMLElement
expect(buttonElement.style.backgroundColor).toBe("rgb(34, 34, 34)"); expect(buttonElement.style.backgroundColor).toBe('rgb(34, 34, 34)')
}); })
it("should have the default svg icon", () => { it('should have the default svg icon', () => {
expect.assertions(1); expect.assertions(1)
Typebot.initBubble({ Typebot.initBubble({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
const buttonIconElement = document.querySelector( const buttonIconElement = document.querySelector(
"#typebot-bubble > button > .icon" '#typebot-bubble > button > .icon'
) as HTMLElement; ) as HTMLElement
expect(buttonIconElement.tagName).toBe("svg"); expect(buttonIconElement.tagName).toBe('svg')
}); })
it("should have the corresponding custom icon", () => { it('should have the corresponding custom icon', () => {
expect.assertions(1); expect.assertions(1)
Typebot.initBubble({ Typebot.initBubble({
button: { iconUrl: "https://web.com/icon.png" }, button: { iconUrl: 'https://web.com/icon.png' },
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
const buttonIconElement = document.querySelector( const buttonIconElement = document.querySelector(
"#typebot-bubble > button > .icon" '#typebot-bubble > button > .icon'
) as HTMLImageElement; ) as HTMLImageElement
expect(buttonIconElement.src).toBe("https://web.com/icon.png"); expect(buttonIconElement.src).toBe('https://web.com/icon.png')
}); })

View File

@@ -1,91 +1,91 @@
import * as Typebot from "../../src"; import * as Typebot from '../../src'
beforeEach(() => { beforeEach(() => {
document.body.innerHTML = ""; document.body.innerHTML = ''
}); })
describe("openBubble", () => { describe('openBubble', () => {
it("should add the opened bubble", () => { it('should add the opened bubble', () => {
expect.assertions(3); expect.assertions(3)
const { open } = Typebot.initBubble({ const { open } = Typebot.initBubble({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
const bubble = document.getElementById("typebot-bubble") as HTMLDivElement; const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains("iframe-opened")).toBe(false); expect(bubble.classList.contains('iframe-opened')).toBe(false)
open(); open()
expect(bubble.classList.contains("iframe-opened")).toBe(true); expect(bubble.classList.contains('iframe-opened')).toBe(true)
expect(open).not.toThrow(); expect(open).not.toThrow()
}); })
it("should hide the proactive message", () => { it('should hide the proactive message', () => {
expect.assertions(2); expect.assertions(2)
const { open, openProactiveMessage } = Typebot.initBubble({ const { open, openProactiveMessage } = Typebot.initBubble({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
proactiveMessage: { proactiveMessage: {
textContent: "Hi click here!", textContent: 'Hi click here!',
avatarUrl: "https://website.com/my-avatar.png", avatarUrl: 'https://website.com/my-avatar.png',
}, },
}); })
const bubble = document.getElementById("typebot-bubble") as HTMLDivElement; const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
if (openProactiveMessage) openProactiveMessage(); if (openProactiveMessage) openProactiveMessage()
expect(bubble.classList.contains("message-opened")).toBe(true); expect(bubble.classList.contains('message-opened')).toBe(true)
open(); open()
expect(bubble.classList.contains("message-opened")).toBe(false); expect(bubble.classList.contains('message-opened')).toBe(false)
}); })
}); })
describe("closeBubble", () => { describe('closeBubble', () => {
it("should remove the corresponding class", () => { it('should remove the corresponding class', () => {
expect.assertions(2); expect.assertions(2)
const { close, open } = Typebot.initBubble({ const { close, open } = Typebot.initBubble({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
open(); open()
const bubble = document.getElementById("typebot-bubble") as HTMLDivElement; const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains("iframe-opened")).toBe(true); expect(bubble.classList.contains('iframe-opened')).toBe(true)
close(); close()
expect(bubble.classList.contains("iframe-opened")).toBe(false); expect(bubble.classList.contains('iframe-opened')).toBe(false)
}); })
}); })
describe("openProactiveMessage", () => { describe('openProactiveMessage', () => {
it("should add the opened className", () => { it('should add the opened className', () => {
expect.assertions(1); expect.assertions(1)
const { openProactiveMessage } = Typebot.initBubble({ const { openProactiveMessage } = Typebot.initBubble({
proactiveMessage: { proactiveMessage: {
textContent: "Hi click here!", textContent: 'Hi click here!',
}, },
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
const bubble = document.getElementById("typebot-bubble") as HTMLDivElement; const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
if (openProactiveMessage) openProactiveMessage(); if (openProactiveMessage) openProactiveMessage()
expect(bubble.classList.contains("message-opened")).toBe(true); expect(bubble.classList.contains('message-opened')).toBe(true)
}); })
it("shouldn't be returned if no message", () => { it("shouldn't be returned if no message", () => {
expect.assertions(1); expect.assertions(1)
const { openProactiveMessage } = Typebot.initBubble({ const { openProactiveMessage } = Typebot.initBubble({
publishId: "typebot-id", url: 'typebot-id',
}); })
expect(openProactiveMessage).toBeUndefined(); expect(openProactiveMessage).toBeUndefined()
}); })
}); })
describe("Request commands afterwards", () => { describe('Request commands afterwards', () => {
it("should return defined commands", () => { it('should return defined commands', () => {
Typebot.initBubble({ Typebot.initBubble({
proactiveMessage: { proactiveMessage: {
textContent: "Hi click here!", textContent: 'Hi click here!',
}, },
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
const { close, open, openProactiveMessage } = Typebot.getBubbleActions(); const { close, open, openProactiveMessage } = Typebot.getBubbleActions()
expect(close).toBeDefined(); expect(close).toBeDefined()
expect(open).toBeDefined(); expect(open).toBeDefined()
expect(openProactiveMessage).toBeDefined(); expect(openProactiveMessage).toBeDefined()
open(); open()
const bubble = document.getElementById("typebot-bubble") as HTMLDivElement; const bubble = document.getElementById('typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains("iframe-opened")).toBe(true); expect(bubble.classList.contains('iframe-opened')).toBe(true)
}); })
}); })

View File

@@ -7,7 +7,7 @@ describe('initBubble', () => {
it('should initialize a bubble embed', () => { it('should initialize a bubble embed', () => {
expect.assertions(2) expect.assertions(2)
Typebot.initBubble({ publishId: 'typebot-id' }) Typebot.initBubble({ url: 'https://typebot.io/typebot-id' })
const bubbleElement = document.getElementById('typebot-bubble') const bubbleElement = document.getElementById('typebot-bubble')
const frame = document.getElementsByTagName('iframe')[0] const frame = document.getElementsByTagName('iframe')[0]
expect(frame).toBeDefined() expect(frame).toBeDefined()
@@ -17,14 +17,14 @@ describe('initBubble', () => {
it('should overwrite bubble if exists', () => { it('should overwrite bubble if exists', () => {
expect.assertions(2) expect.assertions(2)
Typebot.initBubble({ Typebot.initBubble({
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
hiddenVariables: { var1: 'test' }, hiddenVariables: { var1: 'test' },
}) })
Typebot.initBubble({ publishId: 'typebot-id2' }) Typebot.initBubble({ url: 'https://typebot.io/typebot-id2' })
const frames = document.getElementsByTagName('iframe') const frames = document.getElementsByTagName('iframe')
expect(frames).toHaveLength(1) expect(frames).toHaveLength(1)
expect(frames[0].dataset.src).toBe( expect(frames[0].dataset.src).toBe(
'https://typebot-viewer.vercel.app/typebot-id2?hn=localhost' 'https://typebot.io/typebot-id2?hn=localhost'
) )
}) })
@@ -32,7 +32,7 @@ describe('initBubble', () => {
expect.assertions(3) expect.assertions(3)
Typebot.initBubble({ Typebot.initBubble({
autoOpenDelay: 1000, autoOpenDelay: 1000,
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
}) })
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains('iframe-opened')).toBe(false) expect(bubble.classList.contains('iframe-opened')).toBe(false)
@@ -49,7 +49,7 @@ describe('initBubble', () => {
localStorage.setItem(Typebot.localStorageKeys.rememberClose, 'true') localStorage.setItem(Typebot.localStorageKeys.rememberClose, 'true')
Typebot.initBubble({ Typebot.initBubble({
autoOpenDelay: 1000, autoOpenDelay: 1000,
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
}) })
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
await new Promise((r) => setTimeout(r, 1500)) await new Promise((r) => setTimeout(r, 1500))

View File

@@ -8,7 +8,7 @@ it('should create the message', () => {
expect.assertions(2) expect.assertions(2)
Typebot.initBubble({ Typebot.initBubble({
proactiveMessage: { textContent: 'Hi click here!' }, proactiveMessage: { textContent: 'Hi click here!' },
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
}) })
const paragraphElement = document.querySelector( const paragraphElement = document.querySelector(
'#typebot-bubble > .proactive-message > p' '#typebot-bubble > .proactive-message > p'
@@ -27,7 +27,7 @@ it('should have the corresponding avatar', () => {
textContent: 'Hi click here!', textContent: 'Hi click here!',
avatarUrl: 'https://website.com/my-avatar.png', avatarUrl: 'https://website.com/my-avatar.png',
}, },
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
}) })
const avatarElement = document.querySelector( const avatarElement = document.querySelector(
'#typebot-bubble > .proactive-message > img' '#typebot-bubble > .proactive-message > img'
@@ -41,7 +41,7 @@ it("shouldn't have opened class if delay not defined", () => {
proactiveMessage: { proactiveMessage: {
textContent: 'Hi click here!', textContent: 'Hi click here!',
}, },
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
}) })
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains('message-opened')).toBe(false) expect(bubble.classList.contains('message-opened')).toBe(false)
@@ -54,7 +54,7 @@ it('should show almost immediately if delay is 0', async () => {
textContent: 'Hi click here!', textContent: 'Hi click here!',
delay: 0, delay: 0,
}, },
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
}) })
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
await new Promise((r) => setTimeout(r, 1)) await new Promise((r) => setTimeout(r, 1))
@@ -68,7 +68,7 @@ it('show after the corresponding delay', async () => {
textContent: 'Hi click here!', textContent: 'Hi click here!',
delay: 1000, delay: 1000,
}, },
publishId: 'typebot-id', url: 'https://typebot.io/typebot-id',
}) })
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
expect(bubble.classList.contains('message-opened')).toBe(false) expect(bubble.classList.contains('message-opened')).toBe(false)

View File

@@ -1,86 +1,94 @@
import { initContainer } from "../src/embedTypes/container"; import { initContainer } from '../src/embedTypes/container'
const observe = jest.fn(); const observe = jest.fn()
const unobserve = jest.fn(); const unobserve = jest.fn()
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
window.IntersectionObserver = jest.fn(() => ({ window.IntersectionObserver = jest.fn(() => ({
observe, observe,
unobserve, unobserve,
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
})) as any; })) as any
describe("initContainer", () => { describe('initContainer', () => {
beforeEach(() => (document.body.innerHTML = ``)); beforeEach(() => (document.body.innerHTML = ``))
it("should initialize a valid typebot container", () => { it('should initialize a valid typebot container', () => {
expect.assertions(3); expect.assertions(3)
const containerId = "container-id"; const containerId = 'container-id'
document.body.innerHTML = `<div id="${containerId}"></div>`; document.body.innerHTML = `<div id="${containerId}"></div>`
const iframe = initContainer(containerId, { publishId: "typebot-id" }); const iframe = initContainer(containerId, {
const container = document.getElementById(containerId); url: 'https://typebot.io/typebot-id',
expect(container?.children).toHaveLength(1); })
expect(container?.children[0].tagName).toBe("IFRAME"); const container = document.getElementById(containerId)
expect(iframe).toBeDefined(); expect(container?.children).toHaveLength(1)
}); expect(container?.children[0].tagName).toBe('IFRAME')
expect(iframe).toBeDefined()
})
it("should return undefined if container doesn't exist", () => { it("should return undefined if container doesn't exist", () => {
expect.assertions(1); expect.assertions(1)
const containerId = "container-id"; const containerId = 'container-id'
const iframe = initContainer(containerId, { publishId: "typebot-id" });
expect(iframe).toBeUndefined();
});
it("should return exisiting container", () => {
expect.assertions(1);
const containerId = "container-id";
document.body.innerHTML = `<div id="${containerId}"></div>`;
const iframe1 = initContainer(containerId, { publishId: "typebot-id" });
const iframe2 = initContainer(containerId, { publishId: "typebot-id" });
expect(iframe1?.id).toBe(iframe2?.id);
});
it("should create multiple containers correctly", () => {
expect.assertions(5);
const firstId = "container-1";
const secondId = "container-2";
document.body.innerHTML = `<div id="${firstId}"></div><div id="${secondId}"></div>`;
const firstIframeElement = initContainer(firstId, {
publishId: "typebot-id",
});
const secondIframeElement = initContainer(firstId, {
publishId: "typebot-id",
});
const thirdIframeElement = initContainer(secondId, {
publishId: "typebot-id",
});
expect(firstIframeElement).toBeDefined();
expect(secondIframeElement).toBeDefined();
expect(thirdIframeElement).toBeDefined();
expect(firstIframeElement?.id).toBe(secondIframeElement?.id);
expect(firstIframeElement?.id).not.toBe(thirdIframeElement?.id);
});
it("should be lazy loading by default", () => {
expect.assertions(2);
const containerId = "container";
document.body.innerHTML = `<div id="${containerId}"></div>`;
const iframe = initContainer(containerId, { const iframe = initContainer(containerId, {
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}) as HTMLIFrameElement; })
expect(iframe.dataset.src).toBeDefined(); expect(iframe).toBeUndefined()
expect(iframe.src).toBeFalsy(); })
});
it('should return exisiting container', () => {
expect.assertions(1)
const containerId = 'container-id'
document.body.innerHTML = `<div id="${containerId}"></div>`
const iframe1 = initContainer(containerId, {
url: 'https://typebot.io/typebot-id',
})
const iframe2 = initContainer(containerId, {
url: 'https://typebot.io/typebot-id',
})
expect(iframe1?.id).toBe(iframe2?.id)
})
it('should create multiple containers correctly', () => {
expect.assertions(5)
const firstId = 'container-1'
const secondId = 'container-2'
document.body.innerHTML = `<div id="${firstId}"></div><div id="${secondId}"></div>`
const firstIframeElement = initContainer(firstId, {
url: 'https://typebot.io/typebot-id',
})
const secondIframeElement = initContainer(firstId, {
url: 'https://typebot.io/typebot-id',
})
const thirdIframeElement = initContainer(secondId, {
url: 'https://typebot.io/typebot-id',
})
expect(firstIframeElement).toBeDefined()
expect(secondIframeElement).toBeDefined()
expect(thirdIframeElement).toBeDefined()
expect(firstIframeElement?.id).toBe(secondIframeElement?.id)
expect(firstIframeElement?.id).not.toBe(thirdIframeElement?.id)
})
it('should be lazy loading by default', () => {
expect.assertions(2)
const containerId = 'container'
document.body.innerHTML = `<div id="${containerId}"></div>`
const iframe = initContainer(containerId, {
url: 'https://typebot.io/typebot-id',
}) as HTMLIFrameElement
expect(iframe.dataset.src).toBeDefined()
expect(iframe.src).toBeFalsy()
})
it("shouldn't be lazy if setting param to false", () => { it("shouldn't be lazy if setting param to false", () => {
expect.assertions(2); expect.assertions(2)
const containerId = "container"; const containerId = 'container'
document.body.innerHTML = `<div id="${containerId}"></div>`; document.body.innerHTML = `<div id="${containerId}"></div>`
const iframe = initContainer(containerId, { const iframe = initContainer(containerId, {
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
loadWhenVisible: false, loadWhenVisible: false,
}) as HTMLIFrameElement; }) as HTMLIFrameElement
expect(iframe.dataset.src).toBeUndefined(); expect(iframe.dataset.src).toBeUndefined()
expect(iframe.src).toBeTruthy(); expect(iframe.src).toBeTruthy()
}); })
}); })

View File

@@ -1,132 +1,134 @@
import { createIframe } from "../src/iframe"; import { createIframe } from '../src/iframe'
describe("createIframe", () => { describe('createIframe', () => {
it("should create a valid iframe element", () => { it('should create a valid iframe element', () => {
expect.assertions(3); expect.assertions(3)
const iframeElement = createIframe({ const iframeElement = createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
expect(iframeElement.tagName).toBe("IFRAME"); expect(iframeElement.tagName).toBe('IFRAME')
expect(iframeElement.getAttribute("data-id")).toBe("typebot-id"); expect(iframeElement.getAttribute('data-id')).toBe(
expect(iframeElement.getAttribute("src")).toBe( 'https://typebot.io/typebot-id'
"https://typebot-viewer.vercel.app/typebot-id?hn=localhost" )
); expect(iframeElement.getAttribute('src')).toBe(
}); 'https://typebot.io/typebot-id?hn=localhost'
)
})
it("should parse the right src prop if custom domain and starterVariables", () => { it('should parse the right src prop if custom domain and starterVariables', () => {
expect.assertions(1); expect.assertions(1)
const iframes = [ const iframes = [
createIframe({ createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
hiddenVariables: { var1: "value1", var2: "value2", var3: undefined }, hiddenVariables: { var1: 'value1', var2: 'value2', var3: undefined },
}), }),
]; ]
expect(iframes[0].getAttribute("src")).toBe( expect(iframes[0].getAttribute('src')).toBe(
"https://typebot-viewer.vercel.app/typebot-id?hn=localhost&var1=value1&var2=value2" 'https://typebot.io/typebot-id?hn=localhost&var1=value1&var2=value2'
); )
}); })
it("should have a custom background color if defined", () => { it('should have a custom background color if defined', () => {
expect.assertions(1); expect.assertions(1)
const iframeElement = createIframe({ const iframeElement = createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
backgroundColor: "green", backgroundColor: 'green',
}); })
expect(iframeElement.style.backgroundColor).toBe("green"); expect(iframeElement.style.backgroundColor).toBe('green')
}); })
it("should have a lazy loading behavior if defined", () => { it('should have a lazy loading behavior if defined', () => {
expect.assertions(2); expect.assertions(2)
const iframeElement = createIframe({ const iframeElement = createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
loadWhenVisible: true, loadWhenVisible: true,
}); })
expect(iframeElement.getAttribute("data-src")).toBe( expect(iframeElement.getAttribute('data-src')).toBe(
"https://typebot-viewer.vercel.app/typebot-id?hn=localhost" 'https://typebot.io/typebot-id?hn=localhost'
); )
expect(iframeElement.getAttribute("src")).toBeFalsy(); expect(iframeElement.getAttribute('src')).toBeFalsy()
}); })
it("should redirect on event", async () => { it('should redirect on event', async () => {
expect.assertions(1); expect.assertions(1)
createIframe({ createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
window.open = jest.fn(); window.open = jest.fn()
window.postMessage( window.postMessage(
{ {
from: "typebot", from: 'typebot',
redirectUrl: "https://google.fr", redirectUrl: 'https://google.fr',
}, },
"*" '*'
); )
await new Promise((r) => setTimeout(r, 1)); await new Promise((r) => setTimeout(r, 1))
expect(window.open).toHaveBeenCalledWith("https://google.fr"); expect(window.open).toHaveBeenCalledWith('https://google.fr')
}); })
it("should trigger var callback on var event", async () => { it('should trigger var callback on var event', async () => {
expect.assertions(2); expect.assertions(2)
let n, v; let n, v
createIframe({ createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
onNewVariableValue: ({ name, value }) => { onNewVariableValue: ({ name, value }) => {
v = value; v = value
n = name; n = name
}, },
}); })
window.postMessage( window.postMessage(
{ {
from: "typebot", from: 'typebot',
newVariableValue: { name: "varName", value: "varValue" }, newVariableValue: { name: 'varName', value: 'varValue' },
}, },
"*" '*'
); )
await new Promise((r) => setTimeout(r, 1)); await new Promise((r) => setTimeout(r, 1))
expect(n).toBe("varName"); expect(n).toBe('varName')
expect(v).toBe("varValue"); expect(v).toBe('varValue')
}); })
it("should notify when video played", async () => { it('should notify when video played', async () => {
expect.assertions(1); expect.assertions(1)
let hit = false; let hit = false
createIframe({ createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
onVideoPlayed: () => { onVideoPlayed: () => {
hit = true; hit = true
}, },
}); })
window.postMessage( window.postMessage(
{ {
from: "typebot", from: 'typebot',
videoPlayed: true, videoPlayed: true,
}, },
"*" '*'
); )
await new Promise((r) => setTimeout(r, 1)); await new Promise((r) => setTimeout(r, 1))
expect(hit).toBe(true); expect(hit).toBe(true)
}); })
it("shouldn't execute callbacks if event from other than typebot", async () => { it("shouldn't execute callbacks if event from other than typebot", async () => {
expect.assertions(3); expect.assertions(3)
let n, v; let n, v
createIframe({ createIframe({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
onNewVariableValue: ({ name, value }) => { onNewVariableValue: ({ name, value }) => {
v = value; v = value
n = name; n = name
}, },
}); })
window.open = jest.fn(); window.open = jest.fn()
window.postMessage( window.postMessage(
{ {
redirectUrl: "https://google.fr", redirectUrl: 'https://google.fr',
newVariableValue: { name: "varName", value: "varValue" }, newVariableValue: { name: 'varName', value: 'varValue' },
}, },
"*" '*'
); )
await new Promise((r) => setTimeout(r, 1)); await new Promise((r) => setTimeout(r, 1))
expect(window.open).not.toHaveBeenCalled(); expect(window.open).not.toHaveBeenCalled()
expect(n).toBeUndefined(); expect(n).toBeUndefined()
expect(v).toBeUndefined(); expect(v).toBeUndefined()
}); })
}); })

View File

@@ -1,111 +1,114 @@
import { getPopupActions, initPopup } from "../src/embedTypes/popup"; import { getPopupActions, initPopup } from '../src/embedTypes/popup'
describe("initPopup", () => { describe('initPopup', () => {
beforeEach(() => { beforeEach(() => {
document.body.innerHTML = ""; document.body.innerHTML = ''
}); })
it("should return the popupElement with lazy iframe", () => { it('should return the popupElement with lazy iframe', () => {
expect.assertions(2); expect.assertions(2)
initPopup({ publishId: "typebot-id" }); initPopup({ url: 'https://typebot.io/typebot-id' })
const popupElement = document.getElementById("typebot-popup"); const popupElement = document.getElementById('typebot-popup')
const iframeElement = popupElement?.children[0] as HTMLIFrameElement; const iframeElement = popupElement?.children[0] as HTMLIFrameElement
expect(popupElement).toBeTruthy(); expect(popupElement).toBeTruthy()
expect(iframeElement.dataset.src).toBeDefined(); expect(iframeElement.dataset.src).toBeDefined()
}); })
it("should overwrite if exists", () => { it('should overwrite if exists', () => {
expect.assertions(2); expect.assertions(2)
initPopup({ publishId: "typebot-id", hiddenVariables: { test1: "yo" } }); initPopup({
initPopup({ publishId: "typebot-id2" }); url: 'https://typebot.io/typebot-id',
const elements = document.getElementsByTagName("iframe"); hiddenVariables: { test1: 'yo' },
expect(elements).toHaveLength(1); })
initPopup({ url: 'https://typebot.io/typebot-id2' })
const elements = document.getElementsByTagName('iframe')
expect(elements).toHaveLength(1)
expect(elements[0].dataset.src).toBe( expect(elements[0].dataset.src).toBe(
"https://typebot-viewer.vercel.app/typebot-id2?hn=localhost" 'https://typebot.io/typebot-id2?hn=localhost'
); )
}); })
it("shouldn't have opened classname if no delay", () => { it("shouldn't have opened classname if no delay", () => {
expect.assertions(1); expect.assertions(1)
initPopup({ publishId: "typebot-id" }); initPopup({ url: 'https://typebot.io/typebot-id' })
const popupElement = document.getElementById("typebot-popup"); const popupElement = document.getElementById('typebot-popup')
expect(popupElement?.classList.contains("opened")).toBe(false); expect(popupElement?.classList.contains('opened')).toBe(false)
}); })
it("should have the opened classname after the delay", async () => { it('should have the opened classname after the delay', async () => {
expect.assertions(2); expect.assertions(2)
initPopup({ delay: 500, publishId: "typebot-id" }); initPopup({ delay: 500, url: 'https://typebot.io/typebot-id' })
const popupElement = document.getElementById("typebot-popup"); const popupElement = document.getElementById('typebot-popup')
expect(popupElement?.classList.contains("opened")).toBe(false); expect(popupElement?.classList.contains('opened')).toBe(false)
await new Promise((r) => setTimeout(r, 1000)); await new Promise((r) => setTimeout(r, 1000))
expect(popupElement?.classList.contains("opened")).toBe(true); expect(popupElement?.classList.contains('opened')).toBe(true)
}); })
}); })
describe("openPopup", () => { describe('openPopup', () => {
beforeEach(() => { beforeEach(() => {
document.body.innerHTML = ""; document.body.innerHTML = ''
}); })
it("should add opened className and lazy load", () => { it('should add opened className and lazy load', () => {
expect.assertions(5); expect.assertions(5)
const { open } = initPopup({ publishId: "typebot-id" }); const { open } = initPopup({ url: 'https://typebot.io/typebot-id' })
const popupElement = document.getElementById("typebot-popup"); const popupElement = document.getElementById('typebot-popup')
expect(popupElement?.children[0].getAttribute("data-src")).toBeTruthy(); expect(popupElement?.children[0].getAttribute('data-src')).toBeTruthy()
open(); open()
expect(popupElement?.classList.contains("opened")).toBe(true); expect(popupElement?.classList.contains('opened')).toBe(true)
expect(document.body.style.overflowY).toBe("hidden"); expect(document.body.style.overflowY).toBe('hidden')
expect(popupElement?.children[0].getAttribute("data-src")).toBeFalsy(); expect(popupElement?.children[0].getAttribute('data-src')).toBeFalsy()
expect(open).not.toThrow(); expect(open).not.toThrow()
}); })
it("should still work if initializing a second time", () => { it('should still work if initializing a second time', () => {
expect.assertions(2); expect.assertions(2)
initPopup({ publishId: "typebot-id" }); initPopup({ url: 'https://typebot.io/typebot-id' })
const { open } = initPopup({ publishId: "typebot-id" }); const { open } = initPopup({ url: 'https://typebot.io/typebot-id' })
const popupElement = document.getElementById("typebot-popup"); const popupElement = document.getElementById('typebot-popup')
open(); open()
expect(popupElement?.classList.contains("opened")).toBe(true); expect(popupElement?.classList.contains('opened')).toBe(true)
expect(document.body.style.overflowY).toBe("hidden"); expect(document.body.style.overflowY).toBe('hidden')
}); })
}); })
describe("closePopup", () => { describe('closePopup', () => {
beforeEach(() => { beforeEach(() => {
document.body.innerHTML = ""; document.body.innerHTML = ''
}); })
it("shouldn remove opened className", () => { it('shouldn remove opened className', () => {
expect.assertions(2); expect.assertions(2)
const { close } = initPopup({ publishId: "typebot-id" }); const { close } = initPopup({ url: 'https://typebot.io/typebot-id' })
const popupElement = document.getElementById("typebot-popup"); const popupElement = document.getElementById('typebot-popup')
close(); close()
expect(popupElement?.classList.contains("opened")).toBe(false); expect(popupElement?.classList.contains('opened')).toBe(false)
expect(document.body.style.overflowY).toBe("auto"); expect(document.body.style.overflowY).toBe('auto')
}); })
it("should still work if initializing a second time", () => { it('should still work if initializing a second time', () => {
expect.assertions(2); expect.assertions(2)
initPopup({ publishId: "typebot-id" }); initPopup({ url: 'https://typebot.io/typebot-id' })
const { close } = initPopup({ publishId: "typebot-id" }); const { close } = initPopup({ url: 'https://typebot.io/typebot-id' })
const popupElement = document.getElementById("typebot-popup"); const popupElement = document.getElementById('typebot-popup')
close(); close()
expect(popupElement?.classList.contains("opened")).toBe(false); expect(popupElement?.classList.contains('opened')).toBe(false)
expect(document.body.style.overflowY).toBe("auto"); expect(document.body.style.overflowY).toBe('auto')
}); })
}); })
describe("Request commands afterwards", () => { describe('Request commands afterwards', () => {
it("should return defined commands", () => { it('should return defined commands', () => {
initPopup({ initPopup({
publishId: "typebot-id", url: 'https://typebot.io/typebot-id',
}); })
const { close, open } = getPopupActions(); const { close, open } = getPopupActions()
expect(close).toBeDefined(); expect(close).toBeDefined()
expect(open).toBeDefined(); expect(open).toBeDefined()
open(); open()
const popup = document.getElementById("typebot-popup") as HTMLDivElement; const popup = document.getElementById('typebot-popup') as HTMLDivElement
expect(popup.classList.contains("opened")).toBe(true); expect(popup.classList.contains('opened')).toBe(true)
}); })
}); })