Skip to content

Commit

Permalink
fix(bindEvent): escape payload correctly (#4670)
Browse files Browse the repository at this point in the history
* fix(bindEvent): qoute the value

* .

* remove console.log

* update snapshot

* fix type error
  • Loading branch information
Eunjae Lee authored Mar 9, 2021
1 parent 4497a93 commit c1cbaf4
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 31 deletions.
6 changes: 3 additions & 3 deletions src/connectors/hits/__tests__/connectHits-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import algoliasearchHelper, {
SearchParameters,
SearchResults,
} from 'algoliasearch-helper';
import { TAG_PLACEHOLDER } from '../../../lib/utils';
import { TAG_PLACEHOLDER, deserializePayload } from '../../../lib/utils';
import connectHits from '../connectHits';
import {
createInitOptions,
Expand Down Expand Up @@ -844,7 +844,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hits/js/#co
const payload = bindEvent('click', hits[0], 'Product Added');
expect(payload.startsWith('data-insights-event=')).toBe(true);
expect(
JSON.parse(atob(payload.substr('data-insights-event='.length)))
deserializePayload(payload.substr('data-insights-event='.length))
).toEqual({
eventType: 'click',
hits: [
Expand Down Expand Up @@ -875,7 +875,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hits/js/#co
const payload = bindEvent('conversion', hits[1], 'Product Ordered');
expect(payload.startsWith('data-insights-event=')).toBe(true);
expect(
JSON.parse(atob(payload.substr('data-insights-event='.length)))
deserializePayload(payload.substr('data-insights-event='.length))
).toEqual({
eventType: 'conversion',
hits: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
createRenderOptions,
} from '../../../../test/mock/createWidget';
import { createSingleSearchResponse } from '../../../../test/mock/createAPIResponse';
import { TAG_PLACEHOLDER } from '../../../lib/utils';
import { TAG_PLACEHOLDER, deserializePayload } from '../../../lib/utils';
import connectInfiniteHits from '../connectInfiniteHits';
import { createSearchClient } from '../../../../test/mock/createSearchClient';

Expand Down Expand Up @@ -1436,7 +1436,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/infinite-hi
const payload = bindEvent('click', hits[0], 'Product Added');
expect(payload.startsWith('data-insights-event=')).toBe(true);
expect(
JSON.parse(atob(payload.substr('data-insights-event='.length)))
deserializePayload(payload.substr('data-insights-event='.length))
).toEqual({
eventType: 'click',
hits: [
Expand Down Expand Up @@ -1467,7 +1467,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/infinite-hi
const payload = bindEvent('conversion', hits[1], 'Product Ordered');
expect(payload.startsWith('data-insights-event=')).toBe(true);
expect(
JSON.parse(atob(payload.substr('data-insights-event='.length)))
deserializePayload(payload.substr('data-insights-event='.length))
).toEqual({
eventType: 'conversion',
hits: [
Expand Down
13 changes: 7 additions & 6 deletions src/helpers/__tests__/insights-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import insights, {
readDataAttributes,
hasDataAttributes,
} from '../insights';
import { warning } from '../../lib/utils';
import { warning, serializePayload } from '../../lib/utils';

const makeDomElement = (html: string): HTMLElement => {
const div = document.createElement('div');
Expand All @@ -19,7 +19,7 @@ describe('insights', () => {
eventName: 'Add to Cart',
})
).toMatchInlineSnapshot(
`"data-insights-method=\\"clickedObjectIDsAfterSearch\\" data-insights-payload=\\"eyJvYmplY3RJRHMiOlsiMyJdLCJldmVudE5hbWUiOiJBZGQgdG8gQ2FydCJ9\\""`
`"data-insights-method=\\"clickedObjectIDsAfterSearch\\" data-insights-payload=\\"JTdCJTIyb2JqZWN0SURzJTIyJTNBJTVCJTIyMyUyMiU1RCUyQyUyMmV2ZW50TmFtZSUyMiUzQSUyMkFkZCUyMHRvJTIwQ2FydCUyMiU3RA==\\""`
);
});

Expand Down Expand Up @@ -50,7 +50,7 @@ describe('writeDataAttributes', () => {
},
})
).toMatchInlineSnapshot(
`"data-insights-method=\\"clickedObjectIDsAfterSearch\\" data-insights-payload=\\"eyJvYmplY3RJRHMiOlsiMyJdLCJldmVudE5hbWUiOiJBZGQgdG8gQ2FydCJ9\\""`
`"data-insights-method=\\"clickedObjectIDsAfterSearch\\" data-insights-payload=\\"JTdCJTIyb2JqZWN0SURzJTIyJTNBJTVCJTIyMyUyMiU1RCUyQyUyMmV2ZW50TmFtZSUyMiUzQSUyMkFkZCUyMHRvJTIwQ2FydCUyMiU3RA==\\""`
);
});
it('should reject undefined payloads', () => {
Expand Down Expand Up @@ -115,9 +115,10 @@ describe('readDataAttributes', () => {
let domElement: HTMLElement;

beforeEach(() => {
const payload = btoa(
JSON.stringify({ objectIDs: ['3'], eventName: 'Add to Cart' })
);
const payload = serializePayload({
objectIDs: ['3'],
eventName: 'Add to Cart',
});
domElement = makeDomElement(
`<button
data-insights-method="clickedObjectIDsAfterSearch"
Expand Down
8 changes: 4 additions & 4 deletions src/helpers/insights.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { InsightsClientMethod, InsightsClientPayload } from '../types';
import { warning } from '../lib/utils';
import { warning, serializePayload, deserializePayload } from '../lib/utils';

export function readDataAttributes(
domElement: HTMLElement
Expand All @@ -20,8 +20,8 @@ export function readDataAttributes(
}

try {
const payload: Partial<InsightsClientPayload> = JSON.parse(
atob(serializedPayload)
const payload: Partial<InsightsClientPayload> = deserializePayload(
serializedPayload
);
return { method, payload };
} catch (error) {
Expand Down Expand Up @@ -49,7 +49,7 @@ export function writeDataAttributes({
let serializedPayload: string;

try {
serializedPayload = btoa(JSON.stringify(payload));
serializedPayload = serializePayload(payload);
} catch (error) {
throw new Error(`Could not JSON serialize the payload object.`);
}
Expand Down
22 changes: 13 additions & 9 deletions src/lib/__tests__/insights-listener-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import { h } from 'preact';
import { render, fireEvent } from '@testing-library/preact';
import withInsightsListener from '../insights/listener';
import { serializePayload } from '../../lib/utils';

describe('withInsightsListener', () => {
it('should capture clicks performed on inner elements with data-insights-method defined', () => {
const payload = btoa(
JSON.stringify({ objectIDs: ['1'], eventName: 'Add to Cart' })
);
const payload = serializePayload({
objectIDs: ['1'],
eventName: 'Add to Cart',
});

const Hits = () => (
<div>
Expand Down Expand Up @@ -62,9 +64,10 @@ describe('withInsightsListener', () => {
});

it('should capture clicks performed on inner elements whose parents have data-insights-method defined', () => {
const payload = btoa(
JSON.stringify({ objectIDs: ['1'], eventName: 'Product Clicked' })
);
const payload = serializePayload({
objectIDs: ['1'],
eventName: 'Product Clicked',
});

const Hits = () => (
<div>
Expand Down Expand Up @@ -118,9 +121,10 @@ describe('withInsightsListener', () => {
});

it('should not capture clicks performed on inner elements with no data-insights-method defined', () => {
const payload = btoa(
JSON.stringify({ objectIDs: ['1'], eventName: 'Add to Cart' })
);
const payload = serializePayload({
objectIDs: ['1'],
eventName: 'Add to Cart',
});

const Hits = () => (
<div>
Expand Down
7 changes: 5 additions & 2 deletions src/lib/insights/listener.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @jsx h */

import { h } from 'preact';
import { deserializePayload } from '../utils';
import { readDataAttributes, hasDataAttributes } from '../../helpers/insights';
import { InsightsClientWrapper } from '../../types';
import { InsightsEvent } from '../../middlewares/createInsightsMiddleware';
Expand All @@ -26,7 +27,9 @@ const findInsightsTarget = (
return element;
};

const parseInsightsEvent = element => {
type ParseInsightsEvent = (element: HTMLElement) => InsightsEvent;

const parseInsightsEvent: ParseInsightsEvent = element => {
const serializedPayload = element.getAttribute('data-insights-event');

if (typeof serializedPayload !== 'string') {
Expand All @@ -36,7 +39,7 @@ const parseInsightsEvent = element => {
}

try {
return JSON.parse(atob(serializedPayload));
return deserializePayload(serializedPayload) as InsightsEvent;
} catch (error) {
throw new Error(
'The insights middleware was unable to parse `data-insights-event`.'
Expand Down
3 changes: 2 additions & 1 deletion src/lib/utils/__tests__/createSendEventForHits-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
createBindEventForHits,
createSendEventForHits,
} from '../createSendEventForHits';
import { deserializePayload } from '../../utils';

const createTestEnvironment = () => {
const instantSearchInstance = createInstantSearch();
Expand Down Expand Up @@ -227,7 +228,7 @@ describe('createSendEventForHits', () => {
describe('createBindEventForHits', () => {
function parsePayload(payload) {
expect(payload.startsWith('data-insights-event=')).toBe(true);
return JSON.parse(atob(payload.substr('data-insights-event='.length)));
return deserializePayload(payload.substr('data-insights-event='.length));
}

it('returns a payload for click event', () => {
Expand Down
5 changes: 2 additions & 3 deletions src/lib/utils/createSendEventForHits.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { InstantSearch, Hit, Hits, EscapedHits } from '../../types';
import { serializePayload } from '../../lib/utils';
import { InsightsEvent } from '../../middlewares/createInsightsMiddleware';

type BuiltInSendEventForHits = (
Expand Down Expand Up @@ -162,9 +163,7 @@ export function createBindEventForHits({
methodName: 'bindEvent',
args,
});
return payload
? `data-insights-event=${btoa(JSON.stringify(payload))}`
: '';
return payload ? `data-insights-event=${serializePayload(payload)}` : '';
};
return bindEventForHits;
}
1 change: 1 addition & 0 deletions src/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ export { getAppIdAndApiKey } from './getAppIdAndApiKey';
export { convertNumericRefinementsToFilters } from './convertNumericRefinementsToFilters';
export { createConcurrentSafePromise } from './createConcurrentSafePromise';
export { debounce } from './debounce';
export { serializePayload, deserializePayload } from './serializer';
7 changes: 7 additions & 0 deletions src/lib/utils/serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function serializePayload(payload: object): string {
return btoa(encodeURIComponent(JSON.stringify(payload)));
}

export function deserializePayload(payload: string): object {
return JSON.parse(decodeURIComponent(atob(payload)));
}

0 comments on commit c1cbaf4

Please sign in to comment.