@coveo/quantic 3.37.9 → 3.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/force-app/main/default/lwc/quanticFeedback/__tests__/quanticFeedback.test.js +11 -0
- package/force-app/main/default/lwc/quanticFeedback/quanticFeedback.html +6 -4
- package/force-app/main/default/lwc/quanticFeedback/quanticFeedback.js +8 -0
- package/force-app/main/default/lwc/quanticGeneratedAnswer/__tests__/quanticGeneratedAnswer.test.js +32 -3
- package/force-app/main/default/lwc/quanticGeneratedAnswer/quanticGeneratedAnswer.css +1 -8
- package/force-app/main/default/lwc/quanticGeneratedAnswer/quanticGeneratedAnswer.js +6 -28
- package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/generatedAnswer.css +0 -13
- package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/generatedAnswer.html +120 -93
- package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/retryPrompt.html +24 -15
- package/force-app/main/default/lwc/quanticGeneratedAnswerCopyToClipboard/__tests__/quanticGeneratedAnswerCopyToClipboard.test.js +125 -0
- package/force-app/main/default/lwc/quanticGeneratedAnswerCopyToClipboard/quanticGeneratedAnswerCopyToClipboard.html +1 -1
- package/force-app/main/default/lwc/quanticGeneratedAnswerCopyToClipboard/quanticGeneratedAnswerCopyToClipboard.js +20 -1
- package/force-app/main/default/lwc/quanticResultHighlightedTextField/quanticResultHighlightedTextField.js +10 -1
- package/force-app/main/default/lwc/quanticResultLink/quanticResultLink.js +11 -4
- package/force-app/main/default/lwc/quanticResultQuickview/quanticResultQuickview.js +14 -2
- package/force-app/main/default/lwc/quanticThreadItem/__tests__/quanticThreadItem.test.js +176 -0
- package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.css +64 -0
- package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.html +48 -0
- package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.js +80 -0
- package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.js-meta.xml +5 -0
- package/force-app/main/default/lwc/quanticUtils/__tests__/quanticUtils.test.js +30 -0
- package/force-app/main/default/lwc/quanticUtils/quanticUtils.js +24 -0
- package/force-app/main/default/staticresources/coveoheadless/case-assist/headless.js +15 -15
- package/force-app/main/default/staticresources/coveoheadless/definitions/api/knowledge/stream-answer-api.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/api/platform-client.d.ts +5 -0
- package/force-app/main/default/staticresources/coveoheadless/definitions/app/case-assist-engine/case-assist-engine-configuration.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/app/insight-engine/insight-engine-configuration.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/app/recommendation-engine/recommendation-engine-configuration.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/app/search-engine/search-engine-configuration.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/features/case-assist-configuration/case-assist-configuration-actions.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/features/case-assist-configuration/case-assist-configuration-state.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/features/configuration/configuration-actions.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/features/configuration/configuration-state.d.ts +1 -1
- package/force-app/main/default/staticresources/coveoheadless/definitions/features/generated-answer/generated-answer-request.d.ts +2 -2
- package/force-app/main/default/staticresources/coveoheadless/headless.js +17 -17
- package/force-app/main/default/staticresources/coveoheadless/insight/headless.js +16 -16
- package/force-app/main/default/staticresources/coveoheadless/recommendation/headless.js +14 -14
- package/force-app/main/default/staticresources/dompurify/purify.min.js +2 -2
- package/package.json +6 -6
|
@@ -106,6 +106,17 @@ describe('c-quantic-feedback', () => {
|
|
|
106
106
|
expect(question.textContent).toBe(exampleQuestion);
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
+
it('should not render the feedback question when question is empty', async () => {
|
|
110
|
+
const element = createTestComponent({...defaultOptions, question: ''});
|
|
111
|
+
await flushPromises();
|
|
112
|
+
|
|
113
|
+
const question = element.shadowRoot.querySelector(
|
|
114
|
+
selectors.feedbackQuestion
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
expect(question).toBeNull();
|
|
118
|
+
});
|
|
119
|
+
|
|
109
120
|
describe('when the component is in a neutral state', () => {
|
|
110
121
|
it('should display the feedback buttons in a neutral state', async () => {
|
|
111
122
|
const element = createTestComponent();
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="slds-grid feedback__main-section">
|
|
3
|
-
<
|
|
4
|
-
|
|
3
|
+
<template lwc:if={hasQuestion}>
|
|
4
|
+
<span class="slds-var-p-right_small slds-text-color_weak feedback__question"
|
|
5
|
+
id="feedback__question">{question}</span>
|
|
6
|
+
</template>
|
|
5
7
|
<c-quantic-stateful-button selected={liked} data-testid="feedback__like-button" tooltip={likeLabel}
|
|
6
8
|
icon-name={likeIconName} onquantic__select={handleLike} onquantic__deselect={handleLike} without-borders selected-state-color="#2e844a"
|
|
7
9
|
label={likeButtonLabel} icon-size={size}></c-quantic-stateful-button>
|
|
@@ -9,10 +11,10 @@
|
|
|
9
11
|
icon-name={dislikeIconName} onquantic__select={handleDislike} onquantic__deselect={handleDislike} without-borders selected-state-color="#ea001e"
|
|
10
12
|
label={dislikeButtonLabel} icon-size={size}></c-quantic-stateful-button>
|
|
11
13
|
</div>
|
|
12
|
-
<template if
|
|
14
|
+
<template lwc:if={displaySuccessMessage}>
|
|
13
15
|
<div class="slds-grid feedback__success-message">
|
|
14
16
|
<span class="slds-var-p-vertical_x-small">{successMessage}</span>
|
|
15
|
-
<template if
|
|
17
|
+
<template lwc:if={shouldShowExplainWhyButton}>
|
|
16
18
|
<lightning-button data-testid="feedback__explain-why-button" class="slds-var-m-left_x-small feedback__explain-why"
|
|
17
19
|
variant="base" label={labels.explainWhy} onclick={handlePressExplainWhyButton}></lightning-button>
|
|
18
20
|
</template>
|
|
@@ -168,4 +168,12 @@ export default class QuanticFeedback extends LightningElement {
|
|
|
168
168
|
if (this.hideLabels) return '';
|
|
169
169
|
return this.dislikeLabel;
|
|
170
170
|
}
|
|
171
|
+
|
|
172
|
+
get hasQuestion() {
|
|
173
|
+
return !!this.question?.trim();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
get shouldShowExplainWhyButton() {
|
|
177
|
+
return !this.hideExplainWhyButton;
|
|
178
|
+
}
|
|
171
179
|
}
|
package/force-app/main/default/lwc/quanticGeneratedAnswer/__tests__/quanticGeneratedAnswer.test.js
CHANGED
|
@@ -73,8 +73,11 @@ function createTestComponent(options = defaultOptions, assignedElements = []) {
|
|
|
73
73
|
const selectors = {
|
|
74
74
|
initializationError: 'c-quantic-component-error',
|
|
75
75
|
generatedAnswerCard: '[data-testid="generated-answer__card"]',
|
|
76
|
+
generatedAnswerHeader: '[data-testid="generated-answer__header"]',
|
|
77
|
+
generatedAnswerBody: '[data-testid="generated-answer__body"]',
|
|
78
|
+
generatedAnswerFooter: '[data-testid="generated-answer__footer"]',
|
|
76
79
|
generatedAnswer: '[data-testid="generated-answer__answer"]',
|
|
77
|
-
generatedAnswerBadge: '[data-testid="generated-
|
|
80
|
+
generatedAnswerBadge: '[data-testid="generated-answer__header-title"]',
|
|
78
81
|
generatedAnswerRetryButton: '[data-testid="generated-answer__retry-button"]',
|
|
79
82
|
generatedAnswerActions: '[data-testid="generated-answer__actions"]',
|
|
80
83
|
generatedAnswerToggleButton: 'c-quantic-generated-answer-toggle',
|
|
@@ -471,7 +474,7 @@ describe('c-quantic-generated-answer', () => {
|
|
|
471
474
|
expect(generatedAnswerActions).toBeNull();
|
|
472
475
|
});
|
|
473
476
|
|
|
474
|
-
it('should not display the generated answer disclaimer', async () => {
|
|
477
|
+
it('should not display the generated answer disclaimer in the footer', async () => {
|
|
475
478
|
const element = createTestComponent();
|
|
476
479
|
await flushPromises();
|
|
477
480
|
|
|
@@ -727,24 +730,50 @@ describe('c-quantic-generated-answer', () => {
|
|
|
727
730
|
const element = createTestComponent();
|
|
728
731
|
await flushPromises();
|
|
729
732
|
|
|
733
|
+
const generatedAnswerBody = element.shadowRoot.querySelector(
|
|
734
|
+
selectors.generatedAnswerBody
|
|
735
|
+
);
|
|
730
736
|
const generatedAnswerActions = element.shadowRoot.querySelector(
|
|
731
737
|
selectors.generatedAnswerActions
|
|
732
738
|
);
|
|
733
739
|
|
|
740
|
+
expect(generatedAnswerBody).not.toBeNull();
|
|
734
741
|
expect(generatedAnswerActions).not.toBeNull();
|
|
742
|
+
expect(generatedAnswerActions.closest('section')).toBe(
|
|
743
|
+
generatedAnswerBody
|
|
744
|
+
);
|
|
735
745
|
});
|
|
736
746
|
|
|
737
|
-
it('should
|
|
747
|
+
it('should display the generated answer disclaimer', async () => {
|
|
738
748
|
const element = createTestComponent();
|
|
739
749
|
await flushPromises();
|
|
740
750
|
|
|
751
|
+
const generatedAnswerFooter = element.shadowRoot.querySelector(
|
|
752
|
+
selectors.generatedAnswerFooter
|
|
753
|
+
);
|
|
741
754
|
const generatedAnswerDisclaimer = element.shadowRoot.querySelector(
|
|
742
755
|
selectors.generatedAnswerDisclaimer
|
|
743
756
|
);
|
|
744
757
|
|
|
758
|
+
expect(generatedAnswerFooter).not.toBeNull();
|
|
745
759
|
expect(generatedAnswerDisclaimer).not.toBeNull();
|
|
746
760
|
});
|
|
747
761
|
|
|
762
|
+
it('should display the generated answer header content', async () => {
|
|
763
|
+
const element = createTestComponent();
|
|
764
|
+
await flushPromises();
|
|
765
|
+
|
|
766
|
+
const generatedAnswerHeader = element.shadowRoot.querySelector(
|
|
767
|
+
selectors.generatedAnswerHeader
|
|
768
|
+
);
|
|
769
|
+
const generatedAnswerBadge = element.shadowRoot.querySelector(
|
|
770
|
+
selectors.generatedAnswerBadge
|
|
771
|
+
);
|
|
772
|
+
|
|
773
|
+
expect(generatedAnswerHeader).not.toBeNull();
|
|
774
|
+
expect(generatedAnswerBadge).not.toBeNull();
|
|
775
|
+
});
|
|
776
|
+
|
|
748
777
|
it('should pass the disableCitationAnchoring property to the source citations component', async () => {
|
|
749
778
|
const element = createTestComponent();
|
|
750
779
|
await flushPromises();
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
.generated-
|
|
2
|
-
justify-content: space-between;
|
|
3
|
-
align-items: center;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.generated-answer__badge {
|
|
7
|
-
background-color: var(--lwc-colorBackgroundButtonDefaultHover, #eef4ff);
|
|
1
|
+
.generated-answer__header-title {
|
|
8
2
|
color: var(--lwc-brandPrimary, #1b96ff);
|
|
9
|
-
border-radius: var(--lwc-border-radius-medium, 0.25rem);
|
|
10
3
|
}
|
|
@@ -535,12 +535,12 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
535
535
|
];
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
get
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
538
|
+
get generatedAnswerHeaderClass() {
|
|
539
|
+
const headerBaseClass =
|
|
540
|
+
'generated-answer__card-header slds-grid slds-grid_vertical-align-center slds-grid_align-spread slds-p-horizontal_large slds-p-vertical_small';
|
|
541
|
+
return this.isVisible
|
|
542
|
+
? `${headerBaseClass} slds-border_bottom`
|
|
543
|
+
: headerBaseClass;
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
get citationFields() {
|
|
@@ -565,28 +565,6 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
565
565
|
return this.isAnswerCollapsed ? 'utility:chevrondown' : 'utility:chevronup';
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
-
get shouldShowCollapseGeneratingMessage() {
|
|
569
|
-
// If the answer is collapsed and is still streaming,
|
|
570
|
-
// we should show a message letting the user know it's still generating.
|
|
571
|
-
return (
|
|
572
|
-
this.collapsible &&
|
|
573
|
-
this.isVisible &&
|
|
574
|
-
this.isStreaming &&
|
|
575
|
-
this._exceedsMaximumHeight
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
get shouldShowToggleCollapseAnswer() {
|
|
580
|
-
// Only show the toggle collapse button if the answer is
|
|
581
|
-
// collapsible, visible, not streaming, and exceeds the maximum height.
|
|
582
|
-
return (
|
|
583
|
-
this.collapsible &&
|
|
584
|
-
this.isVisible &&
|
|
585
|
-
!this.isStreaming &&
|
|
586
|
-
this._exceedsMaximumHeight
|
|
587
|
-
);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
568
|
/**
|
|
591
569
|
* Returns the label to display in the generated answer show more|show less button.
|
|
592
570
|
* @returns {string}
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
@import '../quanticGeneratedAnswer.css';
|
|
2
2
|
|
|
3
|
-
.generated-answer__header-actions {
|
|
4
|
-
align-items: center;
|
|
5
|
-
flex-wrap: wrap-reverse;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
3
|
.generated-answer__answer {
|
|
9
4
|
overflow: hidden;
|
|
10
5
|
position: relative;
|
|
@@ -60,14 +55,6 @@
|
|
|
60
55
|
visibility: hidden;
|
|
61
56
|
}
|
|
62
57
|
|
|
63
|
-
.generated-answer__disclaimer {
|
|
64
|
-
min-height: var(--lwc-lineHeightButton,1.875rem);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.flex-one {
|
|
68
|
-
flex: 1;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
58
|
@keyframes cursor-blink {
|
|
72
59
|
100% {
|
|
73
60
|
visibility: hidden;
|
|
@@ -1,49 +1,34 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<template lwc:if={shouldDisplayGeneratedAnswer}>
|
|
3
|
-
<div data-testid="generated-answer__card" class="slds-box">
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
like-icon-name="utility:like"
|
|
21
|
-
like-label={labels.thisAnswerWasHelpful}
|
|
22
|
-
dislike-icon-name="utility:dislike"
|
|
23
|
-
dislike-label={labels.thisAnswerWasNotHelpful}
|
|
24
|
-
size="xx-small"
|
|
25
|
-
question=""
|
|
26
|
-
hide-explain-why-button
|
|
27
|
-
hide-labels
|
|
28
|
-
></c-quantic-feedback>
|
|
29
|
-
<c-quantic-generated-answer-copy-to-clipboard
|
|
30
|
-
data-testid="generated-answer__copy-to-clipboard"
|
|
31
|
-
answer={answer}
|
|
32
|
-
class="slds-var-m-horizontal_xx-small"
|
|
33
|
-
></c-quantic-generated-answer-copy-to-clipboard>
|
|
34
|
-
</div>
|
|
35
|
-
</template>
|
|
36
|
-
<template lwc:if={withToggle}>
|
|
37
|
-
<div class="slds-grid flex-one slds-grid_align-end">
|
|
38
|
-
<c-quantic-generated-answer-toggle
|
|
39
|
-
is-generated-answer-visible={isVisible}
|
|
40
|
-
></c-quantic-generated-answer-toggle>
|
|
41
|
-
</div>
|
|
42
|
-
</template>
|
|
3
|
+
<div data-testid="generated-answer__card" class="slds-box slds-p-around_none">
|
|
4
|
+
<header
|
|
5
|
+
data-testid="generated-answer__header"
|
|
6
|
+
class={generatedAnswerHeaderClass}
|
|
7
|
+
>
|
|
8
|
+
<div class="generated-answer__header-title slds-grid slds-grid_vertical-align-center">
|
|
9
|
+
<lightning-icon
|
|
10
|
+
icon-name="utility:sparkles"
|
|
11
|
+
size="x-small"
|
|
12
|
+
alternative-text={labels.generatedAnswerForYou}
|
|
13
|
+
class="slds-current-color slds-var-m-right_x-small"
|
|
14
|
+
></lightning-icon>
|
|
15
|
+
<span
|
|
16
|
+
data-testid="generated-answer__header-title"
|
|
17
|
+
class="slds-text-title_bold slds-p-vertical_x-small"
|
|
18
|
+
>{labels.generatedAnswerForYou}</span
|
|
19
|
+
>
|
|
43
20
|
</div>
|
|
44
|
-
|
|
21
|
+
<template lwc:if={withToggle}>
|
|
22
|
+
<c-quantic-generated-answer-toggle
|
|
23
|
+
is-generated-answer-visible={isVisible}
|
|
24
|
+
></c-quantic-generated-answer-toggle>
|
|
25
|
+
</template>
|
|
26
|
+
</header>
|
|
45
27
|
<template lwc:if={isVisible}>
|
|
46
|
-
<
|
|
28
|
+
<section
|
|
29
|
+
data-testid="generated-answer__body"
|
|
30
|
+
class="generated-answer__content slds-p-top_medium slds-p-horizontal_large"
|
|
31
|
+
>
|
|
47
32
|
<div
|
|
48
33
|
data-testid="generated-answer__answer"
|
|
49
34
|
class={generatedAnswerClass}
|
|
@@ -56,63 +41,100 @@
|
|
|
56
41
|
>
|
|
57
42
|
</c-quantic-generated-answer-content>
|
|
58
43
|
</div>
|
|
59
|
-
<div class=
|
|
60
|
-
<
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<div class={generatedAnswerFooterRowClass}>
|
|
74
|
-
<template lwc:if={shouldShowCollapseGeneratingMessage}>
|
|
44
|
+
<div class="slds-grid slds-grid_vertical">
|
|
45
|
+
<template lwc:if={shouldDisplayCitations}>
|
|
46
|
+
<div class="slds-size_1-of-1 slds-var-m-top_x-small">
|
|
47
|
+
<c-quantic-source-citations
|
|
48
|
+
engine-id={engineId}
|
|
49
|
+
data-testid="generated-answer__citations"
|
|
50
|
+
citations={citations}
|
|
51
|
+
citation-hover-handler={handleCitationHover}
|
|
52
|
+
disable-citation-anchoring={disableCitationAnchoring}
|
|
53
|
+
></c-quantic-source-citations>
|
|
54
|
+
</div>
|
|
55
|
+
</template>
|
|
56
|
+
<template lwc:if={shouldDisplayActions}>
|
|
57
|
+
<div class="slds-size_1-of-1 slds-grid slds-grid_vertical-align-center slds-var-m-top_x-small slds-grid_align-start">
|
|
75
58
|
<div
|
|
76
|
-
data-testid="generated-
|
|
77
|
-
class="
|
|
59
|
+
data-testid="generated-answer__actions"
|
|
60
|
+
class="slds-grid slds-grid_vertical-align-center"
|
|
78
61
|
>
|
|
79
|
-
|
|
62
|
+
<c-quantic-feedback
|
|
63
|
+
state={feedbackState}
|
|
64
|
+
onquantic__like={handleLike}
|
|
65
|
+
onquantic__dislike={handleDislike}
|
|
66
|
+
like-icon-name="utility:like"
|
|
67
|
+
like-label={labels.thisAnswerWasHelpful}
|
|
68
|
+
dislike-icon-name="utility:dislike"
|
|
69
|
+
dislike-label={labels.thisAnswerWasNotHelpful}
|
|
70
|
+
size="x-small"
|
|
71
|
+
question=""
|
|
72
|
+
hide-explain-why-button
|
|
73
|
+
hide-labels
|
|
74
|
+
></c-quantic-feedback>
|
|
75
|
+
<c-quantic-generated-answer-copy-to-clipboard
|
|
76
|
+
data-testid="generated-answer__copy-to-clipboard"
|
|
77
|
+
answer={answer}
|
|
78
|
+
size="x-small"
|
|
79
|
+
class="slds-var-m-horizontal_xx-small"
|
|
80
|
+
></c-quantic-generated-answer-copy-to-clipboard>
|
|
80
81
|
</div>
|
|
81
|
-
</
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
84
|
+
<template lwc:if={isAnswerCollapsed}>
|
|
85
|
+
<div class="slds-grid slds-size_1-of-1 slds-wrap slds-grid_vertical-align-center slds-var-m-top_x-small">
|
|
86
|
+
<div class="slds-grid slds-wrap slds-grid_vertical-align-center">
|
|
87
|
+
<template lwc:if={isStreaming}>
|
|
88
|
+
<div
|
|
89
|
+
data-testid="generated-answer__collapse-generating-message"
|
|
90
|
+
class="generated-answer__collapse-generating-message slds-var-m-right_small"
|
|
91
|
+
>
|
|
92
|
+
{labels.generatingAnswer}...
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
95
|
+
<template lwc:else>
|
|
96
|
+
<lightning-button
|
|
97
|
+
data-testid="generated-answer__answer-toggle"
|
|
98
|
+
icon-name={toggleCollapseAnswerIcon}
|
|
99
|
+
variant="base"
|
|
100
|
+
label={toggleCollapseAnswerLabel}
|
|
101
|
+
title={toggleCollapseAnswerLabel}
|
|
102
|
+
onclick={handleToggleCollapseAnswer}
|
|
103
|
+
icon-position="right"
|
|
104
|
+
class="generated-answer__answer-toggle slds-shrink-none slds-var-m-right_large"
|
|
105
|
+
></lightning-button>
|
|
106
|
+
</template>
|
|
100
107
|
</div>
|
|
101
|
-
</
|
|
102
|
-
</
|
|
108
|
+
</div>
|
|
109
|
+
</template>
|
|
103
110
|
</div>
|
|
104
|
-
</
|
|
111
|
+
</section>
|
|
112
|
+
<template lwc:if={shouldShowDisclaimer}>
|
|
113
|
+
<footer
|
|
114
|
+
data-testid="generated-answer__footer"
|
|
115
|
+
class="generated-answer__disclaimer slds-grid slds-grid_vertical-align-center slds-grid_align-end slds-text-color_weak slds-text-body_small slds-p-horizontal_large slds-p-bottom_medium"
|
|
116
|
+
>
|
|
117
|
+
<div data-testid="generated-answer__disclaimer">
|
|
118
|
+
<slot name="disclaimer"> {labels.rgaDisclaimer} </slot>
|
|
119
|
+
</div>
|
|
120
|
+
</footer>
|
|
121
|
+
</template>
|
|
105
122
|
</template>
|
|
106
123
|
</div>
|
|
107
124
|
</template>
|
|
108
125
|
<template lwc:if={cannotAnswer}>
|
|
109
126
|
<template lwc:if={isManualAnswerGeneration}>
|
|
110
127
|
<div data-testid="generated-answer__no-answer-card" class="slds-box">
|
|
111
|
-
<div class="generated-answer__card-header slds-grid">
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
<div class="generated-answer__card-header slds-grid slds-grid_vertical-align-center slds-border_bottom slds-p-around_x-small">
|
|
129
|
+
<div class="generated-answer__header-title slds-grid slds-grid_vertical-align-center">
|
|
130
|
+
<lightning-icon
|
|
131
|
+
icon-name="utility:sparkles"
|
|
132
|
+
size="x-small"
|
|
133
|
+
alternative-text={labels.generatedAnswerForYou}
|
|
134
|
+
class="slds-current-color slds-var-m-right_x-small"
|
|
135
|
+
></lightning-icon>
|
|
136
|
+
<span class="slds-text-title_bold">{labels.generatedAnswerForYou}</span>
|
|
137
|
+
</div>
|
|
116
138
|
</div>
|
|
117
139
|
<div
|
|
118
140
|
data-testid="generated-answer__no-answer-message"
|
|
@@ -127,11 +149,16 @@
|
|
|
127
149
|
<template lwc:else>
|
|
128
150
|
<template lwc:if={hasCustomNoAnswerMessage}>
|
|
129
151
|
<div data-testid="generated-answer__no-answer-card" class="slds-box">
|
|
130
|
-
<div class="generated-answer__card-header slds-grid">
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
152
|
+
<div class="generated-answer__card-header slds-grid slds-grid_vertical-align-center slds-border_bottom slds-p-around_x-small">
|
|
153
|
+
<div class="generated-answer__header-title slds-grid slds-grid_vertical-align-center">
|
|
154
|
+
<lightning-icon
|
|
155
|
+
icon-name="utility:sparkles"
|
|
156
|
+
size="x-small"
|
|
157
|
+
alternative-text={labels.generatedAnswerForYou}
|
|
158
|
+
class="slds-current-color slds-var-m-right_x-small"
|
|
159
|
+
></lightning-icon>
|
|
160
|
+
<span class="slds-text-title_bold">{labels.generatedAnswerForYou}</span>
|
|
161
|
+
</div>
|
|
135
162
|
</div>
|
|
136
163
|
<div class="generated-answer__content slds-var-m-top_medium">
|
|
137
164
|
<div class={generatedAnswerClass}>
|
|
@@ -2,25 +2,34 @@
|
|
|
2
2
|
<template lwc:if={shouldDisplayGeneratedAnswer}>
|
|
3
3
|
<div
|
|
4
4
|
data-testid="generated-answer__card"
|
|
5
|
-
class="slds-box"
|
|
5
|
+
class="slds-box slds-p-around_none"
|
|
6
6
|
>
|
|
7
7
|
<div
|
|
8
|
-
class="slds-
|
|
8
|
+
class="generated-answer__card-header slds-grid slds-grid_vertical-align-center slds-border_bottom slds-p-vertical_small slds-p-horizontal_large"
|
|
9
9
|
>
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
<div class="generated-answer__header-title slds-grid slds-grid_vertical-align-center">
|
|
11
|
+
<lightning-icon
|
|
12
|
+
icon-name="utility:sparkles"
|
|
13
|
+
size="x-small"
|
|
14
|
+
alternative-text={labels.generatedAnswerForYou}
|
|
15
|
+
class="slds-current-color slds-var-m-right_x-small"
|
|
16
|
+
></lightning-icon>
|
|
17
|
+
<span class="slds-text-title_bold slds-p-vertical_x-small"
|
|
18
|
+
>{labels.generatedAnswerForYou}</span
|
|
19
|
+
>
|
|
20
|
+
</div>
|
|
14
21
|
</div>
|
|
15
|
-
<div>
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
<div class="slds-p-vertical_medium slds-p-horizontal_large">
|
|
23
|
+
<div>{labels.couldNotGenerateAnAnswer}</div>
|
|
24
|
+
<div class="slds-var-m-top_medium">
|
|
25
|
+
<lightning-button
|
|
26
|
+
data-testid="generated-answer__retry-button"
|
|
27
|
+
variant="brand-outline"
|
|
28
|
+
label={labels.tryAgain}
|
|
29
|
+
title={labels.tryAgain}
|
|
30
|
+
onclick={handleRetry}
|
|
31
|
+
></lightning-button>
|
|
32
|
+
</div>
|
|
24
33
|
</div>
|
|
25
34
|
</div>
|
|
26
35
|
</template>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/* eslint-disable jest/no-focused-tests */
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
import {createElement} from 'lwc';
|
|
4
|
+
import QuanticGeneratedAnswerCopyToClipboard from '../quanticGeneratedAnswerCopyToClipboard';
|
|
5
|
+
import {copyToClipboard} from 'c/quanticUtils';
|
|
6
|
+
|
|
7
|
+
const defaultCopyLabel = 'Copy';
|
|
8
|
+
const defaultCopiedLabel = 'Copied';
|
|
9
|
+
const defaultSize = 'xx-small';
|
|
10
|
+
|
|
11
|
+
jest.mock(
|
|
12
|
+
'@salesforce/label/c.quantic_Copy',
|
|
13
|
+
() => ({default: defaultCopyLabel}),
|
|
14
|
+
{
|
|
15
|
+
virtual: true,
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
jest.mock(
|
|
20
|
+
'@salesforce/label/c.quantic_Copied',
|
|
21
|
+
() => ({default: defaultCopiedLabel}),
|
|
22
|
+
{
|
|
23
|
+
virtual: true,
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
jest.mock('c/quanticUtils', () => ({
|
|
28
|
+
copyToClipboard: jest.fn(() => Promise.resolve()),
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
const selectors = {
|
|
32
|
+
copyButton: 'c-quantic-stateful-button',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const defaultOptions = {
|
|
36
|
+
answer: 'Example generated answer',
|
|
37
|
+
size: defaultSize,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function createTestComponent(options = defaultOptions) {
|
|
41
|
+
const element = createElement(
|
|
42
|
+
'c-quantic-generated-answer-copy-to-clipboard',
|
|
43
|
+
{
|
|
44
|
+
is: QuanticGeneratedAnswerCopyToClipboard,
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
for (const [key, value] of Object.entries(options)) {
|
|
49
|
+
element[key] = value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
document.body.appendChild(element);
|
|
53
|
+
return element;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Helper function to wait until the microtask queue is empty.
|
|
57
|
+
function flushPromises() {
|
|
58
|
+
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
59
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
describe('c-quantic-generated-answer-copy-to-clipboard', () => {
|
|
63
|
+
function cleanup() {
|
|
64
|
+
while (document.body.firstChild) {
|
|
65
|
+
document.body.removeChild(document.body.firstChild);
|
|
66
|
+
}
|
|
67
|
+
jest.clearAllMocks();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
afterEach(() => {
|
|
71
|
+
cleanup();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should render the copy button with default size', async () => {
|
|
75
|
+
const element = createTestComponent();
|
|
76
|
+
await flushPromises();
|
|
77
|
+
|
|
78
|
+
const copyButton = element.shadowRoot.querySelector(selectors.copyButton);
|
|
79
|
+
|
|
80
|
+
expect(copyButton).not.toBeNull();
|
|
81
|
+
expect(copyButton.iconName).toBe('utility:copy');
|
|
82
|
+
expect(copyButton.iconSize).toBe(defaultSize);
|
|
83
|
+
expect(copyButton.tooltip).toBe(defaultCopyLabel);
|
|
84
|
+
expect(copyButton.selected).toBe(false);
|
|
85
|
+
expect(copyButton.withoutBorders).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should apply a custom valid size', async () => {
|
|
89
|
+
const customSize = 'large';
|
|
90
|
+
const element = createTestComponent({...defaultOptions, size: customSize});
|
|
91
|
+
await flushPromises();
|
|
92
|
+
|
|
93
|
+
const copyButton = element.shadowRoot.querySelector(selectors.copyButton);
|
|
94
|
+
|
|
95
|
+
expect(copyButton).not.toBeNull();
|
|
96
|
+
expect(copyButton.iconSize).toBe(customSize);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should ignore an invalid size and keep the default value', async () => {
|
|
100
|
+
const element = createTestComponent({
|
|
101
|
+
...defaultOptions,
|
|
102
|
+
size: 'oliphant',
|
|
103
|
+
});
|
|
104
|
+
await flushPromises();
|
|
105
|
+
|
|
106
|
+
const copyButton = element.shadowRoot.querySelector(selectors.copyButton);
|
|
107
|
+
|
|
108
|
+
expect(copyButton).not.toBeNull();
|
|
109
|
+
expect(copyButton.iconSize).toBe(defaultSize);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should copy the answer and dispatch the #quantic__generatedanswercopy event', async () => {
|
|
113
|
+
const element = createTestComponent();
|
|
114
|
+
const handler = jest.fn();
|
|
115
|
+
element.addEventListener('quantic__generatedanswercopy', handler);
|
|
116
|
+
await flushPromises();
|
|
117
|
+
|
|
118
|
+
const copyButton = element.shadowRoot.querySelector(selectors.copyButton);
|
|
119
|
+
copyButton.dispatchEvent(new CustomEvent('quantic__select'));
|
|
120
|
+
await flushPromises();
|
|
121
|
+
|
|
122
|
+
expect(copyToClipboard).toHaveBeenCalledWith(defaultOptions.answer);
|
|
123
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
124
|
+
});
|
|
125
|
+
});
|