feat(lib): ✨ Add auto open delay for bubble embed
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "typebot-js",
|
||||
"version": "2.1.3",
|
||||
"version": "2.1.4",
|
||||
"main": "dist/index.js",
|
||||
"unpkg": "dist/index.umd.min.js",
|
||||
"license": "MIT",
|
||||
|
@ -3,85 +3,91 @@ import {
|
||||
BubbleParams,
|
||||
localStorageKeys,
|
||||
ProactiveMessageParams,
|
||||
} from "../../types";
|
||||
import { createButton } from "./button";
|
||||
} from '../../types'
|
||||
import { createButton } from './button'
|
||||
import {
|
||||
closeIframe,
|
||||
createIframeContainer,
|
||||
loadTypebotIfFirstOpen,
|
||||
openIframe,
|
||||
} from "./iframe";
|
||||
} from './iframe'
|
||||
import {
|
||||
createProactiveMessage,
|
||||
openProactiveMessage,
|
||||
} from "./proactiveMessage";
|
||||
import "./style.css";
|
||||
} from './proactiveMessage'
|
||||
import './style.css'
|
||||
|
||||
export const initBubble = (params: BubbleParams): BubbleActions => {
|
||||
if (document.readyState !== "complete") {
|
||||
window.addEventListener("load", () => initBubble(params));
|
||||
return { close: () => {}, open: () => {} };
|
||||
if (document.readyState !== 'complete') {
|
||||
window.addEventListener('load', () => initBubble(params))
|
||||
return { close: () => {}, open: () => {} }
|
||||
}
|
||||
const existingBubble = document.getElementById("typebot-bubble") as
|
||||
const existingBubble = document.getElementById('typebot-bubble') as
|
||||
| HTMLDivElement
|
||||
| undefined;
|
||||
if (existingBubble) existingBubble.remove();
|
||||
| undefined
|
||||
if (existingBubble) existingBubble.remove()
|
||||
const { bubbleElement, proactiveMessageElement, iframeElement } =
|
||||
createBubble(params);
|
||||
createBubble(params)
|
||||
if (
|
||||
(params.autoOpenDelay || params.autoOpenDelay === 0) &&
|
||||
!hasBeenClosed()
|
||||
) {
|
||||
setRememberCloseInStorage()
|
||||
setTimeout(
|
||||
() => openIframe(bubbleElement, iframeElement),
|
||||
params.autoOpenDelay
|
||||
)
|
||||
}
|
||||
!document.body
|
||||
? (window.onload = () => document.body.appendChild(bubbleElement))
|
||||
: document.body.appendChild(bubbleElement);
|
||||
return getBubbleActions(
|
||||
bubbleElement,
|
||||
iframeElement,
|
||||
proactiveMessageElement
|
||||
);
|
||||
};
|
||||
: document.body.appendChild(bubbleElement)
|
||||
return getBubbleActions(bubbleElement, iframeElement, proactiveMessageElement)
|
||||
}
|
||||
|
||||
const createBubble = (
|
||||
params: BubbleParams
|
||||
): {
|
||||
bubbleElement: HTMLDivElement;
|
||||
iframeElement: HTMLIFrameElement;
|
||||
proactiveMessageElement?: HTMLDivElement;
|
||||
bubbleElement: HTMLDivElement
|
||||
iframeElement: HTMLIFrameElement
|
||||
proactiveMessageElement?: HTMLDivElement
|
||||
} => {
|
||||
const bubbleElement = document.createElement("div");
|
||||
bubbleElement.id = "typebot-bubble";
|
||||
const buttonElement = createButton(params.button);
|
||||
bubbleElement.appendChild(buttonElement);
|
||||
const bubbleElement = document.createElement('div')
|
||||
bubbleElement.id = 'typebot-bubble'
|
||||
const buttonElement = createButton(params.button)
|
||||
bubbleElement.appendChild(buttonElement)
|
||||
const proactiveMessageElement =
|
||||
params.proactiveMessage && !hasBeenClosed()
|
||||
? addProactiveMessage(params.proactiveMessage, bubbleElement)
|
||||
: undefined;
|
||||
const iframeElement = createIframeContainer(params);
|
||||
buttonElement.addEventListener("click", () =>
|
||||
: undefined
|
||||
const iframeElement = createIframeContainer(params)
|
||||
buttonElement.addEventListener('click', () =>
|
||||
onBubbleButtonClick(bubbleElement, iframeElement)
|
||||
);
|
||||
)
|
||||
if (proactiveMessageElement)
|
||||
proactiveMessageElement.addEventListener("click", () =>
|
||||
proactiveMessageElement.addEventListener('click', () =>
|
||||
onProactiveMessageClick(bubbleElement, iframeElement)
|
||||
);
|
||||
bubbleElement.appendChild(iframeElement);
|
||||
return { bubbleElement, proactiveMessageElement, iframeElement };
|
||||
};
|
||||
)
|
||||
bubbleElement.appendChild(iframeElement)
|
||||
return { bubbleElement, proactiveMessageElement, iframeElement }
|
||||
}
|
||||
|
||||
const onBubbleButtonClick = (
|
||||
bubble: HTMLDivElement,
|
||||
iframe: HTMLIFrameElement
|
||||
): void => {
|
||||
loadTypebotIfFirstOpen(iframe);
|
||||
bubble.classList.toggle("iframe-opened");
|
||||
bubble.classList.remove("message-opened");
|
||||
};
|
||||
loadTypebotIfFirstOpen(iframe)
|
||||
bubble.classList.toggle('iframe-opened')
|
||||
bubble.classList.remove('message-opened')
|
||||
}
|
||||
|
||||
const onProactiveMessageClick = (
|
||||
bubble: HTMLDivElement,
|
||||
iframe: HTMLIFrameElement
|
||||
): void => {
|
||||
loadTypebotIfFirstOpen(iframe);
|
||||
bubble.classList.add("iframe-opened");
|
||||
bubble.classList.remove("message-opened");
|
||||
};
|
||||
loadTypebotIfFirstOpen(iframe)
|
||||
bubble.classList.add('iframe-opened')
|
||||
bubble.classList.remove('message-opened')
|
||||
}
|
||||
|
||||
export const getBubbleActions = (
|
||||
bubbleElement?: HTMLDivElement,
|
||||
@ -90,29 +96,29 @@ export const getBubbleActions = (
|
||||
): BubbleActions => {
|
||||
const existingBubbleElement =
|
||||
bubbleElement ??
|
||||
(document.querySelector("#typebot-bubble") as HTMLDivElement);
|
||||
(document.querySelector('#typebot-bubble') as HTMLDivElement)
|
||||
const existingIframeElement =
|
||||
iframeElement ??
|
||||
(existingBubbleElement.querySelector(
|
||||
".typebot-iframe"
|
||||
) as HTMLIFrameElement);
|
||||
'.typebot-iframe'
|
||||
) as HTMLIFrameElement)
|
||||
const existingProactiveMessage =
|
||||
proactiveMessageElement ??
|
||||
document.querySelector("#typebot-bubble .proactive-message");
|
||||
document.querySelector('#typebot-bubble .proactive-message')
|
||||
return {
|
||||
openProactiveMessage: existingProactiveMessage
|
||||
? () => {
|
||||
openProactiveMessage(existingBubbleElement);
|
||||
openProactiveMessage(existingBubbleElement)
|
||||
}
|
||||
: undefined,
|
||||
open: () => {
|
||||
openIframe(existingBubbleElement, existingIframeElement);
|
||||
openIframe(existingBubbleElement, existingIframeElement)
|
||||
},
|
||||
close: () => {
|
||||
closeIframe(existingBubbleElement);
|
||||
closeIframe(existingBubbleElement)
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const addProactiveMessage = (
|
||||
proactiveMessage: ProactiveMessageParams,
|
||||
@ -121,14 +127,17 @@ const addProactiveMessage = (
|
||||
const proactiveMessageElement = createProactiveMessage(
|
||||
proactiveMessage,
|
||||
bubbleElement
|
||||
);
|
||||
bubbleElement.appendChild(proactiveMessageElement);
|
||||
return proactiveMessageElement;
|
||||
};
|
||||
)
|
||||
bubbleElement.appendChild(proactiveMessageElement)
|
||||
return proactiveMessageElement
|
||||
}
|
||||
|
||||
const hasBeenClosed = () => {
|
||||
const closeDecisionFromStorage = localStorage.getItem(
|
||||
localStorageKeys.rememberClose
|
||||
);
|
||||
return closeDecisionFromStorage ? true : false;
|
||||
};
|
||||
)
|
||||
return closeDecisionFromStorage ? true : false
|
||||
}
|
||||
|
||||
export const setRememberCloseInStorage = () =>
|
||||
localStorage.setItem(localStorageKeys.rememberClose, 'true')
|
||||
|
@ -1,66 +1,64 @@
|
||||
import { localStorageKeys, ProactiveMessageParams } from "../../types";
|
||||
import { closeSvgPath } from "./button";
|
||||
import { setRememberCloseInStorage } from '../chat/index'
|
||||
import { ProactiveMessageParams } from '../../types'
|
||||
import { closeSvgPath } from './button'
|
||||
|
||||
const createProactiveMessage = (
|
||||
params: ProactiveMessageParams,
|
||||
bubble: HTMLDivElement
|
||||
): HTMLDivElement => {
|
||||
const container = document.createElement("div");
|
||||
container.classList.add("proactive-message");
|
||||
if (params.delay !== undefined) setOpenTimeout(bubble, params);
|
||||
if (params.avatarUrl) container.appendChild(createAvatar(params.avatarUrl));
|
||||
if (params.rememberClose) setRememberCloseInStorage();
|
||||
container.appendChild(createTextElement(params.textContent));
|
||||
container.appendChild(createCloseButton(bubble));
|
||||
return container;
|
||||
};
|
||||
const container = document.createElement('div')
|
||||
container.classList.add('proactive-message')
|
||||
if (params.delay !== undefined) setOpenTimeout(bubble, params)
|
||||
if (params.avatarUrl) container.appendChild(createAvatar(params.avatarUrl))
|
||||
container.appendChild(createTextElement(params.textContent))
|
||||
container.appendChild(createCloseButton(bubble))
|
||||
return container
|
||||
}
|
||||
|
||||
const setOpenTimeout = (
|
||||
bubble: HTMLDivElement,
|
||||
params: ProactiveMessageParams
|
||||
) => {
|
||||
setTimeout(() => {
|
||||
openProactiveMessage(bubble);
|
||||
}, params.delay);
|
||||
};
|
||||
openProactiveMessage(bubble)
|
||||
}, params.delay)
|
||||
}
|
||||
|
||||
const createAvatar = (avatarUrl: string): HTMLImageElement => {
|
||||
const element = document.createElement("img");
|
||||
element.src = avatarUrl;
|
||||
return element;
|
||||
};
|
||||
const element = document.createElement('img')
|
||||
element.src = avatarUrl
|
||||
return element
|
||||
}
|
||||
|
||||
const createTextElement = (text: string): HTMLParagraphElement => {
|
||||
const element = document.createElement("p");
|
||||
element.innerHTML = text;
|
||||
return element;
|
||||
};
|
||||
const element = document.createElement('p')
|
||||
element.innerHTML = text
|
||||
return element
|
||||
}
|
||||
|
||||
const createCloseButton = (bubble: HTMLDivElement): HTMLButtonElement => {
|
||||
const button = document.createElement("button");
|
||||
button.classList.add("close-button");
|
||||
button.innerHTML = `<svg viewBox="0 0 512 512">${closeSvgPath}</svg>`;
|
||||
button.addEventListener("click", (e) => onCloseButtonClick(e, bubble));
|
||||
return button;
|
||||
};
|
||||
const button = document.createElement('button')
|
||||
button.classList.add('close-button')
|
||||
button.innerHTML = `<svg viewBox="0 0 512 512">${closeSvgPath}</svg>`
|
||||
button.addEventListener('click', (e) => onCloseButtonClick(e, bubble))
|
||||
return button
|
||||
}
|
||||
|
||||
const openProactiveMessage = (bubble: HTMLDivElement): void => {
|
||||
bubble.classList.add("message-opened");
|
||||
};
|
||||
bubble.classList.add('message-opened')
|
||||
}
|
||||
|
||||
const onCloseButtonClick = (
|
||||
e: Event,
|
||||
proactiveMessageElement: HTMLDivElement
|
||||
) => {
|
||||
e.stopPropagation();
|
||||
closeProactiveMessage(proactiveMessageElement);
|
||||
};
|
||||
e.stopPropagation()
|
||||
closeProactiveMessage(proactiveMessageElement)
|
||||
}
|
||||
|
||||
const closeProactiveMessage = (bubble: HTMLDivElement): void => {
|
||||
bubble.classList.remove("message-opened");
|
||||
};
|
||||
setRememberCloseInStorage()
|
||||
bubble.classList.remove('message-opened')
|
||||
}
|
||||
|
||||
const setRememberCloseInStorage = () =>
|
||||
localStorage.setItem(localStorageKeys.rememberClose, "true");
|
||||
|
||||
export { createProactiveMessage, openProactiveMessage, closeProactiveMessage };
|
||||
export { createProactiveMessage, openProactiveMessage, closeProactiveMessage }
|
||||
|
@ -1,58 +1,58 @@
|
||||
import { DataFromTypebot, IframeCallbacks, IframeParams } from "../types";
|
||||
import "./style.css";
|
||||
import { DataFromTypebot, IframeCallbacks, IframeParams } from '../types'
|
||||
import './style.css'
|
||||
|
||||
export const createIframe = ({
|
||||
backgroundColor,
|
||||
viewerHost = "https://typebot-viewer.vercel.app",
|
||||
viewerHost = 'https://typebot-viewer.vercel.app',
|
||||
isV1,
|
||||
...iframeParams
|
||||
}: IframeParams): HTMLIFrameElement => {
|
||||
const { publishId, loadWhenVisible, hiddenVariables } = iframeParams;
|
||||
const iframeUrl = `${viewerHost}/${publishId}${parseQueryParams(
|
||||
hiddenVariables
|
||||
)}`;
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.setAttribute(loadWhenVisible ? "data-src" : "src", iframeUrl);
|
||||
iframe.setAttribute("data-id", iframeParams.publishId);
|
||||
const randomThreeLettersId = Math.random().toString(36).substring(7);
|
||||
const uniqueId = `${publishId}-${randomThreeLettersId}`;
|
||||
iframe.setAttribute("id", uniqueId);
|
||||
if (backgroundColor) iframe.style.backgroundColor = backgroundColor;
|
||||
iframe.classList.add("typebot-iframe");
|
||||
const { onNewVariableValue, onVideoPlayed } = iframeParams;
|
||||
listenForTypebotMessages({ onNewVariableValue, onVideoPlayed });
|
||||
return iframe;
|
||||
};
|
||||
const { publishId, loadWhenVisible, hiddenVariables } = iframeParams
|
||||
const host = isV1 ? `https://bot.typebot.io` : viewerHost
|
||||
const iframeUrl = `${host}/${publishId}${parseQueryParams(hiddenVariables)}`
|
||||
const iframe = document.createElement('iframe')
|
||||
iframe.setAttribute(loadWhenVisible ? 'data-src' : 'src', iframeUrl)
|
||||
iframe.setAttribute('data-id', iframeParams.publishId)
|
||||
const randomThreeLettersId = Math.random().toString(36).substring(7)
|
||||
const uniqueId = `${publishId}-${randomThreeLettersId}`
|
||||
iframe.setAttribute('id', uniqueId)
|
||||
if (backgroundColor) iframe.style.backgroundColor = backgroundColor
|
||||
iframe.classList.add('typebot-iframe')
|
||||
const { onNewVariableValue, onVideoPlayed } = iframeParams
|
||||
listenForTypebotMessages({ onNewVariableValue, onVideoPlayed })
|
||||
return iframe
|
||||
}
|
||||
|
||||
const parseQueryParams = (starterVariables?: {
|
||||
[key: string]: string | undefined;
|
||||
[key: string]: string | undefined
|
||||
}): string => {
|
||||
return parseHostnameQueryParam() + parseStarterVariables(starterVariables);
|
||||
};
|
||||
return parseHostnameQueryParam() + parseStarterVariables(starterVariables)
|
||||
}
|
||||
|
||||
const parseHostnameQueryParam = () => {
|
||||
return `?hn=${window.location.hostname}`;
|
||||
};
|
||||
return `?hn=${window.location.hostname}`
|
||||
}
|
||||
|
||||
const parseStarterVariables = (starterVariables?: {
|
||||
[key: string]: string | undefined;
|
||||
[key: string]: string | undefined
|
||||
}) =>
|
||||
starterVariables
|
||||
? `&${Object.keys(starterVariables)
|
||||
.filter((key) => starterVariables[key])
|
||||
.map((key) => `${key}=${starterVariables[key]}`)
|
||||
.join("&")}`
|
||||
: "";
|
||||
.join('&')}`
|
||||
: ''
|
||||
|
||||
export const listenForTypebotMessages = (callbacks: IframeCallbacks) => {
|
||||
window.addEventListener("message", (event) => {
|
||||
const data = event.data as { from?: "typebot" } & DataFromTypebot;
|
||||
if (data.from === "typebot") processMessage(event.data, callbacks);
|
||||
});
|
||||
};
|
||||
window.addEventListener('message', (event) => {
|
||||
const data = event.data as { from?: 'typebot' } & DataFromTypebot
|
||||
if (data.from === 'typebot') processMessage(event.data, callbacks)
|
||||
})
|
||||
}
|
||||
|
||||
const processMessage = (data: DataFromTypebot, callbacks: IframeCallbacks) => {
|
||||
if (data.redirectUrl) window.open(data.redirectUrl);
|
||||
if (data.redirectUrl) window.open(data.redirectUrl)
|
||||
if (data.newVariableValue && callbacks.onNewVariableValue)
|
||||
callbacks.onNewVariableValue(data.newVariableValue);
|
||||
if (data.videoPlayed && callbacks.onVideoPlayed) callbacks.onVideoPlayed();
|
||||
};
|
||||
callbacks.onNewVariableValue(data.newVariableValue)
|
||||
if (data.videoPlayed && callbacks.onVideoPlayed) callbacks.onVideoPlayed()
|
||||
}
|
||||
|
@ -1,60 +1,62 @@
|
||||
export type IframeParams = {
|
||||
publishId: string;
|
||||
viewerHost?: string;
|
||||
backgroundColor?: string;
|
||||
hiddenVariables?: { [key: string]: string | undefined };
|
||||
customDomain?: string;
|
||||
loadWhenVisible?: boolean;
|
||||
} & IframeCallbacks;
|
||||
publishId: string
|
||||
isV1?: boolean
|
||||
viewerHost?: string
|
||||
backgroundColor?: string
|
||||
hiddenVariables?: { [key: string]: string | undefined }
|
||||
customDomain?: string
|
||||
loadWhenVisible?: boolean
|
||||
} & IframeCallbacks
|
||||
|
||||
export type IframeCallbacks = {
|
||||
onNewVariableValue?: (v: Variable) => void;
|
||||
onVideoPlayed?: () => void;
|
||||
};
|
||||
onNewVariableValue?: (v: Variable) => void
|
||||
onVideoPlayed?: () => void
|
||||
}
|
||||
|
||||
export type PopupParams = {
|
||||
delay?: number;
|
||||
} & IframeParams;
|
||||
delay?: number
|
||||
} & IframeParams
|
||||
|
||||
export type PopupActions = {
|
||||
open: () => void;
|
||||
close: () => void;
|
||||
};
|
||||
open: () => void
|
||||
close: () => void
|
||||
}
|
||||
|
||||
export type BubbleParams = {
|
||||
button?: ButtonParams;
|
||||
proactiveMessage?: ProactiveMessageParams;
|
||||
} & IframeParams;
|
||||
button?: ButtonParams
|
||||
proactiveMessage?: ProactiveMessageParams
|
||||
autoOpenDelay?: number
|
||||
} & IframeParams
|
||||
|
||||
export type ButtonParams = {
|
||||
color?: string;
|
||||
iconUrl?: string;
|
||||
};
|
||||
color?: string
|
||||
iconUrl?: string
|
||||
}
|
||||
|
||||
export type ProactiveMessageParams = {
|
||||
avatarUrl?: string;
|
||||
textContent: string;
|
||||
delay?: number;
|
||||
rememberClose?: boolean;
|
||||
};
|
||||
avatarUrl?: string
|
||||
textContent: string
|
||||
delay?: number
|
||||
rememberClose?: boolean
|
||||
}
|
||||
|
||||
export type BubbleActions = {
|
||||
open: () => void;
|
||||
close: () => void;
|
||||
openProactiveMessage?: () => void;
|
||||
};
|
||||
open: () => void
|
||||
close: () => void
|
||||
openProactiveMessage?: () => void
|
||||
}
|
||||
|
||||
export type Variable = {
|
||||
name: string;
|
||||
value: string;
|
||||
};
|
||||
name: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export type DataFromTypebot = {
|
||||
redirectUrl?: string;
|
||||
newVariableValue?: Variable;
|
||||
videoPlayed?: boolean;
|
||||
};
|
||||
redirectUrl?: string
|
||||
newVariableValue?: Variable
|
||||
videoPlayed?: boolean
|
||||
}
|
||||
|
||||
export const localStorageKeys = {
|
||||
rememberClose: "rememberClose",
|
||||
};
|
||||
rememberClose: 'rememberClose',
|
||||
}
|
||||
|
@ -1,30 +1,58 @@
|
||||
import * as Typebot from "../../src";
|
||||
import * as Typebot from '../../src'
|
||||
|
||||
describe("initBubble", () => {
|
||||
describe('initBubble', () => {
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
it("should initialize a bubble embed", () => {
|
||||
expect.assertions(2);
|
||||
Typebot.initBubble({ publishId: "typebot-id" });
|
||||
const bubbleElement = document.getElementById("typebot-bubble");
|
||||
const frame = document.getElementsByTagName("iframe")[0];
|
||||
expect(frame).toBeDefined();
|
||||
expect(bubbleElement).toBeDefined();
|
||||
});
|
||||
it('should initialize a bubble embed', () => {
|
||||
expect.assertions(2)
|
||||
Typebot.initBubble({ publishId: 'typebot-id' })
|
||||
const bubbleElement = document.getElementById('typebot-bubble')
|
||||
const frame = document.getElementsByTagName('iframe')[0]
|
||||
expect(frame).toBeDefined()
|
||||
expect(bubbleElement).toBeDefined()
|
||||
})
|
||||
|
||||
it("should overwrite bubble if exists", () => {
|
||||
expect.assertions(2);
|
||||
it('should overwrite bubble if exists', () => {
|
||||
expect.assertions(2)
|
||||
Typebot.initBubble({
|
||||
publishId: "typebot-id",
|
||||
hiddenVariables: { var1: "test" },
|
||||
});
|
||||
Typebot.initBubble({ publishId: "typebot-id2" });
|
||||
const frames = document.getElementsByTagName("iframe");
|
||||
expect(frames).toHaveLength(1);
|
||||
publishId: 'typebot-id',
|
||||
hiddenVariables: { var1: 'test' },
|
||||
})
|
||||
Typebot.initBubble({ publishId: 'typebot-id2' })
|
||||
const frames = document.getElementsByTagName('iframe')
|
||||
expect(frames).toHaveLength(1)
|
||||
expect(frames[0].dataset.src).toBe(
|
||||
"https://typebot-viewer.vercel.app/typebot-id2?hn=localhost"
|
||||
);
|
||||
});
|
||||
});
|
||||
'https://typebot-viewer.vercel.app/typebot-id2?hn=localhost'
|
||||
)
|
||||
})
|
||||
|
||||
it('show open after the corresponding delay', async () => {
|
||||
expect.assertions(3)
|
||||
Typebot.initBubble({
|
||||
autoOpenDelay: 1000,
|
||||
publishId: 'typebot-id',
|
||||
})
|
||||
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
|
||||
expect(bubble.classList.contains('iframe-opened')).toBe(false)
|
||||
await new Promise((r) => setTimeout(r, 1000))
|
||||
expect(bubble.classList.contains('iframe-opened')).toBe(true)
|
||||
const rememberCloseDecisionFromStorage = localStorage.getItem(
|
||||
Typebot.localStorageKeys.rememberClose
|
||||
)
|
||||
expect(rememberCloseDecisionFromStorage).toBe('true')
|
||||
})
|
||||
|
||||
it('should remember close decision if set to true', async () => {
|
||||
expect.assertions(1)
|
||||
localStorage.setItem(Typebot.localStorageKeys.rememberClose, 'true')
|
||||
Typebot.initBubble({
|
||||
autoOpenDelay: 1000,
|
||||
publishId: 'typebot-id',
|
||||
})
|
||||
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
|
||||
await new Promise((r) => setTimeout(r, 1500))
|
||||
expect(bubble.classList.contains('iframe-opened')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
@ -1,104 +1,77 @@
|
||||
import * as Typebot from "../../src";
|
||||
import * as Typebot from '../../src'
|
||||
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
it("should create the message", () => {
|
||||
expect.assertions(2);
|
||||
it('should create the message', () => {
|
||||
expect.assertions(2)
|
||||
Typebot.initBubble({
|
||||
proactiveMessage: { textContent: "Hi click here!" },
|
||||
publishId: "typebot-id",
|
||||
});
|
||||
proactiveMessage: { textContent: 'Hi click here!' },
|
||||
publishId: 'typebot-id',
|
||||
})
|
||||
const paragraphElement = document.querySelector(
|
||||
"#typebot-bubble > .proactive-message > p"
|
||||
);
|
||||
'#typebot-bubble > .proactive-message > p'
|
||||
)
|
||||
const closeButton = document.querySelector(
|
||||
"#typebot-bubble > .proactive-message > .close-button"
|
||||
);
|
||||
expect(paragraphElement?.textContent).toBe("Hi click here!");
|
||||
expect(closeButton).toBeTruthy();
|
||||
});
|
||||
'#typebot-bubble > .proactive-message > .close-button'
|
||||
)
|
||||
expect(paragraphElement?.textContent).toBe('Hi click here!')
|
||||
expect(closeButton).toBeTruthy()
|
||||
})
|
||||
|
||||
it("should have the corresponding avatar", () => {
|
||||
expect.assertions(1);
|
||||
it('should have the corresponding avatar', () => {
|
||||
expect.assertions(1)
|
||||
Typebot.initBubble({
|
||||
proactiveMessage: {
|
||||
textContent: "Hi click here!",
|
||||
avatarUrl: "https://website.com/my-avatar.png",
|
||||
textContent: 'Hi click here!',
|
||||
avatarUrl: 'https://website.com/my-avatar.png',
|
||||
},
|
||||
publishId: "typebot-id",
|
||||
});
|
||||
publishId: 'typebot-id',
|
||||
})
|
||||
const avatarElement = document.querySelector(
|
||||
"#typebot-bubble > .proactive-message > img"
|
||||
) as HTMLImageElement;
|
||||
expect(avatarElement.src).toBe("https://website.com/my-avatar.png");
|
||||
});
|
||||
'#typebot-bubble > .proactive-message > img'
|
||||
) as HTMLImageElement
|
||||
expect(avatarElement.src).toBe('https://website.com/my-avatar.png')
|
||||
})
|
||||
|
||||
it("shouldn't have opened class if delay not defined", () => {
|
||||
expect.assertions(1);
|
||||
expect.assertions(1)
|
||||
Typebot.initBubble({
|
||||
proactiveMessage: {
|
||||
textContent: "Hi click here!",
|
||||
textContent: 'Hi click here!',
|
||||
},
|
||||
publishId: "typebot-id",
|
||||
});
|
||||
const bubble = document.querySelector("#typebot-bubble") as HTMLDivElement;
|
||||
expect(bubble.classList.contains("message-opened")).toBe(false);
|
||||
});
|
||||
publishId: 'typebot-id',
|
||||
})
|
||||
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
|
||||
expect(bubble.classList.contains('message-opened')).toBe(false)
|
||||
})
|
||||
|
||||
it("should show almost immediately if delay is 0", async () => {
|
||||
expect.assertions(1);
|
||||
it('should show almost immediately if delay is 0', async () => {
|
||||
expect.assertions(1)
|
||||
Typebot.initBubble({
|
||||
proactiveMessage: {
|
||||
textContent: "Hi click here!",
|
||||
textContent: 'Hi click here!',
|
||||
delay: 0,
|
||||
},
|
||||
publishId: "typebot-id",
|
||||
});
|
||||
const bubble = document.querySelector("#typebot-bubble") as HTMLDivElement;
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
expect(bubble.classList.contains("message-opened")).toBe(true);
|
||||
});
|
||||
publishId: 'typebot-id',
|
||||
})
|
||||
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
|
||||
await new Promise((r) => setTimeout(r, 1))
|
||||
expect(bubble.classList.contains('message-opened')).toBe(true)
|
||||
})
|
||||
|
||||
it("show after the corresponding delay", async () => {
|
||||
expect.assertions(2);
|
||||
it('show after the corresponding delay', async () => {
|
||||
expect.assertions(2)
|
||||
Typebot.initBubble({
|
||||
proactiveMessage: {
|
||||
textContent: "Hi click here!",
|
||||
textContent: 'Hi click here!',
|
||||
delay: 1000,
|
||||
},
|
||||
publishId: "typebot-id",
|
||||
});
|
||||
const bubble = document.querySelector("#typebot-bubble") as HTMLDivElement;
|
||||
expect(bubble.classList.contains("message-opened")).toBe(false);
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
expect(bubble.classList.contains("message-opened")).toBe(true);
|
||||
});
|
||||
|
||||
it("should remember close decision if set to true", () => {
|
||||
expect.assertions(2);
|
||||
Typebot.initBubble({
|
||||
proactiveMessage: {
|
||||
textContent: "Hi click here!",
|
||||
delay: 1000,
|
||||
},
|
||||
publishId: "typebot-id",
|
||||
});
|
||||
const rememberCloseDecisionFromStorage = localStorage.getItem(
|
||||
Typebot.localStorageKeys.rememberClose
|
||||
);
|
||||
expect(rememberCloseDecisionFromStorage).toBeNull();
|
||||
Typebot.initBubble({
|
||||
proactiveMessage: {
|
||||
textContent: "Hi click here!",
|
||||
delay: 1000,
|
||||
rememberClose: true,
|
||||
},
|
||||
publishId: "typebot-id",
|
||||
});
|
||||
const refreshedRememberCloseDecisionFromStorage = localStorage.getItem(
|
||||
Typebot.localStorageKeys.rememberClose
|
||||
);
|
||||
expect(refreshedRememberCloseDecisionFromStorage).toBe("true");
|
||||
});
|
||||
publishId: 'typebot-id',
|
||||
})
|
||||
const bubble = document.querySelector('#typebot-bubble') as HTMLDivElement
|
||||
expect(bubble.classList.contains('message-opened')).toBe(false)
|
||||
await new Promise((r) => setTimeout(r, 1000))
|
||||
expect(bubble.classList.contains('message-opened')).toBe(true)
|
||||
})
|
||||
|
Reference in New Issue
Block a user