Skip to content

Commit

Permalink
fix(TYP-2386): Pass hidden fields via fragment
Browse files Browse the repository at this point in the history
Pass hidden fields to typeform using both query params (legacy) and fragment (new approach)
  • Loading branch information
Matej Lednicky committed Jun 30, 2020
1 parent 4901ac5 commit ef45827
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 68 deletions.
65 changes: 32 additions & 33 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,35 @@ window.addEventListener('message', function (event) {
}
})

var EMBED_DOM_CLASSES = [
{
selector: '.typeform-widget',
attribute: 'data-url'
}, {
selector: '.typeform-share',
attribute: 'href'
}, {
selector: '.typeform-full',
attribute: 'src'
}
]

const addQueryStringToUrl = (url, queryString) => {
return /\?/.test(url) ? `${url}&${queryString}` : `${url}?${queryString}`
}

window.addEventListener('DOMContentLoaded', function () {
var queryString = window.location.search.substring(1)
if (queryString.length === 0) {
return
}

EMBED_DOM_CLASSES
.forEach(function (embed) {
var attribute = embed.attribute
var embeds = document.querySelectorAll(embed.selector)
embeds.forEach(function (embed) {
var embedAttr = embed.getAttribute(attribute)
embed.setAttribute(attribute, addQueryStringToUrl(embedAttr, queryString))
})
})
})
// var EMBED_DOM_CLASSES = [
// {
// selector: '.typeform-widget',
// attribute: 'data-url'
// }, {
// selector: '.typeform-share',
// attribute: 'href'
// }, {
// selector: '.typeform-full',
// attribute: 'src'
// }
// ]
//
// const addQueryStringToUrl = (url, queryString) => {
// return /\?/.test(url) ? `${url}&${queryString}` : `${url}#${queryString}`
// }
// window.addEventListener('DOMContentLoaded', function () {
// var queryString = window.location.search.substring(1)
// if (queryString.length === 0) {
// return
// }
//
// EMBED_DOM_CLASSES
// .forEach(function (embed) {
// var attribute = embed.attribute
// var embeds = document.querySelectorAll(embed.selector)
// embeds.forEach(function (embed) {
// var embedAttr = embed.getAttribute(attribute)
// embed.setAttribute(attribute, addQueryStringToUrl(embedAttr, queryString))
// })
// })
// })
2 changes: 1 addition & 1 deletion demo/form/mock.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
}
</style>
</head>
<body>
<body id="foobar=hello">
<div id="root">
<div data-qa="renderer">
<div data-qa="welcome-screen-wrapper">
Expand Down
2 changes: 1 addition & 1 deletion demo/full.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
width="100%"
height="100%"
frameborder="0"
src="./form/mock.html"
src="./form/mock.html#foobar=hello"
></iframe>

<script type="text/javascript" src="embed.js"></script>
Expand Down
1 change: 1 addition & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ <h2>Embed snippet</h2>
<ul>
<li><a href="./widget-v3.html">Widget accepting form and embed library version as URL parameters</a></li>
<li><a href="./widget.html">Widget *</a></li>
<li><a href="./widget-legacy.html">Widget with legacy hidden fields *</a></li>
<li><a href="./widget-v2.html">Widget with long text</a></li>
<li><a href="./multi-widget.html">Multiple widgets</a></li>
<li><a href="./full.html">Full page *</a></li>
Expand Down
9 changes: 5 additions & 4 deletions demo/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@
<body>
<a
class="typeform-share popup"
href="./form/mock.html"
href="./form/mock.html#foobar=hello"
data-mode="popup"
data-submit-close-delay="4"
target="_blank"
>
Launch me as a popup!
</a>

<!-- uses legacy hidden field in query param -->
<a
class="typeform-share popup"
href="./form/mock.html"
href="./form/mock.html?foobar=hello"
data-mode="drawer_left"
data-submit-close-delay="4"
target="_blank"
Expand All @@ -63,7 +64,7 @@

<a
class="typeform-share popup"
href="./form/mock.html"
href="./form/mock.html#foobar=hello"
data-mode="drawer_right"
data-width="400"
data-submit-close-delay="4"
Expand All @@ -76,7 +77,7 @@

<a
class="typeform-share popover"
href="./form/mock.html"
href="./form/mock.html#foobar=hello"
data-mode="popover"
data-width="500"
data-height="600"
Expand Down
19 changes: 19 additions & 0 deletions demo/widget-legacy.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Widget example</title>
<meta charset="utf-8" />
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
<link rel="stylesheet" href="demo.css" />
</head>
<body>
<div
class="typeform-widget"
data-url="./form/mock.html?foobar=hello"
style="width:100%; height:500px;"
></div>

<script type="text/javascript" src="demo.js"></script>
<script type="text/javascript" src="embed.js"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions demo/widget.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Widget example</title>
<title>Widget (legacy hidden fields) example</title>
<meta charset="utf-8" />
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
<link rel="stylesheet" href="demo.css" />
</head>
<body>
<div
class="typeform-widget"
data-url="./form/mock.html"
data-url="./form/mock.html#foobar=hello"
style="width:100%; height:500px;"
></div>

Expand Down
2 changes: 1 addition & 1 deletion e2e/spec/functional/popup.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Object.keys(popupModes).forEach(popupMode => {
openPopup(popupMode)
})

it('Passes query string parameter', () => {
it('Passes hidden field parameter', () => {
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
})

Expand Down
67 changes: 63 additions & 4 deletions e2e/spec/functional/widget.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { open, testEmbeddedForm, openOnMobile, testEmbedFormOnMobile } from '../../cypress-utils'
import { open, testEmbeddedForm, openOnMobile, testEmbedFormOnMobile, IFRAME_SELECTOR } from '../../cypress-utils'

describe('Embed Widget in div with position:absolute on mobile', () => {
it('Loads correctly the basic embed widget', () => {
Expand All @@ -9,34 +9,93 @@ describe('Embed Widget in div with position:absolute on mobile', () => {

describe('Basic Embed Widget', () => {
describe('On Desktop', () => {
it('Loads correctly the basic embed widget', () => {
before(() => {
open('/widget.html')
})

it('Loads correctly the basic embed widget', () => {
testEmbeddedForm()
})

it('Passes hidden field parameter', () => {
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
})
})

describe('On Mobile', () => {
it('Loads correctly the basic embed widget', () => {
before(() => {
openOnMobile('/widget.html')
})

it('Loads correctly the basic embed widget', () => {
testEmbedFormOnMobile()
})

it('Passes hidden field parameter', () => {
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
})
})
})

describe('Basic Embed Widget with Legacy Hidden Fields', () => {
describe('On Desktop', () => {
before(() => {
open('/widget-legacy.html')
})

it('Loads correctly the basic embed widget', () => {
testEmbeddedForm()
})

it('Passes hidden field parameter', () => {
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
})
})

describe('On Mobile', () => {
before(() => {
openOnMobile('/widget-legacy.html')
})

it('Loads correctly the basic embed widget', () => {
testEmbedFormOnMobile()
})

it('Passes hidden field parameter', () => {
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
})
})
})

describe('Full Page Embed Widget', () => {
const iframe = '#typeform-full'

describe('On Desktop', () => {
before(() => {
open('/full.html')
})

it('Loads correctly the Full Page widget', () => {
open('/full.html')
testEmbeddedForm(iframe)
})

it('Passes hidden field parameter', () => {
cy.get(iframe).should('have.attr', 'src').and('match', /foobar=hello/)
})
})

describe('On Mobile', () => {
it('Loads correctly the Full Page widget', () => {
before(() => {
openOnMobile('/full.html')
})

it('Loads correctly the Full Page widget', () => {
testEmbeddedForm(iframe) // full page widget behaves the same as on desktop (no modal window)
})

it('Passes hidden field parameter', () => {
cy.get(iframe).should('have.attr', 'src').and('match', /foobar=hello/)
})
})
})
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"build": "./scripts/build.sh",
"serve-demo": "PORT=8080 yarn serve -S demo",
"start": "NODE_ENV=development webpack-dev-server -d --config webpack.config.js --content-base ./demo",
"test": "yarn lint && yarn test:unit && yarn test:visual && yarn test:functional",
"test": "yarn lint && yarn test:unit && yarn test:functional && yarn test:visual",
"lint": "yarn eslint ./src --ext .js --ignore-path .eslintignore --max-warnings=0",
"test:unit": "yarn jest",
"test:unit:watch": "yarn jest --watch",
Expand Down
13 changes: 4 additions & 9 deletions src/core/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,16 @@ export const broadcastMessage = (embedId, event) => {
}

export const updateQueryStringParameter = (key, value, uri) => {
const re = new RegExp(`([?&])${key}=.*?(&|$)`, 'i')
const separator = uri.indexOf('?') !== -1 ? '&' : '?'
if (uri.match(re)) {
return uri.replace(re, `$1${key}=${value}$2`)
}

return `${uri + separator + key}=${value}`
return appendParamsToUrl(uri, { [key]: value })
}

export const appendParamsToUrl = (url, params) => {
const queryParameters = []
const {
query,
origin,
pathname
pathname,
hash
} = UrlParse(url, true)
const path = pathname.replace(/\/$/, '') // remove trailing slash
const parameters = Object.assign({}, query, params)
Expand All @@ -47,7 +42,7 @@ export const appendParamsToUrl = (url, params) => {
)
})

return `${origin}${path}?${queryParameters.join('&')}`
return `${origin}${path}?${queryParameters.join('&')}${hash}`
}

export const replaceExistingKeys = (obj, replacer) => {
Expand Down
14 changes: 12 additions & 2 deletions src/core/utils/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,20 @@ jest.mock('./message-propagation')

describe('Utilities', () => {
describe('appendParamsToUrl', () => {
it('should append parameters to url correctly', () => {
fixtures.urls.forEach((fixture) => {
fixtures.urls.forEach((fixture) => {
it(`should append parameters correctly to url ${fixture.url}`, () => {
const result = utils.appendParamsToUrl(fixture.url, fixture.params)
expect(result).toEqual(fixture.expected)
})
})
})

describe('updateQueryStringParameter', () => {
fixtures.urls.forEach((fixture) => {
it(`should update parameter correctly on url ${fixture.url}`, () => {
const key = Object.keys(fixture.params)[0]
const value = Object.values(fixture.params)[0]
const result = utils.updateQueryStringParameter(key, value, fixture.url)
expect(result).toEqual(fixture.expected)
})
})
Expand Down
Loading

0 comments on commit ef45827

Please sign in to comment.