Skip to content

Commit

Permalink
feat(insights): add hogan helper (#4253)
Browse files Browse the repository at this point in the history
  • Loading branch information
tkrugg committed Dec 13, 2019
1 parent 4ff089e commit 85739d7
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
20 changes: 20 additions & 0 deletions src/lib/createHelpers.ts
Expand Up @@ -3,14 +3,17 @@ import {
snippet,
HighlightOptions,
SnippetOptions,
insights,
} from '../helpers';
import { Hit, InsightsClientMethod, InsightsClientPayload } from '../types';

type HoganRenderer = (value: any) => string;

interface HoganHelpers {
formatNumber: (value: number, render: HoganRenderer) => string;
highlight: (options: string, render: HoganRenderer) => string;
snippet: (options: string, render: HoganRenderer) => string;
insights: (options: string, render: HoganRenderer) => string;
}

export default function hoganHelpers({
Expand Down Expand Up @@ -56,5 +59,22 @@ The snippet helper expects a JSON object of the format:
{ "attribute": "name", "highlightedTagName": "mark" }`);
}
},
insights(this: Hit, options, render) {
try {
type InsightsHelperOptions = {
method: InsightsClientMethod;
payload: Partial<InsightsClientPayload>;
};
const { method, payload }: InsightsHelperOptions = JSON.parse(options);

return render(
insights(method, { objectIDs: [this.objectID], ...payload })
);
} catch (error) {
throw new Error(`
The insights helper expects a JSON object of the format:
{ "method": "method-name", "payload": { "eventName": "name of the event" } }`);
}
},
};
}
54 changes: 54 additions & 0 deletions src/lib/utils/__tests__/createHelpers-tests.ts
@@ -0,0 +1,54 @@
import renderTemplate from '../renderTemplate';
import createHelpers from '../../createHelpers';
import { insights } from '../../../helpers';

describe('insights hogan helper', () => {
const helpers = createHelpers({ numberLocale: 'en-US' });
it('should produce the same output as the insights function', () => {
const output = renderTemplate({
templateKey: 'item',
templates: {
item: `
<button {{#helpers.insights}}{
"method": "clickedObjectIDsAfterSearch",
"payload": {"eventName": "Add to cart"}
}{{/helpers.insights}}>Add to cart</button>
`,
},
helpers,
data: {
objectID: 'xxx',
},
});

const expected = `<button ${insights('clickedObjectIDsAfterSearch', {
objectIDs: ['xxx'],
eventName: 'Add to cart',
})}>Add to cart</button>
`;

expect(output.trim()).toEqual(expected.trim());
});
it('should throw an error if the provided string cannot be JSON parsed', () => {
expect(() =>
renderTemplate({
templateKey: 'item',
templates: {
item: `
<button {{#helpers.insights}}{
invalid json
}{{/helpers.insights}}>Add to cart</button>
`,
},
helpers,
data: {
objectID: 'xxx',
},
})
).toThrowErrorMatchingInlineSnapshot(`
"
The insights helper expects a JSON object of the format:
{ \\"method\\": \\"method-name\\", \\"payload\\": { \\"eventName\\": \\"name of the event\\" } }"
`);
});
});
35 changes: 34 additions & 1 deletion stories/hits.stories.js
Expand Up @@ -109,7 +109,7 @@ storiesOf('Results|Hits', module)
})
)
.add(
'with insights helper',
'with insights function',
withHits(
({ search, container, instantsearch }) => {
search.addWidgets([
Expand Down Expand Up @@ -140,4 +140,37 @@ storiesOf('Results|Hits', module)
action(`[InsightsClient] sent ${method} with payload`)(payload),
}
)
)
.add(
'with insights helper',
withHits(
({ search, container, instantsearch }) => {
search.addWidgets([
instantsearch.widgets.configure({
attributesToSnippet: ['name', 'description'],
clickAnalytics: true,
}),
]);

search.addWidgets([
instantsearch.widgets.hits({
container,
templates: {
item: `
<h4>{{name}}</h4>
<button {{#helpers.insights}} {
"method": "clickedObjectIDsAfterSearch",
"payload": { "eventName": "Add to cart" }
} {{/helpers.insights}}>
Add to cart
</button>`,
},
}),
]);
},
{
insightsClient: (method, payload) =>
action(`[InsightsClient] sent ${method} with payload`)(payload),
}
)
);

0 comments on commit 85739d7

Please sign in to comment.