Skip to content

Commit

Permalink
feat(quantic)!: logic to handle opening smart snippet source inside s…
Browse files Browse the repository at this point in the history
…alesforce added (#4323)

[SFINT-5438](https://coveord.atlassian.net/browse/SFINT-5438)

- Added logic to support opening smart sources in Salesforce with the
help of the Navigation mixins utilities.
- This changes contain a breaking change so this will be part of the v3
milestone.
- The breaking changes consists of deleting two public properties
`title` and `url` that were exposed in the `QuanticSmartSnippetSource`
component and replacing them by the a new `source` property
- Unit tests added.


### Demo:



https://github.com/user-attachments/assets/e227c518-365a-446c-8d33-b3ab0eaa9bea



[SFINT-5438]:
https://coveord.atlassian.net/browse/SFINT-5438?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Louis Bompart <[email protected]>
  • Loading branch information
mmitiche and louis-bompart authored Sep 5, 2024
1 parent 65e58fd commit 7dca4f5
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
// @ts-ignore
getNavigateCalledWith, // @ts-ignore
getNavigateCalledWith,
getGenerateUrlCalledWith,
} from 'lightning/navigation';
// @ts-ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as mockHeadlessLoader from 'c/quanticHeadlessLoader';
import {
// @ts-ignore
getNavigateCalledWith, // @ts-ignore
getNavigateCalledWith,
getGenerateUrlCalledWith,
} from 'lightning/navigation';
// @ts-ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
onclick={handleToggleSmartSnippetAnswer} icon-position="right"></lightning-button>
</div>
</template>
<c-quantic-smart-snippet-source title={sourceTitle} uri={sourceUri}
<c-quantic-smart-snippet-source source={source}
actions={smartSnippetSourceActions}></c-quantic-smart-snippet-source>
</div>
</lightning-card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {LightningElement, api} from 'lwc';
/** @typedef {import("coveo").SmartSnippetState} SmartSnippetState */
/** @typedef {import("coveo").SmartSnippetFeedback} SmartSnippetFeedback */
/** @typedef {import("coveo").SearchStatus} SearchStatus */
/** @typedef {import("coveo").Result} Result */

const FEEDBACK_LIKED_STATE = 'liked';
const FEEDBACK_DISLIKED_STATE = 'disliked';
Expand Down Expand Up @@ -332,19 +333,11 @@ export default class QuanticSmartSnippet extends LightningElement {
}

/**
* Returns the smart snippet source title.
* @returns {string}
*/
get sourceTitle() {
return this?.state?.source?.title;
}

/**
* Returns the smart snippet source uri.
* @returns {string}
* Returns the smart snippet source.
* @returns {Result}
*/
get sourceUri() {
return this?.state?.source?.clickUri;
get source() {
return this?.state?.source;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import {
getNavigateCalledWith,
getGenerateUrlCalledWith,
} from 'lightning/navigation';
// @ts-ignore
import {createElement} from 'lwc';
import QuanticSmartSnippetSource from '../quanticSmartSnippetSource';
Expand All @@ -22,8 +26,10 @@ const exampleActions = {
};

const defaultOptions = {
uri: exampleUri,
title: exampleTitle,
source: {
clickUri: exampleUri,
title: exampleTitle,
},
actions: exampleActions,
};

Expand Down Expand Up @@ -104,7 +110,13 @@ describe('c-quantic-smart-snippet-source', () => {
});

it('should not display the source uri when the uri option is undefined', async () => {
const element = createTestComponent({...defaultOptions, uri: undefined});
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: undefined,
title: exampleTitle,
},
});
await flushPromises();

const sourceUri = element.shadowRoot.querySelector(selectors.sourceUri);
Expand All @@ -113,7 +125,13 @@ describe('c-quantic-smart-snippet-source', () => {
});

it('should not display the source title when the title option is undefined', async () => {
const element = createTestComponent({...defaultOptions, title: undefined});
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: exampleUri,
title: undefined,
},
});
await flushPromises();

const sourceTitle = element.shadowRoot.querySelector(selectors.sourceTitle);
Expand All @@ -125,7 +143,13 @@ describe('c-quantic-smart-snippet-source', () => {
describe(`the analytics bindings of the ${key}`, () => {
for (const [eventName, action] of Object.entries(bindingsMap)) {
it(`should execute the proper action when the ${eventName} is triggered`, async () => {
const element = createTestComponent({...defaultOptions, uri: '#'});
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: '#',
title: exampleTitle,
},
});
await flushPromises();

const sourceUri = element.shadowRoot.querySelector(selectors[key]);
Expand All @@ -136,4 +160,131 @@ describe('c-quantic-smart-snippet-source', () => {
}
});
});

describe('when the smart snippet source is of type Salesforce', () => {
const exampleSfid = '123';
const exampleSalesforceLink = 'https://www.example-salesforce.com/';

it('should call the navigation mixin to get the Salesforce record URL', async () => {
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: exampleUri,
title: exampleTitle,
raw: {
sfid: exampleSfid,
},
},
});
await flushPromises();

const sourceTitle = element.shadowRoot.querySelector(
selectors.sourceTitle
);
const sourceUri = element.shadowRoot.querySelector(selectors.sourceUri);
const {pageReference} = getGenerateUrlCalledWith();

expect(pageReference.attributes.recordId).toBe(exampleSfid);
expect(sourceTitle.href).toBe(exampleSalesforceLink);
expect(sourceUri.href).toBe(exampleSalesforceLink);
});

it('should open the source link inside Salesforce after clicking the source title', async () => {
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: exampleUri,
title: exampleTitle,
raw: {
sfid: exampleSfid,
},
},
});
await flushPromises();

const sourceTitle = element.shadowRoot.querySelector(
selectors.sourceTitle
);
sourceTitle.click();

const {pageReference} = getNavigateCalledWith();

expect(pageReference.attributes.recordId).toBe(exampleSfid);
});

it('should open the source link inside Salesforce after clicking the source uri', async () => {
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: exampleUri,
title: exampleTitle,
raw: {
sfid: exampleSfid,
},
},
});
await flushPromises();

const sourceUri = element.shadowRoot.querySelector(selectors.sourceUri);
sourceUri.click();

const {pageReference} = getNavigateCalledWith();

expect(pageReference.attributes.recordId).toBe(exampleSfid);
});

describe('when the result is a knowledge article', () => {
it('should open the source link inside Salesforce after clicking the source title', async () => {
const exampleSfkavid = 'bar';
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: exampleUri,
title: exampleTitle,
raw: {
sfid: exampleSfid,
sfkbid: 'foo',
sfkavid: exampleSfkavid,
},
},
});
await flushPromises();

const sourceTitle = element.shadowRoot.querySelector(
selectors.sourceTitle
);
sourceTitle.click();

const {pageReference} = getNavigateCalledWith();

expect(pageReference.attributes.recordId).toBe(exampleSfkavid);
expect(sourceTitle.href).toBe(exampleSalesforceLink);
});

it('should open the source link inside Salesforce after clicking the source uri', async () => {
const exampleSfkavid = 'bar';
const element = createTestComponent({
...defaultOptions,
source: {
clickUri: exampleUri,
title: exampleTitle,
raw: {
sfid: exampleSfid,
sfkbid: 'foo',
sfkavid: exampleSfkavid,
},
},
});
await flushPromises();

const sourceUri = element.shadowRoot.querySelector(selectors.sourceUri);
sourceUri.click();

const {pageReference} = getNavigateCalledWith();

expect(pageReference.attributes.recordId).toBe(exampleSfkavid);
expect(sourceUri.href).toBe(exampleSalesforceLink);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<template>
<div class="smart-snippet__source">
<template lwc:if={uri}>
<template lwc:if={sourceUri}>
<div class="slds-truncate">
<a data-cy="smart-snippet__source-uri" class="slds-text-title_bold smart-snippet__source-uri" title={uri}
href={uri} target="_blank">{uri}</a>
<a href={hrefValue} aria-label={ariaLabelValue} onclick={handleClick} data-cy="smart-snippet__source-uri"
class="slds-text-title_bold smart-snippet__source-uri" title={sourceUri} target="_blank">{sourceUri}</a>
</div>
</template>
<template lwc:if={title}>
<template lwc:if={sourceTitle}>
<div class="slds-var-m-top_xx-small">
<a data-cy="smart-snippet__source-title" class="smart-snippet__source-title slds-text-heading_small" href={uri}
title={title} target="_blank">{title}</a>
<a href={hrefValue} aria-label={ariaLabelValue} onclick={handleClick} data-cy="smart-snippet__source-title"
class="smart-snippet__source-title slds-text-heading_small" title={sourceTitle}
target="_blank">{sourceTitle}</a>
</div>
</template>
</div>
Expand Down
Loading

0 comments on commit 7dca4f5

Please sign in to comment.