@formsort/web-embed-api
Advanced tools
Comparing version 2.2.0 to 2.2.1
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getMessageSender = void 0; | ||
var getMessageSender = function (iframe) { return function (message) { | ||
const getMessageSender = (iframe) => (message) => { | ||
var _a; | ||
(_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage(message, "*"); | ||
}; }; | ||
}; | ||
exports.getMessageSender = getMessageSender; |
@@ -18,3 +18,10 @@ import { AnalyticsEventType, IFlowAnswers } from '@formsort/constants'; | ||
} | ||
export declare const supportedAnalyticsEvents: readonly [AnalyticsEventType.FlowLoaded, AnalyticsEventType.FlowClosed, AnalyticsEventType.FlowFinalized, AnalyticsEventType.StepLoaded, AnalyticsEventType.StepCompleted]; | ||
export declare enum SupportedAnalyticsEvent { | ||
FlowLoaded = "FlowLoaded", | ||
FlowClosed = "FlowClosed", | ||
FlowFinalized = "FlowFinalized", | ||
StepLoaded = "StepLoaded", | ||
StepCompleted = "StepCompleted" | ||
} | ||
export declare const isSupportedEventType: (eventType: AnalyticsEventType | SupportedAnalyticsEvent) => eventType is SupportedAnalyticsEvent; | ||
interface IBaseEventData { | ||
@@ -26,9 +33,4 @@ answers: IFlowAnswers | undefined; | ||
} | ||
export interface IAnalyticsEventMap { | ||
FlowLoaded: (props: IBaseEventData) => void; | ||
FlowClosed: (props: IBaseEventData) => void; | ||
FlowFinalized: (props: IBaseEventData) => void; | ||
StepLoaded: (props: IBaseEventData) => void; | ||
StepCompleted: (props: IBaseEventData) => void; | ||
} | ||
export declare type IEventListener = (props: IBaseEventData) => void; | ||
export declare type IAnalyticsEventMap = Record<SupportedAnalyticsEvent, IEventListener>; | ||
export interface IEventMap extends IAnalyticsEventMap { | ||
@@ -35,0 +37,0 @@ redirect: (props: IRedirectEventData) => { |
157
lib/index.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.supportedAnalyticsEvents = void 0; | ||
var constants_1 = require("@formsort/constants"); | ||
var iframe_utils_1 = require("./iframe-utils"); | ||
var typeGuards_1 = require("./typeGuards"); | ||
var utils_1 = require("./utils"); | ||
var DEFAULT_FLOW_ORIGIN = "https://flow.formsort.com"; | ||
var DEFAULT_CONFIG = { | ||
exports.isSupportedEventType = exports.SupportedAnalyticsEvent = void 0; | ||
const constants_1 = require("@formsort/constants"); | ||
const iframe_utils_1 = require("./iframe-utils"); | ||
const typeGuards_1 = require("./typeGuards"); | ||
const utils_1 = require("./utils"); | ||
const DEFAULT_FLOW_DOMAIN = 'formsort.app'; | ||
const DEFAULT_CONFIG = { | ||
useHistoryAPI: false, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
origin: undefined, | ||
}; | ||
exports.supportedAnalyticsEvents = [ | ||
constants_1.AnalyticsEventType.FlowLoaded, | ||
constants_1.AnalyticsEventType.FlowClosed, | ||
constants_1.AnalyticsEventType.FlowFinalized, | ||
constants_1.AnalyticsEventType.StepLoaded, | ||
constants_1.AnalyticsEventType.StepCompleted, | ||
]; | ||
var isSupportedEventType = function (eventType) { | ||
return exports.supportedAnalyticsEvents.includes(eventType); | ||
}; | ||
var FormsortWebEmbed = function (rootEl, config) { | ||
if (config === void 0) { config = DEFAULT_CONFIG; } | ||
var iframeEl = document.createElement('iframe'); | ||
var style = config.style, autoHeight = config.autoHeight; | ||
var formsortOrigin = config.origin || DEFAULT_FLOW_ORIGIN; | ||
var SupportedAnalyticsEvent; | ||
(function (SupportedAnalyticsEvent) { | ||
SupportedAnalyticsEvent["FlowLoaded"] = "FlowLoaded"; | ||
SupportedAnalyticsEvent["FlowClosed"] = "FlowClosed"; | ||
SupportedAnalyticsEvent["FlowFinalized"] = "FlowFinalized"; | ||
SupportedAnalyticsEvent["StepLoaded"] = "StepLoaded"; | ||
SupportedAnalyticsEvent["StepCompleted"] = "StepCompleted"; | ||
})(SupportedAnalyticsEvent = exports.SupportedAnalyticsEvent || (exports.SupportedAnalyticsEvent = {})); | ||
const isSupportedEventType = (eventType) => eventType in SupportedAnalyticsEvent; | ||
exports.isSupportedEventType = isSupportedEventType; | ||
const FormsortWebEmbed = (rootEl, config = DEFAULT_CONFIG) => { | ||
const iframeEl = document.createElement('iframe'); | ||
const { style, autoHeight } = config; | ||
let formsortOrigin = config.origin; | ||
iframeEl.style.border = 'none'; | ||
if (style) { | ||
var _a = style.width, width = _a === void 0 ? '' : _a, _b = style.height, height = _b === void 0 ? '' : _b; | ||
const { width = '', height = '' } = style; | ||
iframeEl.style.width = width; | ||
@@ -35,15 +34,15 @@ iframeEl.style.height = height; | ||
rootEl.appendChild(iframeEl); | ||
var sendMessage = iframe_utils_1.getMessageSender(iframeEl); | ||
var eventListenersArrayMap = { | ||
FlowLoaded: [], | ||
FlowClosed: [], | ||
FlowFinalized: [], | ||
StepLoaded: [], | ||
StepCompleted: [], | ||
const sendMessage = (0, iframe_utils_1.getMessageSender)(iframeEl); | ||
const eventListenersArrayMap = { | ||
[SupportedAnalyticsEvent.FlowLoaded]: [], | ||
[SupportedAnalyticsEvent.FlowClosed]: [], | ||
[SupportedAnalyticsEvent.FlowFinalized]: [], | ||
[SupportedAnalyticsEvent.StepLoaded]: [], | ||
[SupportedAnalyticsEvent.StepCompleted]: [], | ||
redirect: [], | ||
unauthorized: [], | ||
}; | ||
var onTokenRequest = function (data) { | ||
const onTokenRequest = (data) => { | ||
var _a; | ||
var payload = data.payload; | ||
const { payload } = data; | ||
if (payload === constants_1.TokenRequestPayload.ID) { | ||
@@ -53,18 +52,17 @@ if ((_a = config.authentication) === null || _a === void 0 ? void 0 : _a.idToken) { | ||
type: constants_1.WebEmbedMessage.EMBED_TOKEN_RESPONSE_MSG, | ||
payload: { token: config.authentication.idToken } | ||
payload: { token: config.authentication.idToken }, | ||
}); | ||
} | ||
else { | ||
throw new Error("The loaded Flow requires authentication using an ID token, please provide it in config.authentication.idToken."); | ||
throw new Error(`The loaded Flow requires authentication using an ID token, please provide it in config.authentication.idToken.`); | ||
} | ||
} | ||
}; | ||
var onRedirectMessage = function (redirectData) { | ||
var url = redirectData.payload, answers = redirectData.answers; | ||
if (!utils_1.isEmpty(eventListenersArrayMap.redirect)) { | ||
var cancelRedirect = false; | ||
const onRedirectMessage = (redirectData) => { | ||
const { payload: url, answers } = redirectData; | ||
if (!(0, utils_1.isEmpty)(eventListenersArrayMap.redirect)) { | ||
let cancelRedirect = false; | ||
// Cancel redirect if any of the redirect listeners return `{ cancel: true }` | ||
for (var _i = 0, _a = eventListenersArrayMap.redirect; _i < _a.length; _i++) { | ||
var redirectListener = _a[_i]; | ||
var cancel = (redirectListener({ url: url, answers: answers }) || {}).cancel; | ||
for (const redirectListener of eventListenersArrayMap.redirect) { | ||
const { cancel } = redirectListener({ url, answers }) || {}; | ||
if (!cancelRedirect && cancel) { | ||
@@ -87,6 +85,5 @@ cancelRedirect = true; | ||
}; | ||
var onUnauthorizedMessage = function () { | ||
if (!utils_1.isEmpty(eventListenersArrayMap.unauthorized)) { | ||
for (var _i = 0, _a = eventListenersArrayMap.unauthorized; _i < _a.length; _i++) { | ||
var unathorizedListener = _a[_i]; | ||
const onUnauthorizedMessage = () => { | ||
if (!(0, utils_1.isEmpty)(eventListenersArrayMap.unauthorized)) { | ||
for (const unathorizedListener of eventListenersArrayMap.unauthorized) { | ||
unathorizedListener(); | ||
@@ -96,4 +93,4 @@ } | ||
}; | ||
var onResizeMessage = function (data) { | ||
var _a = data.payload, width = _a.width, height = _a.height; | ||
const onResizeMessage = (data) => { | ||
const { width, height } = data.payload; | ||
setSize(width, height); | ||
@@ -103,4 +100,4 @@ }; | ||
// and can be typed as MessageEvent<unknown> to increase type safety. | ||
var onWindowMessage = function (message) { | ||
var msgOrigin = message.origin, source = message.source, data = message.data; | ||
const onWindowMessage = (message) => { | ||
const { origin: msgOrigin, source, data } = message; | ||
if (source !== iframeEl.contentWindow) { | ||
@@ -114,18 +111,18 @@ // If we have multiple Formsort instances within a page, only listen to events coming | ||
} | ||
if (!typeGuards_1.isIWebEmbedEventData(data)) { | ||
if (!(0, typeGuards_1.isIWebEmbedEventData)(data)) { | ||
return; | ||
} | ||
if (typeGuards_1.isIFrameAnalyticsEventData(data)) { | ||
if ((0, typeGuards_1.isIFrameAnalyticsEventData)(data)) { | ||
onEventMessage(data); | ||
} | ||
else if (typeGuards_1.isIFrameTokenRequestEventData(data)) { | ||
else if ((0, typeGuards_1.isIFrameTokenRequestEventData)(data)) { | ||
onTokenRequest(data); | ||
} | ||
else if (typeGuards_1.isIFrameRedirectEventData(data)) { | ||
else if ((0, typeGuards_1.isIFrameRedirectEventData)(data)) { | ||
onRedirectMessage(data); | ||
} | ||
else if (typeGuards_1.isIFrameResizeEventData(data) && autoHeight) { | ||
else if ((0, typeGuards_1.isIFrameResizeEventData)(data) && autoHeight) { | ||
onResizeMessage(data); | ||
} | ||
else if (typeGuards_1.isIFrameUnauthorizedEventData(data)) { | ||
else if ((0, typeGuards_1.isIFrameUnauthorizedEventData)(data)) { | ||
onUnauthorizedMessage(); | ||
@@ -137,3 +134,3 @@ } | ||
} | ||
var setSize = function (width, height) { | ||
const setSize = (width, height) => { | ||
if (width !== undefined) { | ||
@@ -146,4 +143,4 @@ iframeEl.style.width = width.toString(); | ||
}; | ||
var getEventListenerArray = function (eventType) { | ||
if (isSupportedEventType(eventType)) { | ||
const getEventListenerArray = (eventType) => { | ||
if ((0, exports.isSupportedEventType)(eventType)) { | ||
return eventListenersArrayMap[eventType]; | ||
@@ -153,4 +150,4 @@ } | ||
}; | ||
var onEventMessage = function (eventData) { | ||
var eventType = eventData.eventType, answers = eventData.answers; | ||
const onEventMessage = (eventData) => { | ||
const { eventType, answers } = eventData; | ||
if (eventType === constants_1.AnalyticsEventType.FlowClosed) { | ||
@@ -160,26 +157,24 @@ removeListeners(); | ||
} | ||
var eventListenersArr = getEventListenerArray(eventType); | ||
const eventListenersArr = getEventListenerArray(eventType); | ||
if (!eventListenersArr) { | ||
return; | ||
} | ||
for (var _i = 0, eventListenersArr_1 = eventListenersArr; _i < eventListenersArr_1.length; _i++) { | ||
var eventListener = eventListenersArr_1[_i]; | ||
eventListener({ answers: answers }); | ||
for (const eventListener of eventListenersArr) { | ||
eventListener({ answers }); | ||
} | ||
}; | ||
var removeListeners = function () { | ||
const removeListeners = () => { | ||
window.removeEventListener('message', onWindowMessage); | ||
}; | ||
var loadFlow = function (clientLabel, flowLabel, variantLabel, queryParams) { | ||
var url = formsortOrigin + "/client/" + clientLabel + "/flow/" + flowLabel; | ||
const loadFlow = (clientLabel, flowLabel, variantLabel, queryParams) => { | ||
// We overwrite `formsortOrigin` because `onWindowMessage` will read it | ||
formsortOrigin = formsortOrigin || `https://${clientLabel}.${DEFAULT_FLOW_DOMAIN}`; | ||
let url = `${formsortOrigin}/client/${clientLabel}/flow/${flowLabel}`; | ||
if (variantLabel) { | ||
url += "/variant/" + variantLabel; | ||
url += `/variant/${variantLabel}`; | ||
} | ||
if (queryParams) { | ||
url += "?" + queryParams | ||
.map(function (_a) { | ||
var key = _a[0], value = _a[1]; | ||
return encodeURIComponent(key) + "=" + encodeURIComponent(value); | ||
}) | ||
.join('&'); | ||
url += `?${queryParams | ||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) | ||
.join('&')}`; | ||
} | ||
@@ -189,9 +184,9 @@ iframeEl.src = url; | ||
return { | ||
loadFlow: loadFlow, | ||
setSize: setSize, | ||
addEventListener: function (eventName, fn) { | ||
utils_1.addToArrayMap(eventListenersArrayMap, eventName, fn); | ||
loadFlow, | ||
setSize, | ||
addEventListener(eventName, fn) { | ||
(0, utils_1.addToArrayMap)(eventListenersArrayMap, eventName, fn); | ||
}, | ||
removeEventListener: function (eventName, eventListener) { | ||
utils_1.removeFromArrayMap(eventListenersArrayMap, eventName, eventListener); | ||
removeEventListener(eventName, eventListener) { | ||
(0, utils_1.removeFromArrayMap)(eventListenersArrayMap, eventName, eventListener); | ||
}, | ||
@@ -198,0 +193,0 @@ }; |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var constants_1 = require("@formsort/constants"); | ||
var _1 = require("."); | ||
var DEFAULT_FLOW_ORIGIN = 'https://flow.formsort.com'; | ||
var EMBEDDING_WINDOW_ORIGIN = 'https://test-origin.formsort.com'; | ||
var clientLabel = 'test-client'; | ||
var flowLabel = 'test-flow'; | ||
var variantLabel = 'test-variant'; | ||
describe('FormsortWebEmbed', function () { | ||
var pushStateSpy = jest | ||
const tslib_1 = require("tslib"); | ||
const constants_1 = require("@formsort/constants"); | ||
const _1 = tslib_1.__importStar(require(".")); | ||
const EMBEDDING_WINDOW_ORIGIN = 'https://test-origin.formsort.com'; | ||
const clientLabel = 'test-client'; | ||
const flowLabel = 'test-flow'; | ||
const variantLabel = 'test-variant'; | ||
describe('FormsortWebEmbed', () => { | ||
const pushStateSpy = jest | ||
.spyOn(window.history, 'pushState') | ||
.mockImplementation(jest.fn); | ||
var originalAddEventListener = window.addEventListener; | ||
var messageHandlers = []; | ||
const originalAddEventListener = window.addEventListener; | ||
let messageHandlers = []; | ||
jest | ||
.spyOn(window, 'addEventListener') | ||
.mockImplementation(function (type, listener) { | ||
.mockImplementation((type, listener) => { | ||
if (type === 'message') { | ||
@@ -76,14 +29,14 @@ messageHandlers.push(listener); | ||
*/ | ||
var mockPostMessage = function (msg) { | ||
messageHandlers.forEach(function (m) { | ||
const mockPostMessage = (msg) => { | ||
messageHandlers.forEach((m) => { | ||
m(msg); | ||
}); | ||
}; | ||
var location = window.location; | ||
beforeAll(function () { | ||
const { location } = window; | ||
beforeAll(() => { | ||
// @ts-ignore | ||
delete window.location; | ||
window.location = __assign(__assign({}, location), { assign: jest.fn(), origin: EMBEDDING_WINDOW_ORIGIN }); | ||
window.location = Object.assign(Object.assign({}, location), { assign: jest.fn(), origin: EMBEDDING_WINDOW_ORIGIN }); | ||
}); | ||
beforeEach(function () { | ||
beforeEach(() => { | ||
pushStateSpy.mockClear(); | ||
@@ -94,65 +47,65 @@ window.location.assign.mockClear(); | ||
}); | ||
afterAll(function () { | ||
afterAll(() => { | ||
window.location = location; | ||
}); | ||
test('does not load anything if instantiated without calling load', function () { | ||
_1.default(document.body); | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
test('does not load anything if instantiated without calling load', () => { | ||
(0, _1.default)(document.body); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
var iframe = iframes[0]; | ||
const iframe = iframes[0]; | ||
expect(iframe.src).toBe(''); | ||
}); | ||
test('mounts at the specified root element', function () { | ||
var rootEl = document.createElement('div'); | ||
test('mounts at the specified root element', () => { | ||
const rootEl = document.createElement('div'); | ||
document.body.appendChild(rootEl); | ||
_1.default(rootEl); | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
(0, _1.default)(rootEl); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
var iframe = iframes[0]; | ||
const iframe = iframes[0]; | ||
expect(iframe.src).toBe(''); | ||
expect(iframe.parentElement).toBe(rootEl); | ||
}); | ||
test('loads with a specific size if specified', function () { | ||
var width = '400px'; | ||
var height = '300px'; | ||
_1.default(document.body, { | ||
style: { width: width, height: height }, | ||
test('loads with a specific size if specified', () => { | ||
const width = '400px'; | ||
const height = '300px'; | ||
(0, _1.default)(document.body, { | ||
style: { width, height }, | ||
}); | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
var iframe = iframes[0]; | ||
const iframe = iframes[0]; | ||
expect(iframe.style.width).toBe(width); | ||
expect(iframe.style.height).toBe(height); | ||
}); | ||
test('Handles present-but-empty style', function () { | ||
_1.default(document.body, { | ||
test('Handles present-but-empty style', () => { | ||
(0, _1.default)(document.body, { | ||
style: {}, | ||
}); | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
var iframe = iframes[0]; | ||
const iframe = iframes[0]; | ||
expect(iframe.style.width).toBe(''); | ||
expect(iframe.style.height).toBe(''); | ||
}); | ||
test('loads a flow when load is called', function () { | ||
var loadFlow = _1.default(document.body).loadFlow; | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
test('loads a flow when load is called', () => { | ||
const { loadFlow } = (0, _1.default)(document.body); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
loadFlow(clientLabel, flowLabel); | ||
var iframe = iframes[0]; | ||
expect(iframe.src).toBe("https://flow.formsort.com/client/" + clientLabel + "/flow/" + flowLabel); | ||
const iframe = iframes[0]; | ||
expect(iframe.src).toBe(`https://${clientLabel}.formsort.app/client/${clientLabel}/flow/${flowLabel}`); | ||
}); | ||
test('loads and handles messages from custom origin when specified', function () { | ||
var customOrigin = 'http://localhost:4040'; | ||
var embed = _1.default(document.body, { | ||
test('loads and handles messages from custom origin when specified', () => { | ||
const customOrigin = 'http://localhost:4040'; | ||
const embed = (0, _1.default)(document.body, { | ||
origin: customOrigin, | ||
}); | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
var iframe = iframes[0]; | ||
expect(iframe.src).toBe(customOrigin + "/client/" + clientLabel + "/flow/" + flowLabel); | ||
var flowLoadedSpy = jest.fn(); | ||
embed.addEventListener('FlowLoaded', flowLoadedSpy); | ||
var msg = new MessageEvent('message', { | ||
const iframe = iframes[0]; | ||
expect(iframe.src).toBe(`${customOrigin}/client/${clientLabel}/flow/${flowLabel}`); | ||
const flowLoadedSpy = jest.fn(); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
@@ -169,19 +122,19 @@ origin: customOrigin, | ||
}); | ||
test('loads a variant when load is called', function () { | ||
var loadFlow = _1.default(document.body).loadFlow; | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
test('loads a variant when load is called', () => { | ||
const { loadFlow } = (0, _1.default)(document.body); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
loadFlow(clientLabel, flowLabel, variantLabel); | ||
var iframe = iframes[0]; | ||
expect(iframe.src).toBe("https://flow.formsort.com" + | ||
("/client/" + clientLabel + "/flow/" + flowLabel + "/variant/" + variantLabel)); | ||
const iframe = iframes[0]; | ||
expect(iframe.src).toBe(`https://${clientLabel}.formsort.app` + | ||
`/client/${clientLabel}/flow/${flowLabel}/variant/${variantLabel}`); | ||
}); | ||
test('loads with query parameters if specified', function () { | ||
var loadFlow = _1.default(document.body).loadFlow; | ||
var iframes = document.body.querySelectorAll('iframe'); | ||
test('loads with query parameters if specified', () => { | ||
const { loadFlow } = (0, _1.default)(document.body); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(1); | ||
var queryParamA = 'queryParamA'; | ||
var queryValueA = 'queryValueA'; | ||
var queryParamB = 'queryParamB'; | ||
var queryValueB = 'queryValueB'; | ||
const queryParamA = 'queryParamA'; | ||
const queryValueA = 'queryValueA'; | ||
const queryParamB = 'queryParamB'; | ||
const queryValueB = 'queryValueB'; | ||
loadFlow(clientLabel, flowLabel, undefined, [ | ||
@@ -191,449 +144,393 @@ [queryParamA, queryValueA], | ||
]); | ||
var iframe = iframes[0]; | ||
expect(iframe.src).toBe("https://flow.formsort.com" + | ||
("/client/" + clientLabel + "/flow/" + flowLabel) + | ||
("?" + queryParamA + "=" + queryValueA + "&" + queryParamB + "=" + queryValueB)); | ||
const iframe = iframes[0]; | ||
expect(iframe.src).toBe(`https://${clientLabel}.formsort.app` + | ||
`/client/${clientLabel}/flow/${flowLabel}` + | ||
`?${queryParamA}=${queryValueA}&${queryParamB}=${queryValueB}`); | ||
}); | ||
test('ignores events from unknown origins', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, flowLoadedSpy, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
flowLoadedSpy = jest.fn(); | ||
embed.addEventListener('FlowClosed', flowLoadedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: 'https://example.com', | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(flowLoadedSpy).toBeCalledTimes(0); | ||
return [2 /*return*/]; | ||
test('ignores events from unknown origins', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const flowLoadedSpy = jest.fn(); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowClosed, flowLoadedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: 'https://example.com', | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
}); }); | ||
test('ignores events without data', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, flowLoadedSpy, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
flowLoadedSpy = jest.fn(); | ||
embed.addEventListener('FlowLoaded', flowLoadedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: undefined, | ||
}); | ||
mockPostMessage(msg); | ||
expect(flowLoadedSpy).toBeCalledTimes(0); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg); | ||
expect(flowLoadedSpy).toBeCalledTimes(0); | ||
})); | ||
test('ignores events without data', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const flowLoadedSpy = jest.fn(); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: undefined, | ||
}); | ||
}); }); | ||
test('handles messages from multiple flows within the same window', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var firstEmbed, secondEmbed, iframes, secondFlowLabel, firstFlowIframe, secondFlowIframe, firstFlowFinalized, secondFlowFinalized, msg; | ||
return __generator(this, function (_a) { | ||
firstEmbed = _1.default(document.body); | ||
secondEmbed = _1.default(document.body); | ||
iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(2); | ||
secondFlowLabel = 'second-test-flow'; | ||
firstEmbed.loadFlow(clientLabel, flowLabel); | ||
secondEmbed.loadFlow(clientLabel, secondFlowLabel); | ||
firstFlowIframe = iframes[0]; | ||
expect(firstFlowIframe.src).toBe("https://flow.formsort.com/client/" + clientLabel + "/flow/" + flowLabel); | ||
secondFlowIframe = iframes[1]; | ||
expect(secondFlowIframe.src).toBe("https://flow.formsort.com/client/" + clientLabel + "/flow/" + secondFlowLabel); | ||
firstFlowFinalized = jest.fn(); | ||
firstEmbed.addEventListener('FlowFinalized', firstFlowFinalized); | ||
secondFlowFinalized = jest.fn(); | ||
secondEmbed.addEventListener('FlowFinalized', secondFlowFinalized); | ||
msg = new MessageEvent('message', { | ||
source: firstFlowIframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowFinalized, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
// We received a message from the first iframe, so only that frame should | ||
// have its callback called. | ||
expect(firstFlowFinalized).toBeCalledTimes(1); | ||
expect(secondFlowFinalized).toBeCalledTimes(0); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg); | ||
expect(flowLoadedSpy).toBeCalledTimes(0); | ||
})); | ||
test('handles messages from multiple flows within the same window', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const firstEmbed = (0, _1.default)(document.body); | ||
const secondEmbed = (0, _1.default)(document.body); | ||
const iframes = document.body.querySelectorAll('iframe'); | ||
expect(iframes.length).toBe(2); | ||
const secondFlowLabel = 'second-test-flow'; | ||
firstEmbed.loadFlow(clientLabel, flowLabel); | ||
secondEmbed.loadFlow(clientLabel, secondFlowLabel); | ||
const firstFlowIframe = iframes[0]; | ||
expect(firstFlowIframe.src).toBe(`https://${clientLabel}.formsort.app/client/${clientLabel}/flow/${flowLabel}`); | ||
const secondFlowIframe = iframes[1]; | ||
expect(secondFlowIframe.src).toBe(`https://${clientLabel}.formsort.app/client/${clientLabel}/flow/${secondFlowLabel}`); | ||
const firstFlowFinalized = jest.fn(); | ||
firstEmbed.addEventListener(_1.SupportedAnalyticsEvent.FlowFinalized, firstFlowFinalized); | ||
const secondFlowFinalized = jest.fn(); | ||
secondEmbed.addEventListener(_1.SupportedAnalyticsEvent.FlowFinalized, secondFlowFinalized); | ||
const msg = new MessageEvent('message', { | ||
source: firstFlowIframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowFinalized, | ||
}, | ||
}); | ||
}); }); | ||
test('handles flow loaded event', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, flowLoadedSpy, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
flowLoadedSpy = jest.fn(); | ||
embed.addEventListener('FlowLoaded', flowLoadedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(flowLoadedSpy).toBeCalledTimes(1); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg); | ||
// We received a message from the first iframe, so only that frame should | ||
// have its callback called. | ||
expect(firstFlowFinalized).toBeCalledTimes(1); | ||
expect(secondFlowFinalized).toBeCalledTimes(0); | ||
})); | ||
test('handles flow loaded event', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const flowLoadedSpy = jest.fn(); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
}); }); | ||
test('handles adding and removing event handlers', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, flowLoadedSpy1, flowLoadedSpy2, flowLoadedSpy3, msg1, msg2, msg3; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
flowLoadedSpy1 = jest.fn(); | ||
flowLoadedSpy2 = jest.fn(); | ||
flowLoadedSpy3 = jest.fn(); | ||
embed.addEventListener('FlowLoaded', flowLoadedSpy1); | ||
embed.addEventListener('FlowLoaded', flowLoadedSpy2); | ||
embed.addEventListener('FlowLoaded', flowLoadedSpy3); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg1 = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
mockPostMessage(msg1); | ||
expect(flowLoadedSpy1).toBeCalledTimes(1); | ||
expect(flowLoadedSpy2).toBeCalledTimes(1); | ||
expect(flowLoadedSpy3).toBeCalledTimes(1); | ||
// Remove second event listener | ||
embed.removeEventListener('FlowLoaded', flowLoadedSpy2); | ||
msg2 = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
mockPostMessage(msg2); | ||
expect(flowLoadedSpy1).toBeCalledTimes(2); | ||
// removed listener should not be called again | ||
expect(flowLoadedSpy2).toBeCalledTimes(1); | ||
expect(flowLoadedSpy3).toBeCalledTimes(2); | ||
// Remove rest of event listeners | ||
embed.removeEventListener('FlowLoaded', flowLoadedSpy1); | ||
embed.removeEventListener('FlowLoaded', flowLoadedSpy3); | ||
embed.removeEventListener('FlowLoaded', flowLoadedSpy2); | ||
msg3 = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
mockPostMessage(msg3); | ||
// removed listeners should not be called again | ||
expect(flowLoadedSpy1).toBeCalledTimes(2); | ||
expect(flowLoadedSpy2).toBeCalledTimes(1); | ||
expect(flowLoadedSpy3).toBeCalledTimes(2); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg); | ||
expect(flowLoadedSpy).toBeCalledTimes(1); | ||
})); | ||
test('handles adding and removing event handlers', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const flowLoadedSpy1 = jest.fn(); | ||
const flowLoadedSpy2 = jest.fn(); | ||
const flowLoadedSpy3 = jest.fn(); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy1); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy2); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy3); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg1 = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
}); }); | ||
test('handles flow finalized event', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, flowFinalizedSpy, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
flowFinalizedSpy = jest.fn(); | ||
embed.addEventListener('FlowFinalized', flowFinalizedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowFinalized, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(flowFinalizedSpy).toBeCalledTimes(1); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg1); | ||
expect(flowLoadedSpy1).toBeCalledTimes(1); | ||
expect(flowLoadedSpy2).toBeCalledTimes(1); | ||
expect(flowLoadedSpy3).toBeCalledTimes(1); | ||
// Remove second event listener | ||
embed.removeEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy2); | ||
const msg2 = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
}); }); | ||
test('handles flow closed event', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, removeEventListenerSpy, flowClosedSpy, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); | ||
flowClosedSpy = jest.fn(); | ||
embed.addEventListener('FlowClosed', flowClosedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowClosed, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(flowClosedSpy).toBeCalledTimes(1); | ||
expect(removeEventListenerSpy).toBeCalledTimes(1); | ||
expect(removeEventListenerSpy.mock.calls[0][0]).toBe('message'); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg2); | ||
expect(flowLoadedSpy1).toBeCalledTimes(2); | ||
// removed listener should not be called again | ||
expect(flowLoadedSpy2).toBeCalledTimes(1); | ||
expect(flowLoadedSpy3).toBeCalledTimes(2); | ||
// Remove rest of event listeners | ||
embed.removeEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy1); | ||
embed.removeEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy3); | ||
embed.removeEventListener(_1.SupportedAnalyticsEvent.FlowLoaded, flowLoadedSpy2); | ||
const msg3 = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
}); }); | ||
test('handles resize event when autoHeight is enabled', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, width, height, msg, newHeight, newWidth, heightMsg, widthMsg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body, { | ||
style: { width: '100px', height: '100px' }, | ||
autoHeight: true, | ||
}); | ||
iframe = document.body.querySelector('iframe'); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
width = '357px'; | ||
height = '733px'; | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width: width, | ||
height: height, | ||
}, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(iframe.style.width).toBe(width); | ||
expect(iframe.style.height).toBe(height); | ||
newHeight = '999px'; | ||
newWidth = '888px'; | ||
heightMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
height: newHeight, | ||
}, | ||
}, | ||
}); | ||
mockPostMessage(heightMsg); | ||
expect(iframe.style.width).toBe(width); | ||
expect(iframe.style.height).toBe(newHeight); | ||
widthMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width: newWidth, | ||
}, | ||
}, | ||
}); | ||
mockPostMessage(widthMsg); | ||
expect(iframe.style.width).toBe(newWidth); | ||
expect(iframe.style.height).toBe(newHeight); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg3); | ||
// removed listeners should not be called again | ||
expect(flowLoadedSpy1).toBeCalledTimes(2); | ||
expect(flowLoadedSpy2).toBeCalledTimes(1); | ||
expect(flowLoadedSpy3).toBeCalledTimes(2); | ||
})); | ||
test('handles flow finalized event', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const flowFinalizedSpy = jest.fn(); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowFinalized, flowFinalizedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowFinalized, | ||
}, | ||
}); | ||
}); }); | ||
test('ignores resize event when autoHeight is enabled', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var originalWidth, originalHeight, embed, iframe, newWidth, newHeight, msg; | ||
return __generator(this, function (_a) { | ||
originalWidth = '200px'; | ||
originalHeight = '300px'; | ||
embed = _1.default(document.body, { | ||
style: { width: originalWidth, height: originalHeight }, | ||
}); | ||
iframe = document.body.querySelector('iframe'); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
newWidth = '357px'; | ||
newHeight = '733px'; | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width: newWidth, | ||
height: newHeight, | ||
}, | ||
mockPostMessage(msg); | ||
expect(flowFinalizedSpy).toBeCalledTimes(1); | ||
})); | ||
test('handles flow closed event', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); | ||
const flowClosedSpy = jest.fn(); | ||
embed.addEventListener(_1.SupportedAnalyticsEvent.FlowClosed, flowClosedSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowClosed, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(flowClosedSpy).toBeCalledTimes(1); | ||
expect(removeEventListenerSpy).toBeCalledTimes(1); | ||
expect(removeEventListenerSpy.mock.calls[0][0]).toBe('message'); | ||
})); | ||
test('handles resize event when autoHeight is enabled', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body, { | ||
style: { width: '100px', height: '100px' }, | ||
autoHeight: true, | ||
}); | ||
const iframe = document.body.querySelector('iframe'); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const width = '357px'; | ||
const height = '733px'; | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width, | ||
height, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(iframe.style.width).toBe(originalWidth); | ||
expect(iframe.style.height).toBe(originalHeight); | ||
return [2 /*return*/]; | ||
}, | ||
}); | ||
}); }); | ||
test('handles redirecting to a URL', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectSpy, redirectUrl, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
redirectUrl = 'https://example.com'; | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
mockPostMessage(msg); | ||
expect(iframe.style.width).toBe(width); | ||
expect(iframe.style.height).toBe(height); | ||
// The resize message can be partial (for example, just height changes) | ||
// Make sure we can handle those. | ||
const newHeight = '999px'; | ||
const newWidth = '888px'; | ||
const heightMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
height: newHeight, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
expect(redirectSpy).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).toBeCalledTimes(1); | ||
expect(window.location.assign).toBeCalledWith(redirectUrl); | ||
return [2 /*return*/]; | ||
}, | ||
}); | ||
}); }); | ||
test('handles redirecting to a URL if no callback returns `{cancel: true}`', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectCallback1, redirectCallback2, redirectCallback3, redirectUrl, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
redirectCallback1 = jest.fn(function () { return ({ cancel: false }); }); | ||
redirectCallback2 = jest.fn(function () { return ({}); }); | ||
redirectCallback3 = jest.fn(function () { return ({}); }); | ||
embed.addEventListener('redirect', redirectCallback1); | ||
embed.addEventListener('redirect', redirectCallback2); | ||
embed.addEventListener('redirect', redirectCallback3); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
redirectUrl = 'https://example.com'; | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
mockPostMessage(heightMsg); | ||
expect(iframe.style.width).toBe(width); | ||
expect(iframe.style.height).toBe(newHeight); | ||
const widthMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width: newWidth, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectCallback1).toBeCalledTimes(1); | ||
expect(redirectCallback1).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback2).toBeCalledTimes(1); | ||
expect(redirectCallback2).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback3).toBeCalledTimes(1); | ||
expect(redirectCallback3).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).toBeCalledTimes(1); | ||
expect(window.location.assign).toBeCalledWith(redirectUrl); | ||
return [2 /*return*/]; | ||
}, | ||
}); | ||
}); }); | ||
test('Cancels redirect if callback returns `cancel: true`', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectUrl, redirectCallback, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
redirectUrl = 'https://example.com'; | ||
redirectCallback = jest.fn(function () { return ({ cancel: true }); }); | ||
embed.addEventListener('redirect', redirectCallback); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
mockPostMessage(widthMsg); | ||
expect(iframe.style.width).toBe(newWidth); | ||
expect(iframe.style.height).toBe(newHeight); | ||
})); | ||
test('ignores resize event when autoHeight is enabled', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const originalWidth = '200px'; | ||
const originalHeight = '300px'; | ||
const embed = (0, _1.default)(document.body, { | ||
style: { width: originalWidth, height: originalHeight }, | ||
}); | ||
const iframe = document.body.querySelector('iframe'); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const newWidth = '357px'; | ||
const newHeight = '733px'; | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width: newWidth, | ||
height: newHeight, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectCallback).toBeCalledTimes(1); | ||
expect(redirectCallback).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).not.toHaveBeenCalled(); | ||
return [2 /*return*/]; | ||
}, | ||
}); | ||
}); }); | ||
test('Cancels redirect if any callback returns `cancel: true`', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectUrl, redirectCallback1, redirectCallback2, redirectCallback3, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
redirectUrl = 'https://example.com'; | ||
redirectCallback1 = jest.fn(function () { return ({ cancel: false }); }); | ||
redirectCallback2 = jest.fn(function () { return ({ cancel: true }); }); | ||
redirectCallback3 = jest.fn(function () { return ({}); }); | ||
embed.addEventListener('redirect', redirectCallback1); | ||
embed.addEventListener('redirect', redirectCallback2); | ||
embed.addEventListener('redirect', redirectCallback3); | ||
mockPostMessage(msg); | ||
expect(iframe.style.width).toBe(originalWidth); | ||
expect(iframe.style.height).toBe(originalHeight); | ||
})); | ||
test('handles redirecting to a URL', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const redirectUrl = 'https://example.com'; | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
expect(redirectSpy).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).toBeCalledTimes(1); | ||
expect(window.location.assign).toBeCalledWith(redirectUrl); | ||
})); | ||
test('handles redirecting to a URL if no callback returns `{cancel: true}`', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const redirectCallback1 = jest.fn(() => ({ cancel: false })); | ||
const redirectCallback2 = jest.fn(() => ({})); | ||
const redirectCallback3 = jest.fn(() => ({})); | ||
embed.addEventListener('redirect', redirectCallback1); | ||
embed.addEventListener('redirect', redirectCallback2); | ||
embed.addEventListener('redirect', redirectCallback3); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const redirectUrl = 'https://example.com'; | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectCallback1).toBeCalledTimes(1); | ||
expect(redirectCallback1).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback2).toBeCalledTimes(1); | ||
expect(redirectCallback2).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback3).toBeCalledTimes(1); | ||
expect(redirectCallback3).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).toBeCalledTimes(1); | ||
expect(window.location.assign).toBeCalledWith(redirectUrl); | ||
})); | ||
test('Cancels redirect if callback returns `cancel: true`', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const redirectUrl = 'https://example.com'; | ||
const redirectCallback = jest.fn(() => ({ cancel: true })); | ||
embed.addEventListener('redirect', redirectCallback); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectCallback).toBeCalledTimes(1); | ||
expect(redirectCallback).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).not.toHaveBeenCalled(); | ||
})); | ||
test('Cancels redirect if any callback returns `cancel: true`', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const redirectUrl = 'https://example.com'; | ||
const redirectCallback1 = jest.fn(() => ({ cancel: false })); | ||
const redirectCallback2 = jest.fn(() => ({ cancel: true })); | ||
const redirectCallback3 = jest.fn(() => ({})); | ||
embed.addEventListener('redirect', redirectCallback1); | ||
embed.addEventListener('redirect', redirectCallback2); | ||
embed.addEventListener('redirect', redirectCallback3); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectCallback1).toBeCalledTimes(1); | ||
expect(redirectCallback1).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback2).toBeCalledTimes(1); | ||
expect(redirectCallback2).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback3).toBeCalledTimes(1); | ||
expect(redirectCallback3).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).not.toHaveBeenCalled(); | ||
})); | ||
describe.each(Object.values(_1.SupportedAnalyticsEvent))('%s', (event) => { | ||
const sendMessage = (eventType, answers) => { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const eventListenerSpy = jest.fn(); | ||
embed.addEventListener(eventType, eventListenerSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType, | ||
answers, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectCallback1).toBeCalledTimes(1); | ||
expect(redirectCallback1).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback2).toBeCalledTimes(1); | ||
expect(redirectCallback2).toBeCalledWith({ url: redirectUrl }); | ||
expect(redirectCallback3).toBeCalledTimes(1); | ||
expect(redirectCallback3).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).not.toHaveBeenCalled(); | ||
return [2 /*return*/]; | ||
expect(eventListenerSpy).toBeCalledTimes(1); | ||
return eventListenerSpy; | ||
}; | ||
it('passes answers when defined', () => { | ||
const answers = { | ||
'a-question': 'an-answer', | ||
}; | ||
const eventListenerSpy = sendMessage(event, answers); | ||
expect(eventListenerSpy).toBeCalledWith({ answers }); | ||
}); | ||
}); }); | ||
test.each(_1.supportedAnalyticsEvents.flatMap(function (eventType) { | ||
return [ | ||
[ | ||
eventType, | ||
{ | ||
answers: { | ||
'a-question': 'an-answer', | ||
}, | ||
}, | ||
], | ||
[eventType, { answers: undefined }], | ||
]; | ||
}))('Passes answers if available for event %s', function (eventType, _a) { | ||
var answers = _a.answers; | ||
return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, eventListenerSpy, msg; | ||
return __generator(this, function (_b) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
eventListenerSpy = jest.fn(); | ||
embed.addEventListener(eventType, eventListenerSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: eventType, | ||
answers: answers, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(eventListenerSpy).toBeCalledTimes(1); | ||
expect(eventListenerSpy).toBeCalledWith(answers ? { answers: answers } : {}); | ||
return [2 /*return*/]; | ||
}); | ||
it('does not crash with empty answers', () => { | ||
const eventListenerSpy = sendMessage(event, undefined); | ||
expect(eventListenerSpy).toBeCalledWith({}); | ||
}); | ||
@@ -648,134 +545,115 @@ }); | ||
{ answers: undefined }, | ||
])('Passes answers if available for redirect event', function (_a) { | ||
var answers = _a.answers; | ||
return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectSpy, redirectUrl, msg, expectedCallArgs; | ||
return __generator(this, function (_b) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
redirectUrl = 'https://example.com'; | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
answers: answers, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
expectedCallArgs = { | ||
url: redirectUrl, | ||
}; | ||
if (answers) { | ||
expectedCallArgs.answers = answers; | ||
} | ||
expect(redirectSpy).toBeCalledWith(expectedCallArgs); | ||
return [2 /*return*/]; | ||
}); | ||
])('Passes answers if available for redirect event', ({ answers }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
const redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const redirectUrl = 'https://example.com'; | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
answers, | ||
}, | ||
}); | ||
}); | ||
test('handles events even when corresponding handlers are not set', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectMsg, resizeMsg, eventMsg, unknownMsg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body); | ||
iframe = document.body.querySelector('iframe'); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
redirectMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: 'https://example.com', | ||
}, | ||
}); | ||
mockPostMessage(redirectMsg); | ||
resizeMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width: '100px', | ||
height: '200px', | ||
}, | ||
}, | ||
}); | ||
mockPostMessage(resizeMsg); | ||
eventMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: 'https://example.com', | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
mockPostMessage(eventMsg); | ||
unknownMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: 'https://example.com', | ||
data: { | ||
type: 'some unknown type', | ||
}, | ||
}); | ||
mockPostMessage(unknownMsg); | ||
return [2 /*return*/]; | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
const expectedCallArgs = { | ||
url: redirectUrl, | ||
}; | ||
if (answers) { | ||
expectedCallArgs.answers = answers; | ||
} | ||
expect(redirectSpy).toBeCalledWith(expectedCallArgs); | ||
})); | ||
test('handles events even when corresponding handlers are not set', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body); | ||
const iframe = document.body.querySelector('iframe'); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const redirectMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: 'https://example.com', | ||
}, | ||
}); | ||
}); }); | ||
test('handles redirecting to a using history API when redirecting in the same origin', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectSpy, redirectUrl, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body, { useHistoryAPI: true }); | ||
iframe = document.body.querySelector('iframe'); | ||
redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
redirectUrl = EMBEDDING_WINDOW_ORIGIN + "/some-other-page-in-the-parent-origin"; | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
mockPostMessage(redirectMsg); | ||
const resizeMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_RESIZE_MSG, | ||
payload: { | ||
width: '100px', | ||
height: '200px', | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
expect(redirectSpy).toBeCalledWith({ url: redirectUrl }); | ||
expect(pushStateSpy).toBeCalledTimes(1); | ||
expect(pushStateSpy).toBeCalledWith({}, '', redirectUrl); | ||
return [2 /*return*/]; | ||
}, | ||
}); | ||
}); }); | ||
test('ignores useHistoryAPI when redirecting to a different origin', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var embed, iframe, redirectSpy, redirectUrl, msg; | ||
return __generator(this, function (_a) { | ||
embed = _1.default(document.body, { useHistoryAPI: true }); | ||
iframe = document.body.querySelector('iframe'); | ||
redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
redirectUrl = "https://www.some-other-origin.com/some-other-page"; | ||
msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: DEFAULT_FLOW_ORIGIN, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
expect(redirectSpy).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).toBeCalledTimes(1); | ||
expect(window.location.assign).toBeCalledWith(redirectUrl); | ||
expect(pushStateSpy).toBeCalledTimes(0); | ||
return [2 /*return*/]; | ||
mockPostMessage(resizeMsg); | ||
const eventMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: 'https://example.com', | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_EVENT_MSG, | ||
createdAt: new Date(), | ||
eventType: constants_1.AnalyticsEventType.FlowLoaded, | ||
}, | ||
}); | ||
}); }); | ||
mockPostMessage(eventMsg); | ||
const unknownMsg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: 'https://example.com', | ||
data: { | ||
type: 'some unknown type', | ||
}, | ||
}); | ||
mockPostMessage(unknownMsg); | ||
})); | ||
test('handles redirecting to a using history API when redirecting in the same origin', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body, { useHistoryAPI: true }); | ||
const iframe = document.body.querySelector('iframe'); | ||
const redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const redirectUrl = `${EMBEDDING_WINDOW_ORIGIN}/some-other-page-in-the-parent-origin`; | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
expect(redirectSpy).toBeCalledWith({ url: redirectUrl }); | ||
expect(pushStateSpy).toBeCalledTimes(1); | ||
expect(pushStateSpy).toBeCalledWith({}, '', redirectUrl); | ||
})); | ||
test('ignores useHistoryAPI when redirecting to a different origin', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { | ||
const embed = (0, _1.default)(document.body, { useHistoryAPI: true }); | ||
const iframe = document.body.querySelector('iframe'); | ||
const redirectSpy = jest.fn(); | ||
embed.addEventListener('redirect', redirectSpy); | ||
embed.loadFlow(clientLabel, flowLabel); | ||
const redirectUrl = `https://www.some-other-origin.com/some-other-page`; | ||
const msg = new MessageEvent('message', { | ||
source: iframe.contentWindow, | ||
origin: `https://${clientLabel}.formsort.app`, | ||
data: { | ||
type: constants_1.WebEmbedMessage.EMBED_REDIRECT_MSG, | ||
payload: redirectUrl, | ||
}, | ||
}); | ||
mockPostMessage(msg); | ||
expect(redirectSpy).toBeCalledTimes(1); | ||
expect(redirectSpy).toBeCalledWith({ url: redirectUrl }); | ||
expect(window.location.assign).toBeCalledTimes(1); | ||
expect(window.location.assign).toBeCalledWith(redirectUrl); | ||
expect(pushStateSpy).toBeCalledTimes(0); | ||
})); | ||
}); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isIFrameUnauthorizedEventData = exports.isIFrameResizeEventData = exports.isIFrameRedirectEventData = exports.isIFrameTokenRequestEventData = exports.isIFrameAnalyticsEventData = exports.isIWebEmbedEventData = void 0; | ||
var constants_1 = require("@formsort/constants"); | ||
const constants_1 = require("@formsort/constants"); | ||
function isRecord(val) { | ||
@@ -16,5 +16,3 @@ return val !== null && typeof val === 'object'; | ||
*/ | ||
var isEnumMember = function (val, anEnum) { | ||
return Object.values(anEnum).includes(val); | ||
}; | ||
const isEnumMember = (val, anEnum) => Object.values(anEnum).includes(val); | ||
function isIWebEmbedEventData(val) { | ||
@@ -21,0 +19,0 @@ return (isRecord(val) && |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var constants_1 = require("@formsort/constants"); | ||
var typeGuards_1 = require("./typeGuards"); | ||
describe('isIWebEmbedEventData', function () { | ||
test.each([1, 'hello', null, undefined, {}, { type: 'hello' }])('%p is not IWebEmbedEventData', function (val) { | ||
expect(typeGuards_1.isIWebEmbedEventData(val)).toEqual(false); | ||
const constants_1 = require("@formsort/constants"); | ||
const typeGuards_1 = require("./typeGuards"); | ||
describe('isIWebEmbedEventData', () => { | ||
test.each([1, 'hello', null, undefined, {}, { type: 'hello' }])('%p is not IWebEmbedEventData', (val) => { | ||
expect((0, typeGuards_1.isIWebEmbedEventData)(val)).toEqual(false); | ||
}); | ||
test.each(Object.values(constants_1.WebEmbedMessage).map(function (type) { return ({ type: type }); }))('%p is IWebEmbedEventData', function (val) { | ||
expect(typeGuards_1.isIWebEmbedEventData(val)).toEqual(true); | ||
test.each(Object.values(constants_1.WebEmbedMessage).map((type) => ({ type })))('%p is IWebEmbedEventData', (val) => { | ||
expect((0, typeGuards_1.isIWebEmbedEventData)(val)).toEqual(true); | ||
}); | ||
}); |
@@ -9,3 +9,3 @@ "use strict"; | ||
function removeFromArrayMap(arrayMap, key, val) { | ||
var indexOfElem = arrayMap[key].findIndex(function (elem) { return elem === val; }); | ||
const indexOfElem = arrayMap[key].findIndex((elem) => elem === val); | ||
if (indexOfElem !== -1) { | ||
@@ -12,0 +12,0 @@ arrayMap[key].splice(indexOfElem, 1); |
{ | ||
"name": "@formsort/web-embed-api", | ||
"version": "2.2.0", | ||
"version": "2.2.1", | ||
"description": "Embed Formsort flows within other webpages", | ||
"publishConfig": { | ||
"access": "public", | ||
"registry": "https://registry.npmjs.org/" | ||
}, | ||
"main": "lib/index.js", | ||
@@ -10,9 +14,7 @@ "types": "lib/index.d.ts", | ||
"coverage": "jest --coverage", | ||
"build": "tsc", | ||
"prepare": "npm run build", | ||
"prepublishOnly": "npm run lint", | ||
"preversion": "npm run lint", | ||
"format": "eslint -c .eslintrc.js --ext .ts,.tsx src --fix", | ||
"lint": "eslint -c .eslintrc.js --ext .ts,.tsx src", | ||
"pretty-check": "prettier --check src" | ||
"build": "tsc --project tsconfig.build.json", | ||
"format": "eslint --ext .ts,.tsx src --fix", | ||
"lint": "eslint --ext .ts,.tsx src", | ||
"pack": "yarn pack", | ||
"release": "craft prepare --publish" | ||
}, | ||
@@ -31,3 +33,3 @@ "repository": { | ||
], | ||
"author": "Fil Zembowicz <fil@formsort.com>", | ||
"author": "Formsort Engineering <engineering@formsort.com>", | ||
"license": "MIT", | ||
@@ -37,4 +39,4 @@ "devDependencies": { | ||
"@types/jest": "^27.0.1", | ||
"@typescript-eslint/eslint-plugin": "^4.11.0", | ||
"eslint": "^7.16.0", | ||
"@typescript-eslint/eslint-plugin": "^5.17.0", | ||
"eslint": "^8.12.0", | ||
"eslint-plugin-import": "^2.22.1", | ||
@@ -47,7 +49,26 @@ "eslint-plugin-jsdoc": "^30.7.9", | ||
"ts-jest": "^27.0.5", | ||
"typescript": "^3.8.3" | ||
"typescript": "^4.6.3" | ||
}, | ||
"dependencies": { | ||
"@formsort/constants": "^1.6.0" | ||
}, | ||
"jest": { | ||
"cacheDirectory": "./.jest-cache", | ||
"roots": [ | ||
"<rootDir>/src" | ||
], | ||
"testMatch": [ | ||
"**/__tests__/**/*.+(ts|tsx|js)", | ||
"**/?(*.)+(spec|test).+(ts|tsx|js)" | ||
], | ||
"testPathIgnorePatterns": [ | ||
"/node_modules/", | ||
"/lib/", | ||
"/dist/" | ||
], | ||
"transform": { | ||
"^.+\\.(ts|tsx)$": "ts-jest" | ||
}, | ||
"testEnvironment": "jsdom" | ||
} | ||
} |
@@ -12,2 +12,6 @@ # @formsort/web-embed-api | ||
```shell | ||
yarn add @formsort/web-embed-api | ||
``` | ||
```shell | ||
npm install @formsort/web-embed-api --save | ||
@@ -14,0 +18,0 @@ ``` |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
16
146
53056
988