diff --git a/package.json b/package.json
index 7f028a1ce8..dff64dc546 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"scripts": {
"dev": "gulp dev",
"test": "npm run unitTests",
+ "test:watch": "gulp devTest",
"unitTests": "gulp unitTests && gulp coverage",
"accessibilityTests": "gulp accessibilityTests",
"testChunks": "node chunkTesters/chunk.tester.js",
diff --git a/pages/index.html b/pages/index.html
index 7a948afdf2..a2f35051ef 100644
--- a/pages/index.html
+++ b/pages/index.html
@@ -10,7 +10,7 @@
diff --git a/src/ui/MissingTerm/MissingTerms.ts b/src/ui/MissingTerm/MissingTerms.ts
index bb1ccce4ea..59b3823ee5 100644
--- a/src/ui/MissingTerm/MissingTerms.ts
+++ b/src/ui/MissingTerm/MissingTerms.ts
@@ -9,6 +9,7 @@ import { IComponentBindings } from '../Base/ComponentBindings';
import { ComponentOptions } from '../Base/ComponentOptions';
import { MissingTermManager } from './MissingTermManager';
import XRegExp = require('xregexp');
+import { intersection } from 'underscore';
export interface IMissingTermsOptions {
caption?: string;
@@ -46,8 +47,8 @@ export class MissingTerms extends Component {
/**
* The maximum number of missing term to be displayed
*
- * **Default:** `5`
- * **Minimum value:** `1`
+ * **Default:** `5`
+ * **Minimum value:** `1`
*/
numberOfTerms: ComponentOptions.buildNumberOption({
defaultValue: 5,
@@ -81,13 +82,32 @@ export class MissingTerms extends Component {
this.options = ComponentOptions.initComponentOptions(element, MissingTerms, options);
this.addMissingTerms();
}
+
+ private get absentTerms() {
+ let absentTerms = this.result.absentTerms;
+
+ if (this.result.attachments) {
+ absentTerms = this.intersectAbsentTerms(absentTerms, this.result.attachments);
+ }
+
+ if (this.result.childResults) {
+ absentTerms = this.intersectAbsentTerms(absentTerms, this.result.childResults);
+ }
+
+ return absentTerms;
+ }
+
+ private intersectAbsentTerms(absentTerms: string[], results: IQueryResult[]) {
+ return intersection(absentTerms, ...results.map(result => result.absentTerms));
+ }
+
/**
- *Returns all original basic query expression terms that were not matched by the result item the component instance is associated with.
+ * Returns all original basic query expression terms that were not matched by the result item the component instance is associated with.
*/
public get missingTerms(): string[] {
const terms = [];
- for (const term of this.result.absentTerms) {
+ for (const term of this.absentTerms) {
const regex = this.createWordBoundaryDelimitedRegex(term);
const query = this.queryStateModel.get('q');
const result = regex.exec(query);
diff --git a/unitTests/ui/MissingTermsTest.ts b/unitTests/ui/MissingTermsTest.ts
index 00bba27e99..effe72c775 100644
--- a/unitTests/ui/MissingTermsTest.ts
+++ b/unitTests/ui/MissingTermsTest.ts
@@ -5,7 +5,7 @@ import { FakeResults } from '../Fake';
import { IQueryResult } from '../../src/rest/QueryResult';
export function MissingTermsTest() {
- describe('MissingTerm', () => {
+ describe('MissingTerms', () => {
let test: Mock.IBasicComponentSetup;
let fakeResult: IQueryResult;
@@ -13,10 +13,14 @@ export function MissingTermsTest() {
const test = Mock.advancedResultComponentSetup(
MissingTerms,
fakeResult,
- new Mock.AdvancedComponentSetupOptions(null, option, (env: Mock.MockEnvironmentBuilder): Mock.MockEnvironmentBuilder => {
- env.withLiveQueryStateModel().queryStateModel.set('q', query);
- return env;
- })
+ new Mock.AdvancedComponentSetupOptions(
+ null,
+ option,
+ (env: Mock.MockEnvironmentBuilder): Mock.MockEnvironmentBuilder => {
+ env.withLiveQueryStateModel().queryStateModel.set('q', query);
+ return env;
+ }
+ )
);
const analyticsElement = $$('div', {
className: 'CoveoAnalytics'
@@ -52,7 +56,7 @@ export function MissingTermsTest() {
});
it(`true,
- it should log a addMissingTerm event when it is clicked`, function() {
+ it should log a addMissingTerm event when it is clicked`, function () {
const query = 'This is my query';
fakeResult.absentTerms = ['This'];
test = mockComponent(query);
@@ -106,9 +110,7 @@ export function MissingTermsTest() {
});
it('when the show more button is clicked, show all the missing terms', () => {
- $$(test.cmp.element)
- .find('.coveo-missing-term-show-more')
- .click();
+ $$(test.cmp.element).find('.coveo-missing-term-show-more').click();
const visibleMissingTerm = $$(test.cmp.element)
.findAll('.coveo-missing-term')
.filter(element => {
@@ -118,6 +120,7 @@ export function MissingTermsTest() {
});
});
});
+
describe('when the langage is', () => {
const getMissingTerms = () => {
return test.cmp.queryStateModel.get('missingTerms');
@@ -289,5 +292,43 @@ export function MissingTermsTest() {
});
});
});
+
+ describe('with attachments & child results', () => {
+ it('should only display missing terms that are returned both by the result & its attachments', () => {
+ const attachment = FakeResults.createFakeResult();
+ attachment.absentTerms = ['hello', 'bye'];
+
+ fakeResult.absentTerms = ['hello', 'world'];
+ fakeResult.attachments = [attachment];
+
+ test = mockComponent('hello world bye');
+ expect(test.cmp.missingTerms).toEqual(['hello']);
+ });
+
+ it('should only display missing terms that are returned both by the result & its child results', () => {
+ const childResult = FakeResults.createFakeResult();
+ childResult.absentTerms = ['hello', 'bye'];
+
+ fakeResult.absentTerms = ['hello', 'world'];
+ fakeResult.childResults = [childResult];
+
+ test = mockComponent('hello world bye');
+ expect(test.cmp.missingTerms).toEqual(['hello']);
+ });
+
+ it('should only display missing terms that are returned by the result, its attachments & its child results', () => {
+ const childResult = FakeResults.createFakeResult();
+ childResult.absentTerms = ['hello', 'world', 'forever'];
+ const attachment = FakeResults.createFakeResult();
+ attachment.absentTerms = ['hello', 'world', 'bye'];
+
+ fakeResult.absentTerms = ['hello', 'world', 'bye'];
+ fakeResult.attachments = [attachment];
+ fakeResult.childResults = [childResult];
+
+ test = mockComponent('hello world bye forever');
+ expect(test.cmp.missingTerms).toEqual(['hello', 'world']);
+ });
+ });
});
}