@coveo/quantic 3.43.0 → 3.43.2
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/quanticGeneratedAnswer/__tests__/quanticGeneratedAnswer.test.js +145 -60
- package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/fixture-agent.ts +3 -3
- package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/fixture.ts +12 -9
- package/force-app/main/default/lwc/quanticGeneratedAnswer/e2e/pageObject.ts +5 -8
- package/force-app/main/default/lwc/quanticGeneratedAnswer/quanticGeneratedAnswer.js +12 -108
- package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/generatedAnswer.html +8 -47
- package/force-app/main/default/lwc/quanticGeneratedAnswerContent/__tests__/quanticGeneratedAnswerContent.test.js +27 -0
- package/force-app/main/default/lwc/quanticGeneratedAnswerContent/quanticGeneratedAnswerContent.js +8 -1
- package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.css +16 -4
- package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.html +12 -16
- package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.css +29 -11
- package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.html +11 -15
- package/force-app/main/default/staticresources/coveoheadless/case-assist/headless.js +2 -2
- package/force-app/main/default/staticresources/coveoheadless/headless.js +2 -2
- package/force-app/main/default/staticresources/coveoheadless/insight/headless.js +2 -2
- package/force-app/main/default/staticresources/coveoheadless/recommendation/headless.js +2 -2
- package/package.json +3 -2
package/force-app/main/default/lwc/quanticGeneratedAnswer/__tests__/quanticGeneratedAnswer.test.js
CHANGED
|
@@ -89,9 +89,8 @@ const selectors = {
|
|
|
89
89
|
generatedAnswer: '[data-testid="generated-answer__answer"]',
|
|
90
90
|
generatedAnswerBadge: '[data-testid="generated-answer__header-title"]',
|
|
91
91
|
generatedAnswerRetryButton: '[data-testid="generated-answer__retry-button"]',
|
|
92
|
-
generatedAnswerActions: '[data-testid="generated-answer__actions"]',
|
|
93
92
|
generatedAnswerToggleButton: 'c-quantic-generated-answer-toggle',
|
|
94
|
-
|
|
93
|
+
generatedAnswerBodyComponent: 'c-quantic-generated-answer-body',
|
|
95
94
|
generatingMessageWhenAnswerCollapsed:
|
|
96
95
|
'[data-testid="generated-answer__collapse-generating-message"]',
|
|
97
96
|
generatedAnswerCollapseToggle:
|
|
@@ -101,10 +100,8 @@ const selectors = {
|
|
|
101
100
|
'[data-testid="generated-answer__no-answer-card"]',
|
|
102
101
|
generatedAnswerNoAnswerMessage:
|
|
103
102
|
'[data-testid="generated-answer__no-answer-message"]',
|
|
104
|
-
generatedAnswerCitations: 'c-quantic-source-citations',
|
|
105
103
|
generatedAnswerThread: 'c-quantic-generated-answer-thread',
|
|
106
104
|
generatedAnswerFollowUpInput: 'c-quantic-generated-answer-follow-up-input',
|
|
107
|
-
generatedAnswerFeedback: 'c-quantic-feedback',
|
|
108
105
|
loadingSpinner: 'lightning-spinner',
|
|
109
106
|
};
|
|
110
107
|
|
|
@@ -128,6 +125,7 @@ const functionsMocks = {
|
|
|
128
125
|
like: functionsMocks.like,
|
|
129
126
|
dislike: functionsMocks.dislike,
|
|
130
127
|
closeFeedbackModal: functionsMocks.closeFeedbackModal,
|
|
128
|
+
logCitationHover: functionsMocks.logCitationHover,
|
|
131
129
|
})),
|
|
132
130
|
buildSearchStatus: jest.fn(() => ({
|
|
133
131
|
state: searchStatusState,
|
|
@@ -148,6 +146,7 @@ const functionsMocks = {
|
|
|
148
146
|
like: jest.fn(),
|
|
149
147
|
dislike: jest.fn(),
|
|
150
148
|
closeFeedbackModal: jest.fn(),
|
|
149
|
+
logCitationHover: jest.fn(),
|
|
151
150
|
};
|
|
152
151
|
|
|
153
152
|
/**
|
|
@@ -504,33 +503,25 @@ describe('c-quantic-generated-answer', () => {
|
|
|
504
503
|
});
|
|
505
504
|
});
|
|
506
505
|
|
|
507
|
-
it('should
|
|
506
|
+
it('should forward the streaming answer to the generated answer body', async () => {
|
|
508
507
|
const element = createTestComponent();
|
|
509
508
|
await flushPromises();
|
|
510
509
|
|
|
511
|
-
const
|
|
512
|
-
selectors.
|
|
513
|
-
);
|
|
514
|
-
|
|
515
|
-
expect(generatedAnswerContent).not.toBeNull();
|
|
516
|
-
expect(generatedAnswerContent.isStreaming).toBe(true);
|
|
517
|
-
expect(generatedAnswerContent.answer).toBe(exampleAnswer);
|
|
518
|
-
expect(generatedAnswerContent.answerContentFormat).toBe(
|
|
519
|
-
exampleAnswerContentFormat
|
|
510
|
+
const generatedAnswerBody = element.shadowRoot.querySelector(
|
|
511
|
+
selectors.generatedAnswerBodyComponent
|
|
520
512
|
);
|
|
521
|
-
expect(generatedAnswerContent.engineId).toBe(exampleEngineId);
|
|
522
|
-
expect(generatedAnswerContent.answerId).toBe(exampleAnswerId);
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
it('should not display the generated answer actions', async () => {
|
|
526
|
-
const element = createTestComponent();
|
|
527
|
-
await flushPromises();
|
|
528
513
|
|
|
529
|
-
|
|
530
|
-
|
|
514
|
+
expect(generatedAnswerBody).not.toBeNull();
|
|
515
|
+
expect(generatedAnswerBody.engineId).toBe(exampleEngineId);
|
|
516
|
+
expect(generatedAnswerBody.disableCitationAnchoring).toBe(false);
|
|
517
|
+
expect(generatedAnswerBody.generatedAnswer).toEqual(
|
|
518
|
+
expect.objectContaining({
|
|
519
|
+
answer: exampleAnswer,
|
|
520
|
+
answerContentFormat: exampleAnswerContentFormat,
|
|
521
|
+
answerId: exampleAnswerId,
|
|
522
|
+
isStreaming: true,
|
|
523
|
+
})
|
|
531
524
|
);
|
|
532
|
-
|
|
533
|
-
expect(generatedAnswerActions).toBeNull();
|
|
534
525
|
});
|
|
535
526
|
|
|
536
527
|
it('should not display the generated answer disclaimer in the footer', async () => {
|
|
@@ -769,38 +760,48 @@ describe('c-quantic-generated-answer', () => {
|
|
|
769
760
|
});
|
|
770
761
|
});
|
|
771
762
|
|
|
772
|
-
it('should
|
|
763
|
+
it('should forward the ready answer with citations to the generated answer body', async () => {
|
|
773
764
|
const element = createTestComponent();
|
|
774
765
|
await flushPromises();
|
|
775
766
|
|
|
776
|
-
const
|
|
777
|
-
selectors.
|
|
767
|
+
const generatedAnswerBody = element.shadowRoot.querySelector(
|
|
768
|
+
selectors.generatedAnswerBodyComponent
|
|
778
769
|
);
|
|
779
770
|
|
|
780
|
-
expect(
|
|
781
|
-
expect(
|
|
782
|
-
expect(
|
|
783
|
-
expect(
|
|
784
|
-
|
|
771
|
+
expect(generatedAnswerBody).not.toBeNull();
|
|
772
|
+
expect(generatedAnswerBody.engineId).toBe(exampleEngineId);
|
|
773
|
+
expect(generatedAnswerBody.disableCitationAnchoring).toBe(false);
|
|
774
|
+
expect(generatedAnswerBody.generatedAnswer).toEqual(
|
|
775
|
+
expect.objectContaining({
|
|
776
|
+
answer: exampleAnswer,
|
|
777
|
+
answerContentFormat: exampleAnswerContentFormat,
|
|
778
|
+
citations: exampleCitations,
|
|
779
|
+
isStreaming: false,
|
|
780
|
+
})
|
|
785
781
|
);
|
|
786
782
|
});
|
|
787
783
|
|
|
788
|
-
it('should
|
|
789
|
-
const element = createTestComponent(
|
|
784
|
+
it('should collapse the answer when the body reports a content height exceeding the maximum collapsed height', async () => {
|
|
785
|
+
const element = createTestComponent({
|
|
786
|
+
...defaultOptions,
|
|
787
|
+
collapsible: true,
|
|
788
|
+
});
|
|
790
789
|
await flushPromises();
|
|
791
790
|
|
|
792
791
|
const generatedAnswerBody = element.shadowRoot.querySelector(
|
|
793
|
-
selectors.
|
|
792
|
+
selectors.generatedAnswerBodyComponent
|
|
794
793
|
);
|
|
795
|
-
|
|
796
|
-
|
|
794
|
+
generatedAnswerBody.dispatchEvent(
|
|
795
|
+
new CustomEvent('quantic__answercontentupdated', {
|
|
796
|
+
detail: {height: defaultAnswerHeight + 100},
|
|
797
|
+
})
|
|
797
798
|
);
|
|
799
|
+
await flushPromises();
|
|
798
800
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
expect(generatedAnswerActions.closest('section')).toBe(
|
|
802
|
-
generatedAnswerBody
|
|
801
|
+
const generatedAnswerCollapseToggle = element.shadowRoot.querySelector(
|
|
802
|
+
selectors.generatedAnswerCollapseToggle
|
|
803
803
|
);
|
|
804
|
+
expect(generatedAnswerCollapseToggle).not.toBeNull();
|
|
804
805
|
});
|
|
805
806
|
|
|
806
807
|
it('should display the generated answer disclaimer', async () => {
|
|
@@ -833,17 +834,6 @@ describe('c-quantic-generated-answer', () => {
|
|
|
833
834
|
expect(generatedAnswerBadge).not.toBeNull();
|
|
834
835
|
});
|
|
835
836
|
|
|
836
|
-
it('should pass the disableCitationAnchoring property to the source citations component', async () => {
|
|
837
|
-
const element = createTestComponent();
|
|
838
|
-
await flushPromises();
|
|
839
|
-
|
|
840
|
-
const generatedAnswerCitations = element.shadowRoot.querySelector(
|
|
841
|
-
selectors.generatedAnswerCitations
|
|
842
|
-
);
|
|
843
|
-
expect(generatedAnswerCitations).not.toBeNull();
|
|
844
|
-
expect(generatedAnswerCitations.disableCitationAnchoring).toBe(false);
|
|
845
|
-
});
|
|
846
|
-
|
|
847
837
|
describe('when follow-ups are enabled', () => {
|
|
848
838
|
const exampleAgentId = 'example agent id';
|
|
849
839
|
const exampleFollowUpAnswers = [
|
|
@@ -1385,6 +1375,103 @@ describe('c-quantic-generated-answer', () => {
|
|
|
1385
1375
|
});
|
|
1386
1376
|
});
|
|
1387
1377
|
|
|
1378
|
+
describe('the citation hover event', () => {
|
|
1379
|
+
const exampleAnswer = 'answer generated successfully';
|
|
1380
|
+
const exampleAgentId = 'example agent id';
|
|
1381
|
+
const exampleCitationId = 'citation-id-1';
|
|
1382
|
+
const exampleCitationHoverTimeMs = 1500;
|
|
1383
|
+
|
|
1384
|
+
describe('when follow-ups are not enabled', () => {
|
|
1385
|
+
beforeEach(() => {
|
|
1386
|
+
generatedAnswerState = {
|
|
1387
|
+
...initialGeneratedAnswerState,
|
|
1388
|
+
isStreaming: false,
|
|
1389
|
+
answer: exampleAnswer,
|
|
1390
|
+
answerContentFormat: 'text/markdown',
|
|
1391
|
+
answerId: exampleAnswerId,
|
|
1392
|
+
citations: exampleCitations,
|
|
1393
|
+
};
|
|
1394
|
+
mockSuccessfulHeadlessInitialization();
|
|
1395
|
+
prepareHeadlessState();
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
afterAll(() => {
|
|
1399
|
+
generatedAnswerState = initialGeneratedAnswerState;
|
|
1400
|
+
});
|
|
1401
|
+
|
|
1402
|
+
it('should call logCitationHover on the controller with the correct parameters', async () => {
|
|
1403
|
+
const element = createTestComponent();
|
|
1404
|
+
await flushPromises();
|
|
1405
|
+
|
|
1406
|
+
const generatedAnswerBody = element.shadowRoot.querySelector(
|
|
1407
|
+
selectors.generatedAnswerBodyComponent
|
|
1408
|
+
);
|
|
1409
|
+
generatedAnswerBody.dispatchEvent(
|
|
1410
|
+
new CustomEvent('quantic__citationhover', {
|
|
1411
|
+
detail: {
|
|
1412
|
+
citationId: exampleCitationId,
|
|
1413
|
+
citationHoverTimeMs: exampleCitationHoverTimeMs,
|
|
1414
|
+
answerId: exampleAnswerId,
|
|
1415
|
+
},
|
|
1416
|
+
})
|
|
1417
|
+
);
|
|
1418
|
+
await flushPromises();
|
|
1419
|
+
|
|
1420
|
+
expect(functionsMocks.logCitationHover).toHaveBeenCalledTimes(1);
|
|
1421
|
+
expect(functionsMocks.logCitationHover).toHaveBeenCalledWith(
|
|
1422
|
+
exampleCitationId,
|
|
1423
|
+
exampleCitationHoverTimeMs,
|
|
1424
|
+
exampleAnswerId
|
|
1425
|
+
);
|
|
1426
|
+
});
|
|
1427
|
+
});
|
|
1428
|
+
|
|
1429
|
+
describe('when follow-ups are enabled', () => {
|
|
1430
|
+
beforeEach(() => {
|
|
1431
|
+
generatedAnswerState = {
|
|
1432
|
+
...initialGeneratedAnswerState,
|
|
1433
|
+
answer: exampleAnswer,
|
|
1434
|
+
followUpAnswers: {isEnabled: true, followUpAnswers: []},
|
|
1435
|
+
};
|
|
1436
|
+
mockSuccessfulHeadlessInitialization();
|
|
1437
|
+
prepareHeadlessState();
|
|
1438
|
+
});
|
|
1439
|
+
|
|
1440
|
+
afterAll(() => {
|
|
1441
|
+
generatedAnswerState = initialGeneratedAnswerState;
|
|
1442
|
+
});
|
|
1443
|
+
|
|
1444
|
+
it('should call logCitationHover on the controller with the correct parameters', async () => {
|
|
1445
|
+
const element = createTestComponent({
|
|
1446
|
+
...defaultOptions,
|
|
1447
|
+
agentId: exampleAgentId,
|
|
1448
|
+
});
|
|
1449
|
+
await flushPromises();
|
|
1450
|
+
|
|
1451
|
+
const thread = element.shadowRoot.querySelector(
|
|
1452
|
+
selectors.generatedAnswerThread
|
|
1453
|
+
);
|
|
1454
|
+
thread.dispatchEvent(
|
|
1455
|
+
new CustomEvent('quantic__citationhover', {
|
|
1456
|
+
detail: {
|
|
1457
|
+
citationId: exampleCitationId,
|
|
1458
|
+
citationHoverTimeMs: exampleCitationHoverTimeMs,
|
|
1459
|
+
answerId: exampleAnswerId,
|
|
1460
|
+
},
|
|
1461
|
+
})
|
|
1462
|
+
);
|
|
1463
|
+
await flushPromises();
|
|
1464
|
+
|
|
1465
|
+
expect(functionsMocks.logCitationHover).toHaveBeenCalledTimes(1);
|
|
1466
|
+
expect(functionsMocks.logCitationHover).toHaveBeenCalledWith(
|
|
1467
|
+
exampleCitationId,
|
|
1468
|
+
exampleCitationHoverTimeMs,
|
|
1469
|
+
exampleAnswerId
|
|
1470
|
+
);
|
|
1471
|
+
});
|
|
1472
|
+
});
|
|
1473
|
+
});
|
|
1474
|
+
|
|
1388
1475
|
describe('the generated answer feedback', () => {
|
|
1389
1476
|
const exampleAnswer = 'answer generated successfully';
|
|
1390
1477
|
const exampleAgentId = 'example agent id';
|
|
@@ -1392,19 +1479,17 @@ describe('c-quantic-generated-answer', () => {
|
|
|
1392
1479
|
describe.each([
|
|
1393
1480
|
{
|
|
1394
1481
|
action: 'like',
|
|
1395
|
-
feedbackEvent: 'quantic__like',
|
|
1396
1482
|
threadEvent: 'quantic__generatedanswerlike',
|
|
1397
1483
|
controllerMethod: 'like',
|
|
1398
1484
|
},
|
|
1399
1485
|
{
|
|
1400
1486
|
action: 'dislike',
|
|
1401
|
-
feedbackEvent: 'quantic__dislike',
|
|
1402
1487
|
threadEvent: 'quantic__generatedanswerdislike',
|
|
1403
1488
|
controllerMethod: 'dislike',
|
|
1404
1489
|
},
|
|
1405
1490
|
])(
|
|
1406
1491
|
'when the user clicks the $action button',
|
|
1407
|
-
({
|
|
1492
|
+
({threadEvent, controllerMethod}) => {
|
|
1408
1493
|
describe('when follow-ups are not enabled', () => {
|
|
1409
1494
|
beforeEach(() => {
|
|
1410
1495
|
generatedAnswerState = {
|
|
@@ -1427,11 +1512,11 @@ describe('c-quantic-generated-answer', () => {
|
|
|
1427
1512
|
const element = createTestComponent();
|
|
1428
1513
|
await flushPromises();
|
|
1429
1514
|
|
|
1430
|
-
const
|
|
1431
|
-
selectors.
|
|
1515
|
+
const generatedAnswerBody = element.shadowRoot.querySelector(
|
|
1516
|
+
selectors.generatedAnswerBodyComponent
|
|
1432
1517
|
);
|
|
1433
|
-
|
|
1434
|
-
new CustomEvent(
|
|
1518
|
+
generatedAnswerBody.dispatchEvent(
|
|
1519
|
+
new CustomEvent(threadEvent, {
|
|
1435
1520
|
detail: {answerId: exampleAnswerId},
|
|
1436
1521
|
})
|
|
1437
1522
|
);
|
|
@@ -46,7 +46,6 @@ export const testAgent =
|
|
|
46
46
|
{
|
|
47
47
|
headAnswerRequestRegex: agentAnswerRequestRegex,
|
|
48
48
|
agentFollowUpRequestRegex,
|
|
49
|
-
isAgent: true,
|
|
50
49
|
}
|
|
51
50
|
);
|
|
52
51
|
|
|
@@ -56,7 +55,8 @@ export const testAgent =
|
|
|
56
55
|
await generatedAnswerObject.mockAgentFollowUpResponse(
|
|
57
56
|
data.followUpStreams
|
|
58
57
|
);
|
|
59
|
-
|
|
58
|
+
|
|
59
|
+
await search.mockSearchWithBaseResponse();
|
|
60
60
|
await page.goto(pageUrl);
|
|
61
61
|
await configuration.configure(options);
|
|
62
62
|
await search.waitForSearchResponse();
|
|
@@ -67,7 +67,7 @@ export const testAgent =
|
|
|
67
67
|
generatedAnswerObject.waitForHeadAnswerRequest();
|
|
68
68
|
|
|
69
69
|
await search.fillSearchInput(exampleQuery);
|
|
70
|
-
|
|
70
|
+
search.performSearch();
|
|
71
71
|
await search.waitForSearchResponse();
|
|
72
72
|
|
|
73
73
|
await use(generatedAnswerObject);
|
|
@@ -89,6 +89,7 @@ export const testSearch =
|
|
|
89
89
|
data.streamId
|
|
90
90
|
);
|
|
91
91
|
|
|
92
|
+
await search.mockSearchWithBaseResponse();
|
|
92
93
|
await page.goto(pageUrl);
|
|
93
94
|
if (withFacets) {
|
|
94
95
|
await generatedAnswerObject.clickAddFacetsButton();
|
|
@@ -104,10 +105,12 @@ export const testSearch =
|
|
|
104
105
|
generatedAnswerObject.waitForHeadAnswerRequest();
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
await search.fillSearchInput(exampleQuery);
|
|
108
108
|
await search.mockSearchWithGenerativeQuestionAnsweringId(data.streamId);
|
|
109
|
-
await search.
|
|
110
|
-
await
|
|
109
|
+
await search.fillSearchInput(exampleQuery);
|
|
110
|
+
await Promise.all([
|
|
111
|
+
search.waitForSearchResponse(),
|
|
112
|
+
search.performSearch(),
|
|
113
|
+
]);
|
|
111
114
|
|
|
112
115
|
await use(generatedAnswerObject);
|
|
113
116
|
},
|
|
@@ -162,17 +165,14 @@ export const testInsight =
|
|
|
162
165
|
data.streamId
|
|
163
166
|
);
|
|
164
167
|
|
|
168
|
+
await search.mockSearchWithBaseResponse();
|
|
165
169
|
await page.goto(pageUrl);
|
|
166
170
|
if (withFacets) {
|
|
167
171
|
await generatedAnswerObject.clickAddFacetsButton();
|
|
168
172
|
}
|
|
169
173
|
configuration.configure({...options, useCase: useCaseEnum.insight});
|
|
170
|
-
|
|
171
174
|
await insightSetup.waitForInsightInterfaceInitialization();
|
|
172
|
-
await search.performSearch();
|
|
173
|
-
await search.waitForSearchResponse();
|
|
174
175
|
|
|
175
|
-
await search.mockSearchWithGenerativeQuestionAnsweringId(data.streamId);
|
|
176
176
|
generatedAnswerObject.streamEndAnalyticRequestPromise =
|
|
177
177
|
generatedAnswerObject.waitForStreamEndAnalytics();
|
|
178
178
|
if (options.answerConfigurationId) {
|
|
@@ -180,9 +180,12 @@ export const testInsight =
|
|
|
180
180
|
generatedAnswerObject.waitForHeadAnswerRequest();
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
await search.mockSearchWithGenerativeQuestionAnsweringId(data.streamId);
|
|
183
184
|
await search.fillSearchInput(exampleQuery);
|
|
184
|
-
await
|
|
185
|
-
|
|
185
|
+
await Promise.all([
|
|
186
|
+
search.waitForSearchResponse(),
|
|
187
|
+
search.performSearch(),
|
|
188
|
+
]);
|
|
186
189
|
|
|
187
190
|
await use(generatedAnswerObject);
|
|
188
191
|
},
|
|
@@ -29,7 +29,6 @@ export interface GeneratedAnswerObjectConfig {
|
|
|
29
29
|
answerApiEnabled?: boolean;
|
|
30
30
|
headAnswerRequestRegex?: RegExp;
|
|
31
31
|
agentFollowUpRequestRegex?: RegExp;
|
|
32
|
-
isAgent?: boolean;
|
|
33
32
|
withFacets?: boolean;
|
|
34
33
|
}
|
|
35
34
|
|
|
@@ -39,7 +38,6 @@ export class GeneratedAnswerObject {
|
|
|
39
38
|
private headAnswerRequestRegex?: RegExp;
|
|
40
39
|
private agentFollowUpRequestRegex?: RegExp;
|
|
41
40
|
private withFacets: boolean;
|
|
42
|
-
private isAgent: boolean;
|
|
43
41
|
|
|
44
42
|
constructor(
|
|
45
43
|
private page: Page,
|
|
@@ -55,15 +53,14 @@ export class GeneratedAnswerObject {
|
|
|
55
53
|
this.headAnswerRequestRegex = config.headAnswerRequestRegex;
|
|
56
54
|
this.agentFollowUpRequestRegex = config.agentFollowUpRequestRegex;
|
|
57
55
|
this.withFacets = config.withFacets ?? false;
|
|
58
|
-
this.isAgent = config.isAgent ?? false;
|
|
59
56
|
}
|
|
60
57
|
|
|
61
58
|
get likeButton(): Locator {
|
|
62
|
-
return this.page.getByRole('button', {name:
|
|
59
|
+
return this.page.getByRole('button', {name: 'Like', exact: true});
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
get dislikeButton(): Locator {
|
|
66
|
-
return this.page.getByRole('button', {name:
|
|
63
|
+
return this.page.getByRole('button', {name: 'Dislike', exact: true});
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
get copyToClipboardButton(): Locator {
|
|
@@ -132,7 +129,7 @@ export class GeneratedAnswerObject {
|
|
|
132
129
|
|
|
133
130
|
get citationLink(): Locator {
|
|
134
131
|
return this.page
|
|
135
|
-
.getByTestId(
|
|
132
|
+
.getByTestId('generated-answer-body__citations')
|
|
136
133
|
.locator('.citation__link');
|
|
137
134
|
}
|
|
138
135
|
|
|
@@ -157,8 +154,8 @@ export class GeneratedAnswerObject {
|
|
|
157
154
|
}
|
|
158
155
|
|
|
159
156
|
async hoverOverCitation(index: number): Promise<void> {
|
|
160
|
-
// waiting
|
|
161
|
-
await this.page.waitForTimeout(
|
|
157
|
+
// waiting 1000ms to allow the component to render completely, cause any re-rendering abort the hover action.
|
|
158
|
+
await this.page.waitForTimeout(1000);
|
|
162
159
|
await this.citationLink.nth(index).hover();
|
|
163
160
|
await this.page.waitForTimeout(minimumCitationTooltipDisplayDurationMs);
|
|
164
161
|
await this.page.mouse.move(0, 0);
|
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
import answerGenerated from '@salesforce/label/c.quantic_AnswerGenerated';
|
|
2
2
|
import couldNotGenerateAnAnswer from '@salesforce/label/c.quantic_CouldNotGenerateAnAnswer';
|
|
3
|
-
import feedback from '@salesforce/label/c.quantic_Feedback';
|
|
4
3
|
import feedbackHelpUsImprove from '@salesforce/label/c.quantic_FeedbackHelpUsImprove';
|
|
5
4
|
import generatedAnswerForYou from '@salesforce/label/c.quantic_GeneratedAnswerForYou';
|
|
6
5
|
import generatedAnswerIsHidden from '@salesforce/label/c.quantic_GeneratedAnswerIsHidden';
|
|
7
6
|
import showLess from '@salesforce/label/c.quantic_GeneratedAnswerShowLess';
|
|
8
7
|
import showMore from '@salesforce/label/c.quantic_GeneratedAnswerShowMore';
|
|
9
8
|
import generatingAnswer from '@salesforce/label/c.quantic_GeneratingAnswer';
|
|
10
|
-
import harmful from '@salesforce/label/c.quantic_Harmful';
|
|
11
|
-
import inaccurate from '@salesforce/label/c.quantic_Inaccurate';
|
|
12
|
-
import irrelevant from '@salesforce/label/c.quantic_Irrelevant';
|
|
13
9
|
import loading from '@salesforce/label/c.quantic_Loading';
|
|
14
|
-
import other from '@salesforce/label/c.quantic_Other';
|
|
15
|
-
import outOfDate from '@salesforce/label/c.quantic_OutOfDate';
|
|
16
10
|
import rgaDisclaimer from '@salesforce/label/c.quantic_RGADisclaimer';
|
|
17
|
-
import thisAnswerWasHelpful from '@salesforce/label/c.quantic_ThisAnswerWasHelpful';
|
|
18
|
-
import thisAnswerWasNotHelpful from '@salesforce/label/c.quantic_ThisAnswerWasNotHelpful';
|
|
19
11
|
import tryAgain from '@salesforce/label/c.quantic_TryAgain';
|
|
20
|
-
import whyGeneratedAnswerWasNotHelpful from '@salesforce/label/c.quantic_WhyGeneratedAnswerWasNotHelpful';
|
|
21
12
|
import noGeneratedAnswer from '@salesforce/label/c.quantic_NoGeneratedAnswer';
|
|
22
13
|
import FeedbackModalQna from 'c/quanticFeedbackModalQna';
|
|
23
14
|
import {
|
|
@@ -25,7 +16,7 @@ import {
|
|
|
25
16
|
initializeWithHeadless,
|
|
26
17
|
getHeadlessBundle,
|
|
27
18
|
} from 'c/quanticHeadlessLoader';
|
|
28
|
-
import {AriaLiveRegion, I18nUtils
|
|
19
|
+
import {AriaLiveRegion, I18nUtils} from 'c/quanticUtils';
|
|
29
20
|
import {LightningElement, api} from 'lwc';
|
|
30
21
|
// @ts-ignore
|
|
31
22
|
import errorTemplate from './templates/errorTemplate.html';
|
|
@@ -42,15 +33,9 @@ import conversationTemplate from './templates/conversation.html';
|
|
|
42
33
|
/** @typedef {import("coveo").GeneratedAnswer} GeneratedAnswer */
|
|
43
34
|
/** @typedef {import("coveo").GeneratedAnswerWithFollowUps} GeneratedAnswerWithFollowUps */
|
|
44
35
|
/** @typedef {import("coveo").GeneratedAnswerState} GeneratedAnswerState */
|
|
45
|
-
/** @typedef {import("coveo").GeneratedAnswerCitation} GeneratedAnswerCitation */
|
|
46
|
-
/** @typedef { 'neutral' | 'liked' | 'disliked'} FeedbackState */
|
|
47
36
|
/** @typedef {import("coveo").SearchStatus} SearchStatus */
|
|
48
37
|
/** @typedef {import("coveo").SearchStatusState} SearchStatusState */
|
|
49
38
|
|
|
50
|
-
const FEEDBACK_LIKED_STATE = 'liked';
|
|
51
|
-
const FEEDBACK_DISLIKED_STATE = 'disliked';
|
|
52
|
-
const FEEDBACK_NEUTRAL_STATE = 'neutral';
|
|
53
|
-
|
|
54
39
|
const DEFAULT_COLLAPSED_HEIGHT = 250;
|
|
55
40
|
const MAX_VALID_COLLAPSED_HEIGHT = 500;
|
|
56
41
|
const MIN_VALID_COLLAPSED_HEIGHT = 150;
|
|
@@ -143,18 +128,9 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
143
128
|
|
|
144
129
|
labels = {
|
|
145
130
|
generatedAnswerForYou,
|
|
146
|
-
thisAnswerWasNotHelpful,
|
|
147
|
-
thisAnswerWasHelpful,
|
|
148
131
|
tryAgain,
|
|
149
132
|
couldNotGenerateAnAnswer,
|
|
150
|
-
other,
|
|
151
|
-
harmful,
|
|
152
|
-
irrelevant,
|
|
153
|
-
inaccurate,
|
|
154
|
-
outOfDate,
|
|
155
133
|
feedbackHelpUsImprove,
|
|
156
|
-
feedback,
|
|
157
|
-
whyGeneratedAnswerWasNotHelpful,
|
|
158
134
|
generatingAnswer,
|
|
159
135
|
generatedAnswerIsHidden,
|
|
160
136
|
answerGenerated,
|
|
@@ -169,8 +145,6 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
169
145
|
generatedAnswer;
|
|
170
146
|
/** @type {GeneratedAnswerState} */
|
|
171
147
|
state;
|
|
172
|
-
/** @type {FeedbackState} */
|
|
173
|
-
feedbackState = 'neutral';
|
|
174
148
|
/** @type {SearchStatus} */
|
|
175
149
|
searchStatus;
|
|
176
150
|
/** @type {SearchStatusState} */
|
|
@@ -185,6 +159,8 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
185
159
|
_exceedsMaximumHeight = false;
|
|
186
160
|
/** @type {number} */
|
|
187
161
|
_maxCollapsedHeight = DEFAULT_COLLAPSED_HEIGHT;
|
|
162
|
+
/** @type {number} */
|
|
163
|
+
generatedAnswerHeight = 0;
|
|
188
164
|
|
|
189
165
|
connectedCallback() {
|
|
190
166
|
registerComponentForInit(this, this.engineId);
|
|
@@ -266,7 +242,6 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
266
242
|
|
|
267
243
|
updateState() {
|
|
268
244
|
this.state = this.generatedAnswer.state;
|
|
269
|
-
this.updateFeedbackState();
|
|
270
245
|
this.ariaLiveMessage.dispatchMessage(this.getGeneratedAnswerStatus());
|
|
271
246
|
|
|
272
247
|
if (this.isCollapsibleEnabled) {
|
|
@@ -278,8 +253,8 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
278
253
|
// If we are still streaming add a little extra height to the answer element to account for the next answer chunk.
|
|
279
254
|
// This helps a lot with the jankyness of the answer fading out when the chunk is close but not yet over the max height.
|
|
280
255
|
const answerElementHeight = this.isStreaming
|
|
281
|
-
? this.
|
|
282
|
-
: this.
|
|
256
|
+
? this.generatedAnswerHeight + 50
|
|
257
|
+
: this.generatedAnswerHeight;
|
|
283
258
|
|
|
284
259
|
return answerElementHeight > this.maxCollapsedHeight;
|
|
285
260
|
}
|
|
@@ -309,25 +284,6 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
309
284
|
this.searchStatusState = this.searchStatus.state;
|
|
310
285
|
}
|
|
311
286
|
|
|
312
|
-
updateFeedbackState() {
|
|
313
|
-
if (this.state?.liked) {
|
|
314
|
-
this.feedbackState = FEEDBACK_LIKED_STATE;
|
|
315
|
-
} else if (this.state?.disliked) {
|
|
316
|
-
this.feedbackState = FEEDBACK_DISLIKED_STATE;
|
|
317
|
-
} else {
|
|
318
|
-
this.feedbackState = FEEDBACK_NEUTRAL_STATE;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* handles hovering over a citation.
|
|
324
|
-
* @param {string} id
|
|
325
|
-
* @param {number} citationHoverTimeMs
|
|
326
|
-
*/
|
|
327
|
-
logCitationHover = (id, citationHoverTimeMs) => {
|
|
328
|
-
this.generatedAnswer.logCitationHover(id, citationHoverTimeMs);
|
|
329
|
-
};
|
|
330
|
-
|
|
331
287
|
/**
|
|
332
288
|
* handles liking the generated answer.
|
|
333
289
|
* @param {CustomEvent} event
|
|
@@ -420,6 +376,7 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
420
376
|
|
|
421
377
|
handleAnswerContentUpdated = (event) => {
|
|
422
378
|
event.stopPropagation();
|
|
379
|
+
this.generatedAnswerHeight = event.detail?.height;
|
|
423
380
|
if (this.isCollapsibleEnabled) {
|
|
424
381
|
this._exceedsMaximumHeight = this.isMaximumHeightExceeded();
|
|
425
382
|
}
|
|
@@ -453,15 +410,6 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
453
410
|
return this.template.querySelector('.generated-answer__answer');
|
|
454
411
|
}
|
|
455
412
|
|
|
456
|
-
/**
|
|
457
|
-
* Returns the generated answer height.
|
|
458
|
-
* @returns {number}
|
|
459
|
-
*/
|
|
460
|
-
get generatedAnswerElementHeight() {
|
|
461
|
-
// @ts-ignore
|
|
462
|
-
return getAbsoluteHeight(this.generatedAnswerElement?.firstChild);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
413
|
/**
|
|
466
414
|
* Sets the value of the CSS variable "--maxHeight" to the value of the maxCollapsedHeight property.
|
|
467
415
|
*/
|
|
@@ -476,31 +424,14 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
476
424
|
return this?.state?.answer;
|
|
477
425
|
}
|
|
478
426
|
|
|
479
|
-
get answerId() {
|
|
480
|
-
return this?.state?.answerId;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
427
|
get citations() {
|
|
484
428
|
return this?.state?.citations;
|
|
485
429
|
}
|
|
486
430
|
|
|
487
|
-
get answerContentFormat() {
|
|
488
|
-
return this?.state?.answerContentFormat;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
get shouldDisplayCitations() {
|
|
492
|
-
const hasCitations = !!this.citations?.length;
|
|
493
|
-
return hasCitations && !this.isAnswerCollapsed;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
431
|
get isStreaming() {
|
|
497
432
|
return this?.state?.isStreaming;
|
|
498
433
|
}
|
|
499
434
|
|
|
500
|
-
get shouldDisplayActions() {
|
|
501
|
-
return this.isVisible && !this.isStreaming && !this.isAnswerCollapsed;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
435
|
get isVisible() {
|
|
505
436
|
return this.state.isVisible;
|
|
506
437
|
}
|
|
@@ -527,15 +458,18 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
527
458
|
);
|
|
528
459
|
}
|
|
529
460
|
|
|
530
|
-
get
|
|
531
|
-
|
|
461
|
+
get initialAnswer() {
|
|
462
|
+
return {
|
|
532
463
|
...this.state,
|
|
533
464
|
question: this.engine?.state.query?.q ?? '',
|
|
534
465
|
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
get allGeneratedAnswers() {
|
|
535
469
|
const followUpAnswers =
|
|
536
470
|
this.generateAnswerWithFollowUps?.state.followUpAnswers
|
|
537
471
|
?.followUpAnswers ?? [];
|
|
538
|
-
return [initialAnswer, ...followUpAnswers];
|
|
472
|
+
return [this.initialAnswer, ...followUpAnswers];
|
|
539
473
|
}
|
|
540
474
|
|
|
541
475
|
get isCollapsibleEnabled() {
|
|
@@ -566,36 +500,6 @@ export default class QuanticGeneratedAnswer extends LightningElement {
|
|
|
566
500
|
return !this?.searchStatusState?.hasError && this.state?.error?.isRetryable;
|
|
567
501
|
}
|
|
568
502
|
|
|
569
|
-
/**
|
|
570
|
-
* Returns the options displayed in the Quantic Feedback Modal.
|
|
571
|
-
*/
|
|
572
|
-
get options() {
|
|
573
|
-
return [
|
|
574
|
-
{
|
|
575
|
-
label: this.labels.irrelevant,
|
|
576
|
-
value: 'irrelevant',
|
|
577
|
-
},
|
|
578
|
-
{
|
|
579
|
-
label: this.labels.inaccurate,
|
|
580
|
-
value: 'notAccurate',
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
label: this.labels.outOfDate,
|
|
584
|
-
value: 'outOfDate',
|
|
585
|
-
},
|
|
586
|
-
{
|
|
587
|
-
label: this.labels.harmful,
|
|
588
|
-
value: 'harmful',
|
|
589
|
-
},
|
|
590
|
-
{
|
|
591
|
-
label: this.labels.other,
|
|
592
|
-
value: 'other',
|
|
593
|
-
withDetails: true,
|
|
594
|
-
detailsRequired: true,
|
|
595
|
-
},
|
|
596
|
-
];
|
|
597
|
-
}
|
|
598
|
-
|
|
599
503
|
get generatedAnswerHeaderClass() {
|
|
600
504
|
const headerBaseClass =
|
|
601
505
|
'generated-answer__card-header slds-grid slds-grid_vertical-align-center slds-grid_align-spread slds-p-horizontal_large slds-p-vertical_small';
|