Skip to content

Commit

Permalink
fix(surveys): Validate HTML for all questions and descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
neilkakkar committed Oct 5, 2023
1 parent 5f493d2 commit cfd61f8
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 1 deletion.
74 changes: 73 additions & 1 deletion src/__tests__/extensions/surveys.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createShadow, callSurveys, generateSurveys } from '../../extensions/surveys'
import { createShadow, callSurveys, generateSurveys, validateAndFixHTML } from '../../extensions/surveys'

describe('survey display logic', () => {
beforeEach(() => {
Expand Down Expand Up @@ -152,4 +152,76 @@ describe('survey display logic', () => {
expect(mockPostHog.getActiveMatchingSurveys).toBeCalledTimes(1)
expect(setInterval).toHaveBeenLastCalledWith(expect.any(Function), 1500)
})

test('survey fixes broken HTML', () => {
mockSurveys = [
{
id: 'testSurvey1',
name: 'Test survey 1',
appearance: null,
questions: [
{
question: 'How satisfied are you with our newest product?<li>test',
description: 'This is a question description<li>break</br><br/>',
type: 'rating',
display: 'number',
scale: 10,
lower_bound_label: 'Not Satisfied',
upper_bound_label: 'Very Satisfied',
},
],
},
]

expect(localStorage.getItem(`seenSurvey_${mockSurveys[0].id}`)).toBe(null)
callSurveys(mockPostHog, false)
expect(mockPostHog.capture).toBeCalledTimes(1)
expect(mockPostHog.capture).toBeCalledWith('survey shown', {
$survey_id: 'testSurvey1',
$survey_name: 'Test survey 1',
sessionRecordingUrl: undefined,
})

expect(
document
.getElementsByClassName(`PostHogSurvey${mockSurveys[0].id}`)[0]
.shadowRoot.querySelectorAll('.survey-question')[0].innerHTML
).toEqual('How satisfied are you with our newest product?<li>test</li>')
expect(
document
.getElementsByClassName(`PostHogSurvey${mockSurveys[0].id}`)[0]
.shadowRoot.querySelectorAll('.description')[0].innerHTML
).toEqual('This is a question description<li>break<br><br></li>')
})
})

describe('validateAndFixHTML', () => {
it('should do nothing to valid HTML', () => {
const html = '<div><h1>Test</h1><p>Test</p></div>'
expect(validateAndFixHTML(html)).toEqual('<div><h1>Test</h1><p>Test</p></div>')
})

it('should fix broken HTML', () => {
const html = '<div><h1>Test</h1><p>Test</p></div'
expect(validateAndFixHTML(html)).toEqual('<div><h1>Test</h1><p>Test</p></div>')
})

it('should do nothing to regular strings', () => {
const html = 'Test'
expect(validateAndFixHTML(html)).toEqual('Test')
})

it('should do nothing to empty strings', () => {
const html = ''
expect(validateAndFixHTML(html)).toEqual('')
})

it('returns undefined when passed undefined', () => {
expect(validateAndFixHTML(undefined)).toEqual(undefined)
})

it('completes missing closing tags', () => {
const html = '<div><h1>Test</h1><p>Test</p>'
expect(validateAndFixHTML(html)).toEqual('<div><h1>Test</h1><p>Test</p></div>')
})
})
16 changes: 16 additions & 0 deletions src/extensions/surveys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,12 @@ export const callSurveys = (posthog: PostHog, forceReload: boolean = false) => {
}
}

// safe-validate all the questions & descriptions
survey.questions.forEach((question) => {
question.question = validateAndFixHTML(question.question) || ''
question.description = validateAndFixHTML(question.description || undefined)
})

if (!localStorage.getItem(`seenSurvey_${survey.id}`)) {
const shadow = createShadow(style(survey.id, survey?.appearance), survey.id)
let surveyPopup
Expand Down Expand Up @@ -875,3 +881,13 @@ export function generateSurveys(posthog: PostHog) {
}, 1500)
}
}

export function validateAndFixHTML(html?: string): string | undefined {
if (html === undefined || html === null) {
return undefined
}
// marks scripts as non-executable
const doc = new DOMParser().parseFromString(html, 'text/html')
const body = doc.body
return body.innerHTML
}

0 comments on commit cfd61f8

Please sign in to comment.