From 9a664b98bfa84b1c7a57a156498ccf950d9c19d9 Mon Sep 17 00:00:00 2001 From: Michael Grondines Date: Thu, 15 Aug 2019 15:42:03 -0400 Subject: [PATCH 1/3] Added strings for defaults strings of AttachResult and ResultsFilter Added events when attaching / detaching result and filtering SNOW-182 --- src/components/AttachResult/AttachResult.ts | 13 ++++++++---- src/components/AttachResult/Events.ts | 10 ++++++++++ src/components/AttachResult/Strings.ts | 6 ++++++ src/components/ResultsFilter/Events.ts | 7 +++++++ src/components/ResultsFilter/ResultsFilter.ts | 8 ++++++-- src/components/ResultsFilter/Strings.ts | 5 +++++ .../AttachResult/AttachResult.spec.ts | 17 ++++++++++++++++ .../ResultsFilter/ResultsFilter.spec.ts | 20 ++++++++++++++++++- 8 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 src/components/AttachResult/Events.ts create mode 100644 src/components/AttachResult/Strings.ts create mode 100644 src/components/ResultsFilter/Events.ts create mode 100644 src/components/ResultsFilter/Strings.ts diff --git a/src/components/AttachResult/AttachResult.ts b/src/components/AttachResult/AttachResult.ts index 1de00a09..661a365c 100644 --- a/src/components/AttachResult/AttachResult.ts +++ b/src/components/AttachResult/AttachResult.ts @@ -8,9 +8,12 @@ import { IAnalyticsCaseAttachMeta, IAnalyticsCaseDetachMeta, analyticsActionCauseList, - IAnalyticsActionCause + IAnalyticsActionCause, + l } from 'coveo-search-ui'; import { paperclipIcon } from '../../utils/icons'; +import { AttachResultEvents, IAttachResultEventArgs } from './Events'; +import './Strings'; export interface IAttachResultOptions { /** Specifies the tooltip displayed when the result is not attached. */ @@ -37,12 +40,12 @@ export class AttachResult extends Component { private buttonElement: HTMLElement; private tooltipElement: HTMLElement; - static options: IAttachResultOptions = { + public static readonly options: IAttachResultOptions = { attachCaption: ComponentOptions.buildStringOption({ - defaultValue: 'Attach Result' + defaultValue: l(`${AttachResult.ID}_DefaultAttachCaption`) }), detachCaption: ComponentOptions.buildStringOption({ - defaultValue: 'Detach Result' + defaultValue: l(`${AttachResult.ID}_DefaultDetachCaption`) }), attach: ComponentOptions.buildCustomOption( name => (result: IQueryResult) => @@ -111,6 +114,7 @@ export class AttachResult extends Component { .then(() => { this.attached = true; this.logAnalyticsCaseEvent(analyticsActionCauseList.caseAttach); + Coveo.$$(this.root).trigger(AttachResultEvents.Attach, { queryResult: this.queryResult } as IAttachResultEventArgs); }) .finally(() => { this.setLoading(false); @@ -131,6 +135,7 @@ export class AttachResult extends Component { .then(() => { this.attached = false; this.logAnalyticsCaseEvent(analyticsActionCauseList.caseDetach); + Coveo.$$(this.root).trigger(AttachResultEvents.Detach, { queryResult: this.queryResult } as IAttachResultEventArgs); }) .finally(() => { this.setLoading(false); diff --git a/src/components/AttachResult/Events.ts b/src/components/AttachResult/Events.ts new file mode 100644 index 00000000..d5078fdd --- /dev/null +++ b/src/components/AttachResult/Events.ts @@ -0,0 +1,10 @@ +import { IQueryResult } from 'coveo-search-ui'; + +export enum AttachResultEvents { + Attach = 'attach', + Detach = 'detach' +} + +export interface IAttachResultEventArgs { + queryResult: IQueryResult; +} diff --git a/src/components/AttachResult/Strings.ts b/src/components/AttachResult/Strings.ts new file mode 100644 index 00000000..6df09497 --- /dev/null +++ b/src/components/AttachResult/Strings.ts @@ -0,0 +1,6 @@ +import { Translation, Language } from '../../utils/translation'; + +Translation.register(Language.English, { + AttachResult_DefaultAttachCaption: 'Attach Result', + AttachResult_DefaultDetachCaption: 'Detach Result' +}); diff --git a/src/components/ResultsFilter/Events.ts b/src/components/ResultsFilter/Events.ts new file mode 100644 index 00000000..7da86f26 --- /dev/null +++ b/src/components/ResultsFilter/Events.ts @@ -0,0 +1,7 @@ +export enum ResultsFilterEvents { + Click = 'click' +} + +export interface IResultsFilterEventArgs { + checked: boolean; +} diff --git a/src/components/ResultsFilter/ResultsFilter.ts b/src/components/ResultsFilter/ResultsFilter.ts index f8942500..8069c73f 100644 --- a/src/components/ResultsFilter/ResultsFilter.ts +++ b/src/components/ResultsFilter/ResultsFilter.ts @@ -9,8 +9,11 @@ import { IBuildingQueryEventArgs, QueryStateModel, load, - IAttributesChangedEventArg + IAttributesChangedEventArg, + l } from 'coveo-search-ui'; +import { ResultsFilterEvents, IResultsFilterEventArgs } from './Events'; +import './Strings'; export interface IAnalyticsFilteredResultsMeta { filteredResults: boolean; @@ -36,7 +39,7 @@ export class ResultsFilter extends Component { static options: IResultsFilterOptions = { text: ComponentOptions.buildStringOption({ - defaultValue: 'Filter Results' + defaultValue: l(`${ResultsFilter.ID}_DefaultText`) }), field: ComponentOptions.buildStringOption({ defaultValue: 'urihash' @@ -97,6 +100,7 @@ export class ResultsFilter extends Component { private handleCheckboxChange(checkbox: Checkbox) { this.queryStateModel.set(QueryStateModel.getFacetId(ResultsFilter.ID), this.checkbox.isSelected()); this.triggerQuery(); + Coveo.$$(this.root).trigger(ResultsFilterEvents.Click, { checked: this.checkbox.isSelected() } as IResultsFilterEventArgs); } private triggerQuery() { diff --git a/src/components/ResultsFilter/Strings.ts b/src/components/ResultsFilter/Strings.ts new file mode 100644 index 00000000..8c98f14a --- /dev/null +++ b/src/components/ResultsFilter/Strings.ts @@ -0,0 +1,5 @@ +import { Translation, Language } from '../../utils/translation'; + +Translation.register(Language.English, { + ResultsFilter_DefaultText: 'Filter Results' +}); diff --git a/tests/components/AttachResult/AttachResult.spec.ts b/tests/components/AttachResult/AttachResult.spec.ts index e5002f4b..17b32d73 100644 --- a/tests/components/AttachResult/AttachResult.spec.ts +++ b/tests/components/AttachResult/AttachResult.spec.ts @@ -1,6 +1,7 @@ import { AttachResult, IAttachResultOptions } from '../../../src/components/AttachResult/AttachResult'; import { Mock, Fake } from 'coveo-search-ui-tests'; import { IQueryResult, Logger } from 'coveo-search-ui'; +import { AttachResultEvents, IAttachResultEventArgs } from '../../../src/components/AttachResult/Events'; describe('AttachResult', () => { let attachResult: Mock.IBasicComponentSetup; @@ -129,6 +130,14 @@ describe('AttachResult', () => { await attachResult.cmp.attach(); expect(attachResult.cmp.element.querySelector('.coveo-caption-for-icon').innerHTML).toBe('detach me'); }); + + it('should trigger the attach event', done => { + Coveo.$$(attachResult.env.root).on(AttachResultEvents.Attach, (evt: Event, args: IAttachResultEventArgs) => { + expect(args.queryResult).not.toBeNull(); + done(); + }); + attachResult.cmp.attach(); + }); }); describe('detach', () => { @@ -186,6 +195,14 @@ describe('AttachResult', () => { await attachResult.cmp.detach(); expect(attachResult.cmp.element.querySelector('.coveo-caption-for-icon').innerHTML).toBe('attach me'); }); + + it('should trigger the detach event', done => { + Coveo.$$(attachResult.env.root).on(AttachResultEvents.Detach, (evt: Event, args: IAttachResultEventArgs) => { + expect(args.queryResult).not.toBeNull(); + done(); + }); + attachResult.cmp.detach(); + }); }); describe('click', () => { diff --git a/tests/components/ResultsFilter/ResultsFilter.spec.ts b/tests/components/ResultsFilter/ResultsFilter.spec.ts index 5b1b94ff..5c419351 100644 --- a/tests/components/ResultsFilter/ResultsFilter.spec.ts +++ b/tests/components/ResultsFilter/ResultsFilter.spec.ts @@ -1,6 +1,7 @@ import { ResultsFilter, IResultsFilterOptions } from '../../../src/components/ResultsFilter/ResultsFilter'; import { Mock, Simulate } from 'coveo-search-ui-tests'; -import { QueryStateModel } from 'coveo-search-ui'; +import { QueryStateModel, Assert } from 'coveo-search-ui'; +import { ResultsFilterEvents, IResultsFilterEventArgs } from '../../../src/components/ResultsFilter/Events'; describe('ResultsFilter', () => { let filter: Mock.IBasicComponentSetup; @@ -42,6 +43,23 @@ describe('ResultsFilter', () => { expect(filter.cmp.isSelected()).toBeFalsy(); }); + it('should trigger events on toggling', done => { + let cpt = 0; + Coveo.$$(filter.env.root).on(ResultsFilterEvents.Click, (evt: Event, args: IResultsFilterEventArgs) => { + expect(evt.type).toBe(ResultsFilterEvents.Click); + if (args.checked) { + cpt++; + } else { + cpt++; + } + if (cpt == 2) { + done(); + } + }); + filter.cmp.toggle(); + filter.cmp.toggle(); + }); + describe('when setting options', () => { beforeEach(() => { filter = Mock.optionsComponentSetup(ResultsFilter, { From f77f8730bb4952b74941964f53e1b82a3c8c167c Mon Sep 17 00:00:00 2001 From: Michael Grondines Date: Mon, 19 Aug 2019 14:58:41 -0400 Subject: [PATCH 2/3] PR modifications Added side effects files SNOW-182 --- package.json | 2 + src/components/AttachResult/AttachResult.ts | 4 +- src/components/AttachResult/Events.ts | 10 +++++ src/components/AttachResult/Strings.ts | 4 +- src/components/ResultsFilter/Events.ts | 9 ++++ src/components/ResultsFilter/ResultsFilter.ts | 2 +- src/components/ResultsFilter/Strings.ts | 2 +- .../AttachResult/AttachResult.spec.ts | 7 ++++ .../ResultsFilter/ResultsFilter.spec.ts | 41 ++++++++++++------- 9 files changed, 60 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 73e01959..67830f21 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "module": "./bin/es6/Index.js", "types": "./bin/typings", "sideEffects": [ + "./bin/es6/components/AttachResult/Strings.js", + "./bin/es6/components/ResultsFilter/Strings.js", "./bin/es6/components/UserActions/Strings.js" ], "scripts": { diff --git a/src/components/AttachResult/AttachResult.ts b/src/components/AttachResult/AttachResult.ts index 661a365c..2fb6873a 100644 --- a/src/components/AttachResult/AttachResult.ts +++ b/src/components/AttachResult/AttachResult.ts @@ -42,10 +42,10 @@ export class AttachResult extends Component { public static readonly options: IAttachResultOptions = { attachCaption: ComponentOptions.buildStringOption({ - defaultValue: l(`${AttachResult.ID}_DefaultAttachCaption`) + defaultValue: l(`${AttachResult.ID}_Attach`) }), detachCaption: ComponentOptions.buildStringOption({ - defaultValue: l(`${AttachResult.ID}_DefaultDetachCaption`) + defaultValue: l(`${AttachResult.ID}_Detach`) }), attach: ComponentOptions.buildCustomOption( name => (result: IQueryResult) => diff --git a/src/components/AttachResult/Events.ts b/src/components/AttachResult/Events.ts index d5078fdd..e4a07fea 100644 --- a/src/components/AttachResult/Events.ts +++ b/src/components/AttachResult/Events.ts @@ -1,10 +1,20 @@ import { IQueryResult } from 'coveo-search-ui'; +/** + * List of possible event types triggered by the **AttachResult** component + * when a user interacts with it. + */ export enum AttachResultEvents { Attach = 'attach', Detach = 'detach' } +/** + * Arguments sent with the events coming from the **AttachResult** component. + */ export interface IAttachResultEventArgs { + /** + * The **IQueryResult** that is attached to the **AttachResult** component. + */ queryResult: IQueryResult; } diff --git a/src/components/AttachResult/Strings.ts b/src/components/AttachResult/Strings.ts index 6df09497..3cd215e1 100644 --- a/src/components/AttachResult/Strings.ts +++ b/src/components/AttachResult/Strings.ts @@ -1,6 +1,6 @@ import { Translation, Language } from '../../utils/translation'; Translation.register(Language.English, { - AttachResult_DefaultAttachCaption: 'Attach Result', - AttachResult_DefaultDetachCaption: 'Detach Result' + AttachResult_Attach: 'Attach Result', + AttachResult_Detach: 'Detach Result' }); diff --git a/src/components/ResultsFilter/Events.ts b/src/components/ResultsFilter/Events.ts index 7da86f26..3f08028c 100644 --- a/src/components/ResultsFilter/Events.ts +++ b/src/components/ResultsFilter/Events.ts @@ -1,7 +1,16 @@ +/** + * Events triggered by the **ResultsFilter** component. + */ export enum ResultsFilterEvents { Click = 'click' } +/** + * Arguments sent with the events coming from the **ResultsFilter** component. + */ export interface IResultsFilterEventArgs { + /** + * Whether the filter is currently checked or not. + */ checked: boolean; } diff --git a/src/components/ResultsFilter/ResultsFilter.ts b/src/components/ResultsFilter/ResultsFilter.ts index 8069c73f..228a3f35 100644 --- a/src/components/ResultsFilter/ResultsFilter.ts +++ b/src/components/ResultsFilter/ResultsFilter.ts @@ -39,7 +39,7 @@ export class ResultsFilter extends Component { static options: IResultsFilterOptions = { text: ComponentOptions.buildStringOption({ - defaultValue: l(`${ResultsFilter.ID}_DefaultText`) + defaultValue: l(`${ResultsFilter.ID}_Label`) }), field: ComponentOptions.buildStringOption({ defaultValue: 'urihash' diff --git a/src/components/ResultsFilter/Strings.ts b/src/components/ResultsFilter/Strings.ts index 8c98f14a..0e89ee77 100644 --- a/src/components/ResultsFilter/Strings.ts +++ b/src/components/ResultsFilter/Strings.ts @@ -1,5 +1,5 @@ import { Translation, Language } from '../../utils/translation'; Translation.register(Language.English, { - ResultsFilter_DefaultText: 'Filter Results' + ResultsFilter_Label: 'Filter Results' }); diff --git a/tests/components/AttachResult/AttachResult.spec.ts b/tests/components/AttachResult/AttachResult.spec.ts index 17b32d73..e4a4557f 100644 --- a/tests/components/AttachResult/AttachResult.spec.ts +++ b/tests/components/AttachResult/AttachResult.spec.ts @@ -56,6 +56,13 @@ describe('AttachResult', () => { }, 50); }); + it('tooltip should contain the default localized string', async () => { + await attachResult.cmp.attach(); + expect(attachResult.cmp.element.querySelector('.coveo-caption-for-icon').textContent).toBe('Detach Result'); + await attachResult.cmp.detach(); + expect(attachResult.cmp.element.querySelector('.coveo-caption-for-icon').textContent).toBe('Attach Result'); + }); + it('should be detached when isAttached returns false', done => { isAttachedSpy.and.returnValue(Promise.resolve(false)); attachResult = Mock.optionsResultComponentSetup(AttachResult, { isAttached: faker.isAttached }, fakeResult); diff --git a/tests/components/ResultsFilter/ResultsFilter.spec.ts b/tests/components/ResultsFilter/ResultsFilter.spec.ts index 5c419351..695d4d0f 100644 --- a/tests/components/ResultsFilter/ResultsFilter.spec.ts +++ b/tests/components/ResultsFilter/ResultsFilter.spec.ts @@ -1,7 +1,8 @@ import { ResultsFilter, IResultsFilterOptions } from '../../../src/components/ResultsFilter/ResultsFilter'; import { Mock, Simulate } from 'coveo-search-ui-tests'; -import { QueryStateModel, Assert } from 'coveo-search-ui'; +import { QueryStateModel } from 'coveo-search-ui'; import { ResultsFilterEvents, IResultsFilterEventArgs } from '../../../src/components/ResultsFilter/Events'; +import { Translation, Language } from '../../../src/utils/translation'; describe('ResultsFilter', () => { let filter: Mock.IBasicComponentSetup; @@ -43,21 +44,31 @@ describe('ResultsFilter', () => { expect(filter.cmp.isSelected()).toBeFalsy(); }); - it('should trigger events on toggling', done => { - let cpt = 0; - Coveo.$$(filter.env.root).on(ResultsFilterEvents.Click, (evt: Event, args: IResultsFilterEventArgs) => { - expect(evt.type).toBe(ResultsFilterEvents.Click); - if (args.checked) { - cpt++; - } else { - cpt++; - } - if (cpt == 2) { - done(); - } + it('should trigger event with checked true when first toggling', () => { + return new Promise(resolve => { + Coveo.$$(filter.env.root).on(ResultsFilterEvents.Click, (evt: Event, args: IResultsFilterEventArgs) => { + expect(evt.type).toBe(ResultsFilterEvents.Click); + expect(args.checked).toBeTruthy(); + resolve(); + }); + filter.cmp.toggle(); + }); + }); + + it('should trigger event with checked false when toggling twice', () => { + return new Promise(resolve => { + filter.cmp.toggle(); + Coveo.$$(filter.env.root).on(ResultsFilterEvents.Click, (evt: Event, args: IResultsFilterEventArgs) => { + expect(evt.type).toBe(ResultsFilterEvents.Click); + expect(args.checked).toBeFalsy(); + resolve(); + }); + filter.cmp.toggle(); }); - filter.cmp.toggle(); - filter.cmp.toggle(); + }); + + it('should contain the default label string', () => { + expect(filter.cmp.element.querySelector('span').innerText).toBe('Filter Results'); }); describe('when setting options', () => { From bc8251db870ccf7ad3a25bf08072a9a3ba630178 Mon Sep 17 00:00:00 2001 From: Michael Grondines Date: Tue, 20 Aug 2019 13:25:29 -0400 Subject: [PATCH 3/3] Added slightly more comments --- src/components/AttachResult/AttachResult.ts | 3 +++ src/components/ResultsFilter/ResultsFilter.ts | 6 ++++++ tests/components/ResultsFilter/ResultsFilter.spec.ts | 2 -- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/AttachResult/AttachResult.ts b/src/components/AttachResult/AttachResult.ts index 2fb6873a..2af70ddb 100644 --- a/src/components/AttachResult/AttachResult.ts +++ b/src/components/AttachResult/AttachResult.ts @@ -15,6 +15,9 @@ import { paperclipIcon } from '../../utils/icons'; import { AttachResultEvents, IAttachResultEventArgs } from './Events'; import './Strings'; +/** + * Possible options to configure the **AttachResult** component. + */ export interface IAttachResultOptions { /** Specifies the tooltip displayed when the result is not attached. */ attachCaption?: string; diff --git a/src/components/ResultsFilter/ResultsFilter.ts b/src/components/ResultsFilter/ResultsFilter.ts index 228a3f35..b47945f8 100644 --- a/src/components/ResultsFilter/ResultsFilter.ts +++ b/src/components/ResultsFilter/ResultsFilter.ts @@ -15,10 +15,16 @@ import { import { ResultsFilterEvents, IResultsFilterEventArgs } from './Events'; import './Strings'; +/** + * Metadata sent when an analytics event is sent. + */ export interface IAnalyticsFilteredResultsMeta { filteredResults: boolean; } +/** + * Possible options to configure the **ResultsFilter** component. + */ export interface IResultsFilterOptions { /** Specifies the text displayed next to the checkbox. */ text?: string; diff --git a/tests/components/ResultsFilter/ResultsFilter.spec.ts b/tests/components/ResultsFilter/ResultsFilter.spec.ts index 695d4d0f..8f7aa3fc 100644 --- a/tests/components/ResultsFilter/ResultsFilter.spec.ts +++ b/tests/components/ResultsFilter/ResultsFilter.spec.ts @@ -47,7 +47,6 @@ describe('ResultsFilter', () => { it('should trigger event with checked true when first toggling', () => { return new Promise(resolve => { Coveo.$$(filter.env.root).on(ResultsFilterEvents.Click, (evt: Event, args: IResultsFilterEventArgs) => { - expect(evt.type).toBe(ResultsFilterEvents.Click); expect(args.checked).toBeTruthy(); resolve(); }); @@ -59,7 +58,6 @@ describe('ResultsFilter', () => { return new Promise(resolve => { filter.cmp.toggle(); Coveo.$$(filter.env.root).on(ResultsFilterEvents.Click, (evt: Event, args: IResultsFilterEventArgs) => { - expect(evt.type).toBe(ResultsFilterEvents.Click); expect(args.checked).toBeFalsy(); resolve(); });