Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,10 @@ export const DisableCitationAnchoring: Story = {
'disable-citation-anchoring': true,
},
};

export const WithoutAnswerConfigurationId: Story = {
name: 'Without answer configuration ID',
args: {
'answer-configuration-id': undefined,
},
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,86 @@
import {expect, test} from './fixture';

test.describe('atomic-generated-answer citation', () => {
const testScenarios = [
{
name: 'with answer-configuration-id',
args: {
answerConfigurationId: 'fc581be0-6e61-4039-ab26-a3f2f52f308f',
},
},
{
name: 'without answer-configuration-id',
args: {
answerConfigurationId: undefined,
},
},
];

test.describe('atomic-generated-answer - Happy Path', () => {
testScenarios.forEach(({name, args}) => {
test.describe(name, () => {
test.beforeEach(async ({generatedAnswer}) => {

Check failure on line 21 in packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts

View workflow job for this annotation

GitHub Actions / Run Playwright tests for Atomic (8, 12)

[chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation

2) [chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Test timeout of 30000ms exceeded while running "beforeEach" hook. 19 | testScenarios.forEach(({name, args}) => { 20 | test.describe(name, () => { > 21 | test.beforeEach(async ({generatedAnswer}) => { | ^ 22 | await generatedAnswer.load({story: 'default', args}); 23 | await generatedAnswer.hydrated.first().waitFor({state: 'visible'}); 24 | }); at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:21:12

Check failure on line 21 in packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts

View workflow job for this annotation

GitHub Actions / Run Playwright tests for Atomic (8, 12)

[chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation

2) [chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation Test timeout of 30000ms exceeded while running "beforeEach" hook. 19 | testScenarios.forEach(({name, args}) => { 20 | test.describe(name, () => { > 21 | test.beforeEach(async ({generatedAnswer}) => { | ^ 22 | await generatedAnswer.load({story: 'default', args}); 23 | await generatedAnswer.hydrated.first().waitFor({state: 'visible'}); 24 | }); at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:21:12
await generatedAnswer.load({story: 'default', args});
await generatedAnswer.hydrated.first().waitFor({state: 'visible'});

Check failure on line 23 in packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts

View workflow job for this annotation

GitHub Actions / Run Playwright tests for Atomic (8, 12)

[chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation

2) [chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.waitFor: Test timeout of 30000ms exceeded. Call log: - waiting for locator('atomic-generated-answer[class*="hydrated"]').first() to be visible - locator resolved to hidden <atomic-generated-answer tabs-included="" tabs-excluded="" data-atomic-loaded="false" data-atomic-rendered="false" class="atomic-hidden hydrated">…</atomic-generated-answer> 60 × locator resolved to hidden <atomic-generated-answer tabs-included="" tabs-excluded="" class="hydrated" data-atomic-loaded="true" data-atomic-rendered="true">…</atomic-generated-answer> 21 | test.beforeEach(async ({generatedAnswer}) => { 22 | await generatedAnswer.load({story: 'default', args}); > 23 | await generatedAnswer.hydrated.first().waitFor({state: 'visible'}); | ^ 24 | }); 25 | 26 | test('should complete full user journey: view answer → like → feedback → citations → navigation', async ({ at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:23:48

Check failure on line 23 in packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts

View workflow job for this annotation

GitHub Actions / Run Playwright tests for Atomic (8, 12)

[chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation

2) [chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › without answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation Error: locator.waitFor: Test timeout of 30000ms exceeded. Call log: - waiting for locator('atomic-generated-answer[class*="hydrated"]').first() to be visible - locator resolved to hidden <atomic-generated-answer tabs-included="" tabs-excluded="" data-atomic-loaded="false" data-atomic-rendered="false" class="atomic-hidden hydrated">…</atomic-generated-answer> 59 × locator resolved to hidden <atomic-generated-answer tabs-included="" tabs-excluded="" class="hydrated" data-atomic-loaded="true" data-atomic-rendered="true">…</atomic-generated-answer> 21 | test.beforeEach(async ({generatedAnswer}) => { 22 | await generatedAnswer.load({story: 'default', args}); > 23 | await generatedAnswer.hydrated.first().waitFor({state: 'visible'}); | ^ 24 | }); 25 | 26 | test('should complete full user journey: view answer → like → feedback → citations → navigation', async ({ at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:23:48
});

test('should complete full user journey: view answer → like → feedback → citations → navigation', async ({
generatedAnswer,
page,
}) => {
await test.step('Wait for and verify generated answer text is displayed', async () => {
await generatedAnswer.waitForGeneratedText();
await expect(generatedAnswer.generatedText).toBeVisible();
const textContent = await generatedAnswer.generatedText.textContent();
expect(textContent).toBeTruthy();
expect(textContent!.length).toBeGreaterThan(0);
});

await test.step('Like the answer', async () => {
expect(await generatedAnswer.isLikeButtonActive()).toBe(false);
await generatedAnswer.clickLikeButton();
expect(await generatedAnswer.isLikeButtonActive()).toBe(true);
});

await test.step('Open and fill feedback modal', async () => {
await generatedAnswer.waitForFeedbackModal();
expect(await generatedAnswer.isFeedbackModalOpen()).toBe(true);

await generatedAnswer.fillFeedbackForm({
correctTopic: 'yes',
hallucinationFree: 'yes',
documented: 'yes',
readable: 'yes',
details: 'This is a great answer!',
});
});

await test.step('Submit feedback', async () => {
await generatedAnswer.submitFeedback();
await generatedAnswer.page.waitForTimeout(500);
expect(await generatedAnswer.isFeedbackModalOpen()).toBe(false);
});

await test.step('Verify citations are displayed', async () => {
await generatedAnswer.waitForCitations();
const citationCount = await generatedAnswer.getCitationCount();
expect(citationCount).toBeGreaterThan(0);
});

await test.step('Click on citation and verify navigation', async () => {
const firstCitationHref = await generatedAnswer.getCitationHref(0);
expect(firstCitationHref).toBeTruthy();

const navigationPromise = page.waitForURL(/.*/, {timeout: 5000});
await generatedAnswer.citation.first().click();

await expect(navigationPromise).resolves.not.toThrow();
});
});
});
});
});

test.describe('atomic-generated-answer - Citations', () => {
test.describe('with citation anchoring enabled', () => {
test.beforeEach(async ({generatedAnswer}) => {
await generatedAnswer.load({story: 'default'});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,34 @@
return this.page.locator('atomic-citation [part="citation"]');
}

get generatedText() {
return this.page.locator('atomic-generated-answer [part="generated-text"]');
}

get likeButton() {
return this.page
.locator('atomic-generated-answer [part="feedback-button"].like')
.first();
}

get dislikeButton() {
return this.page
.locator('atomic-generated-answer [part="feedback-button"].dislike')
.first();
}

get feedbackModal() {
return this.page.locator('atomic-generated-answer-feedback-modal');
}

get feedbackSubmitButton() {
return this.feedbackModal.getByRole('button', {name: /submit/i});
}

get feedbackCancelButton() {
return this.feedbackModal.getByRole('button', {name: /cancel/i});
}

async waitForCitations() {
await this.citation.first().waitFor();
}
Expand All @@ -41,4 +69,92 @@
);
});
}

async waitForGeneratedText() {
await this.generatedText.first().waitFor({state: 'visible'});
}

async clickLikeButton() {
await this.likeButton.click();
}

async clickDislikeButton() {
await this.dislikeButton.click();
}

async isLikeButtonActive(): Promise<boolean> {
const ariaPressed = await this.likeButton.getAttribute('aria-pressed');
return ariaPressed === 'true';
}

async isDislikeButtonActive(): Promise<boolean> {
const ariaPressed = await this.dislikeButton.getAttribute('aria-pressed');
return ariaPressed === 'true';
}

async waitForFeedbackModal() {
await this.feedbackModal.waitFor({state: 'visible'});

Check failure on line 96 in packages/atomic/src/components/search/atomic-generated-answer/e2e/page-object.ts

View workflow job for this annotation

GitHub Actions / Run Playwright tests for Atomic (8, 12)

[chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › with answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation

1) [chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › with answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation › Open and fill feedback modal Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.waitFor: Test timeout of 30000ms exceeded. Call log: - waiting for locator('atomic-generated-answer-feedback-modal') to be visible 55 × locator resolved to hidden <atomic-generated-answer-feedback-modal is-open="" helpful="" class="hydrated" data-atomic-loaded="true" data-atomic-rendered="true"></atomic-generated-answer-feedback-modal> at components/search/atomic-generated-answer/e2e/page-object.ts:96 94 | 95 | async waitForFeedbackModal() { > 96 | await this.feedbackModal.waitFor({state: 'visible'}); | ^ 97 | } 98 | 99 | async isFeedbackModalOpen(): Promise<boolean> { at GeneratedAnswerPageObject.waitForFeedbackModal (/__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/page-object.ts:96:30) at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:45:33 at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:44:20

Check failure on line 96 in packages/atomic/src/components/search/atomic-generated-answer/e2e/page-object.ts

View workflow job for this annotation

GitHub Actions / Run Playwright tests for Atomic (8, 12)

[chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › with answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation

1) [chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › with answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation › Open and fill feedback modal Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.waitFor: Test timeout of 30000ms exceeded. Call log: - waiting for locator('atomic-generated-answer-feedback-modal') to be visible 56 × locator resolved to hidden <atomic-generated-answer-feedback-modal is-open="" helpful="" class="hydrated" data-atomic-loaded="true" data-atomic-rendered="true"></atomic-generated-answer-feedback-modal> at components/search/atomic-generated-answer/e2e/page-object.ts:96 94 | 95 | async waitForFeedbackModal() { > 96 | await this.feedbackModal.waitFor({state: 'visible'}); | ^ 97 | } 98 | 99 | async isFeedbackModalOpen(): Promise<boolean> { at GeneratedAnswerPageObject.waitForFeedbackModal (/__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/page-object.ts:96:30) at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:45:33 at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:44:20

Check failure on line 96 in packages/atomic/src/components/search/atomic-generated-answer/e2e/page-object.ts

View workflow job for this annotation

GitHub Actions / Run Playwright tests for Atomic (8, 12)

[chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › with answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation

1) [chromium] › src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:26:7 › atomic-generated-answer - Happy Path › with answer-configuration-id › should complete full user journey: view answer → like → feedback → citations → navigation › Open and fill feedback modal Error: locator.waitFor: Test timeout of 30000ms exceeded. Call log: - waiting for locator('atomic-generated-answer-feedback-modal') to be visible 56 × locator resolved to hidden <atomic-generated-answer-feedback-modal is-open="" helpful="" class="hydrated" data-atomic-loaded="true" data-atomic-rendered="true"></atomic-generated-answer-feedback-modal> at components/search/atomic-generated-answer/e2e/page-object.ts:96 94 | 95 | async waitForFeedbackModal() { > 96 | await this.feedbackModal.waitFor({state: 'visible'}); | ^ 97 | } 98 | 99 | async isFeedbackModalOpen(): Promise<boolean> { at GeneratedAnswerPageObject.waitForFeedbackModal (/__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/page-object.ts:96:30) at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:45:33 at /__w/ui-kit/ui-kit/packages/atomic/src/components/search/atomic-generated-answer/e2e/atomic-generated-answer.e2e.ts:44:20
}

async isFeedbackModalOpen(): Promise<boolean> {
return await this.feedbackModal.isVisible();
}

async submitFeedback() {
await this.feedbackSubmitButton.click();
}

async cancelFeedback() {
await this.feedbackCancelButton.click();
}

async fillFeedbackForm(options?: {
correctTopic?: 'yes' | 'unknown' | 'no';
hallucinationFree?: 'yes' | 'unknown' | 'no';
documented?: 'yes' | 'unknown' | 'no';
readable?: 'yes' | 'unknown' | 'no';
documentUrl?: string;
details?: string;
}) {
const {
correctTopic = 'yes',
hallucinationFree = 'yes',
documented = 'yes',
readable = 'yes',
documentUrl,
details,
} = options || {};

// Click radio buttons for each evaluation question
await this.feedbackModal
.locator(`.answer-evaluation.correctTopic`)
.getByRole('radio', {name: correctTopic})
.click();

await this.feedbackModal
.locator(`.answer-evaluation.hallucinationFree`)
.getByRole('radio', {name: hallucinationFree})
.click();

await this.feedbackModal
.locator(`.answer-evaluation.documented`)
.getByRole('radio', {name: documented})
.click();

await this.feedbackModal
.locator(`.answer-evaluation.readable`)
.getByRole('radio', {name: readable})
.click();

// Fill optional fields if provided
if (documentUrl) {
await this.feedbackModal
.locator('input[placeholder="https://URL"]')
.fill(documentUrl);
}

if (details) {
await this.feedbackModal.locator('textarea').fill(details);
}
}
}
Loading