diff --git a/pages/attached_result.html b/pages/attached_result.html index 2003cc1a..1fcd9309 100644 --- a/pages/attached_result.html +++ b/pages/attached_result.html @@ -79,7 +79,7 @@
-
+
diff --git a/src/components/AttachResult/AttachResult.ts b/src/components/AttachResult/AttachResult.ts index 60e528dd..8edb8a49 100644 --- a/src/components/AttachResult/AttachResult.ts +++ b/src/components/AttachResult/AttachResult.ts @@ -23,6 +23,10 @@ export interface IAttachResultOptions { attachCaption?: string; /** Specifies the tooltip displayed when the result is already attached. */ detachCaption?: string; + /** The field of the query result which represents the Article ID in the index, used for Usage Analytics purposes. */ + articleIdField?: string; + /** Id of the record where the search is currently displayed, if any. */ + caseId?: string; /** The function that is called when the user wants to attach a result. */ attach?: (queryResult: IQueryResult) => Promise; /** The function called when the user wants to un-link a result. */ @@ -50,6 +54,10 @@ export class AttachResult extends Component { detachCaption: ComponentOptions.buildStringOption({ defaultValue: l(`${AttachResult.ID}_Detach`) }), + articleIdField: ComponentOptions.buildStringOption({ + defaultValue: 'permanentid' + }), + caseId: ComponentOptions.buildStringOption(), attach: ComponentOptions.buildCustomOption( name => (result: IQueryResult) => new Promise((resolve, reject) => { @@ -116,6 +124,7 @@ export class AttachResult extends Component { .attach(this.queryResult) .then(() => { this.attached = true; + this.usageAnalytics.logClickEvent(analyticsActionCauseList.caseAttach, {}, this.queryResult, this.element); this.logAnalyticsCaseEvent(analyticsActionCauseList.caseAttach); Coveo.$$(this.root).trigger(AttachResultEvents.Attach, { queryResult: this.queryResult } as IAttachResultEventArgs); }) @@ -194,11 +203,11 @@ export class AttachResult extends Component { let customData: IAnalyticsCaseAttachMeta = { resultUriHash: this.queryResult.raw.urihash, author: this.queryResult.raw.author, - articleID: null, - caseID: null + articleID: this.queryResult.raw[this.options.articleIdField], + caseID: this.options.caseId }; - this.usageAnalytics.logCustomEvent(cause, customData, this.root); + this.usageAnalytics.logCustomEvent(cause, customData, this.element, this.queryResult); } protected render(): void { diff --git a/tests/components/AttachResult/AttachResult.spec.ts b/tests/components/AttachResult/AttachResult.spec.ts index e4a4557f..bc516bb7 100644 --- a/tests/components/AttachResult/AttachResult.spec.ts +++ b/tests/components/AttachResult/AttachResult.spec.ts @@ -1,11 +1,12 @@ import { AttachResult, IAttachResultOptions } from '../../../src/components/AttachResult/AttachResult'; import { Mock, Fake } from 'coveo-search-ui-tests'; -import { IQueryResult, Logger } from 'coveo-search-ui'; +import { IQueryResult, Logger, analyticsActionCauseList } from 'coveo-search-ui'; import { AttachResultEvents, IAttachResultEventArgs } from '../../../src/components/AttachResult/Events'; describe('AttachResult', () => { let attachResult: Mock.IBasicComponentSetup; let fakeResult = Fake.createFakeResult(); + fakeResult.raw.article = 'foo'; beforeAll(() => { Logger.disable(); @@ -94,14 +95,23 @@ describe('AttachResult', () => { attachSpy = spyOn(faker, 'attach').and.callThrough(); - attachResult = Mock.optionsResultComponentSetup( + attachResult = Mock.advancedResultComponentSetup( AttachResult, - { - attach: faker.attach, - detachCaption: 'detach me', - attachCaption: 'attach me' - }, - fakeResult + fakeResult, + new Mock.AdvancedComponentSetupOptions( + document.createElement('div'), + { + attach: faker.attach, + detachCaption: 'detach me', + attachCaption: 'attach me', + caseId: 'testcase', + articleIdField: 'article' + }, + env => { + env.searchInterface.usageAnalytics = env.usageAnalytics; + return env; + } + ) ); attachResult.cmp.detach().then(() => { @@ -145,6 +155,22 @@ describe('AttachResult', () => { }); attachResult.cmp.attach(); }); + + it('should log a click and attach event', async () => { + await attachResult.cmp.attach(); + expect(attachResult.env.usageAnalytics.logClickEvent).toHaveBeenCalledWith( + analyticsActionCauseList.caseAttach, + jasmine.any(Object), + fakeResult, + attachResult.cmp.element + ); + expect(attachResult.env.usageAnalytics.logCustomEvent).toHaveBeenCalledWith( + analyticsActionCauseList.caseAttach, + jasmine.objectContaining({ caseID: 'testcase', articleID: 'foo', resultUriHash: fakeResult.raw.urihash }), + attachResult.cmp.element, + fakeResult + ); + }); }); describe('detach', () => { @@ -159,14 +185,23 @@ describe('AttachResult', () => { detachSpy = spyOn(faker, 'detach').and.callThrough(); - attachResult = Mock.optionsResultComponentSetup( + attachResult = Mock.advancedResultComponentSetup( AttachResult, - { - detach: faker.detach, - detachCaption: 'detach me', - attachCaption: 'attach me' - }, - fakeResult + fakeResult, + new Mock.AdvancedComponentSetupOptions( + document.createElement('div'), + { + detach: faker.detach, + detachCaption: 'detach me', + attachCaption: 'attach me', + caseId: 'testcase', + articleIdField: 'article' + }, + env => { + env.searchInterface.usageAnalytics = env.usageAnalytics; + return env; + } + ) ); attachResult.cmp.attach().then(() => { @@ -210,6 +245,16 @@ describe('AttachResult', () => { }); attachResult.cmp.detach(); }); + + it('should log a detach event', async () => { + await attachResult.cmp.detach(); + expect(attachResult.env.usageAnalytics.logCustomEvent).toHaveBeenCalledWith( + analyticsActionCauseList.caseDetach, + jasmine.objectContaining({ caseID: 'testcase', articleID: 'foo', resultUriHash: fakeResult.raw.urihash }), + attachResult.cmp.element, + fakeResult + ); + }); }); describe('click', () => {