Skip to content

Commit

Permalink
feat(e2e): fix E2E broken tests (#1003)
Browse files Browse the repository at this point in the history
  • Loading branch information
fredalai authored Dec 18, 2024
1 parent 6bc6fbd commit 4caee5a
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 232 deletions.
283 changes: 112 additions & 171 deletions wren-ui/e2e/commonTests/home.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
import { Page, expect } from '@playwright/test';
import * as helper from '../helper';
import {
AskingTask,
AskingTaskStatus,
ThreadResponse,
} from '@/apollo/client/graphql/__types__';
import * as modelingHelper from './modeling';

export const checkAskingProcess = async (page: Page, question: string) => {
// check process state
await expect(page.getByText('Searching data')).toBeVisible({
timeout: 10000,
});
await expect(page.getByTestId('prompt__result')).toBeVisible();
await expect(page.getByRole('button', { name: 'Stop' })).toBeVisible();
await expect(page.getByPlaceholder('Ask to explore your data')).toHaveValue(
question,
);
await expect(page.getByRole('button', { name: 'Ask' })).toBeDisabled();
};

export const waitingForAskingTask = async (page: Page, baseURL) => {
await page.waitForResponse(
async (response) => {
const responseBody = await response.json();
const responseData: AskingTask = responseBody?.data?.askingTask;
return (
response.url() === `${baseURL}/api/graphql` &&
response.status() === 200 &&
responseBody &&
[AskingTaskStatus.FAILED, AskingTaskStatus.FINISHED].includes(
responseData?.status,
)
);
},
{ timeout: 100000 },
export const waitingForAskingTask = async (page: Page) => {
await helper.waitForGraphQLResponse({ page }, 'askingTask', (data) =>
[AskingTaskStatus.FAILED, AskingTaskStatus.FINISHED].includes(data?.status),
);
};

Expand Down Expand Up @@ -63,33 +49,79 @@ export const getFirstCandidatesResultSummary = async (page: Page) => {
return firstResultSummary;
};

export const checkSkeletonLoading = async (page: Page, isShow: boolean) => {
await expect(page.locator('.ant-skeleton-content')).toBeVisible({
visible: isShow,
export const checkThreadResponseSkeletonLoading = async (page: Page) => {
await expect(page.locator('.ant-skeleton-content').last()).toBeVisible({
timeout: 60000,
});
await expect(page.locator('.ant-skeleton-content').last()).toBeHidden({
timeout: 60000,
});
};

export const waitingForThreadResponse = async (page: Page, baseURL: string) => {
await page.waitForResponse(
async (response) => {
const responseBody = await response.json();
const responseData: ThreadResponse = responseBody?.data?.threadResponse;
return (
response.url() === `${baseURL}/api/graphql` &&
response.status() === 200 &&
responseBody &&
[AskingTaskStatus.FAILED, AskingTaskStatus.FINISHED].includes(
responseData?.breakdownDetail?.status,
)
);
},
{ timeout: 100000 },
);
const checkThreadResponseBreakdownContent = async (page: Page) => {
// switch to the View SQL tab
await page
.locator('div')
.filter({ hasText: /^View SQL$/ })
.last()
.click();

// View SQL tab content
await expect(
page.getByLabel('View SQL').locator('.ant-skeleton-content').last(),
).toBeVisible();

await expect(
page.getByLabel('View SQL').locator('.ant-skeleton-content').last(),
).toBeHidden({ timeout: 60000 });

// check show preview data table as default open
await expect(
page.getByLabel('View SQL').locator('.ant-table').last(),
).toBeVisible();
await expect(page.getByText('Showing up to 500 rows').last()).toBeVisible();

// check up-circle icon with Collapse button
await expect(
page.getByLabel('View SQL').getByLabel('up-circle').locator('svg').last(),
).toBeVisible();
await expect(
page
.getByLabel('View SQL')
.getByRole('button', { name: 'Collapse' })
.last(),
).toBeVisible();

// click View Full SQL button
await page
.getByLabel('View SQL')
.getByRole('button', { name: 'View Full SQL' })
.last()
.click();
await expect(
page.getByLabel('View SQL').locator('.ace_editor'),
).toBeVisible();

// check collapse and copy button
await expect(
page.getByLabel('View SQL').getByLabel('up-circle').locator('svg').last(),
).toBeVisible();
await expect(
page
.getByLabel('View SQL')
.getByRole('button', { name: 'Collapse' })
.last(),
).toBeVisible();
await expect(
page.getByLabel('View SQL').getByLabel('copy').locator('svg'),
).toBeVisible();
await expect(
page.getByLabel('View SQL').getByRole('button', { name: 'Copy' }),
).toBeVisible();
};

export const askSuggestionQuestionTest = async ({
page,
baseURL,
suggestedQuestion,
}) => {
await page.goto('/home');
Expand All @@ -99,142 +131,75 @@ export const askSuggestionQuestionTest = async ({

// check asking process state and wait for asking task to finish
await checkAskingProcess(page, suggestedQuestion);
await waitingForAskingTask(page, baseURL);
await checkCandidatesResult(page);

const firstResult = await getFirstCandidatesResultSummary(page);
await page.getByRole('cell', { name: firstResult }).first().click();

await checkSkeletonLoading(page, true);
await waitingForThreadResponse(page, baseURL);
await checkSkeletonLoading(page, false);
await waitingForAskingTask(page);
await checkThreadResponseSkeletonLoading(page);

// check question block
await expect(page.getByLabel('question-circle').locator('svg')).toBeVisible();
await expect(page.getByText('Question:')).toBeVisible();
await expect(page.getByText(suggestedQuestion)).toBeVisible();

// check thread summary
await expect(page.getByRole('heading', { name: firstResult })).toBeVisible();

// check show preview data table as default open
await expect(page.locator('.ant-table')).toBeVisible();
await expect(page.getByText('Showing up to 500 rows')).toBeVisible();

// check up-circle icon with Collapse button
await expect(page.getByLabel('up-circle').locator('svg')).toBeVisible();
await expect(page.getByRole('button', { name: 'Collapse' })).toBeVisible();

// click View Full SQL button
await page.getByRole('button', { name: 'View Full SQL' }).click();
await expect(page.locator('.ace_editor')).toBeVisible();
await expect(page.getByLabel('message').locator('svg')).toBeVisible();
await expect(
page.getByRole('heading', { name: suggestedQuestion }),
).toBeVisible();

// check collapse and copy button
await expect(page.getByLabel('up-circle').locator('svg')).toBeVisible();
await expect(page.getByRole('button', { name: 'Collapse' })).toBeVisible();
await expect(page.getByLabel('copy').locator('svg')).toBeVisible();
await expect(page.getByRole('button', { name: 'Copy' })).toBeVisible();
// check answer result basic UI elements
await expect(
page.locator('#rc-tabs-0-tab-answer').getByText('Answer'),
).toBeVisible();
await expect(
page.locator('#rc-tabs-0-tab-view-sql').getByText('View SQL'),
).toBeVisible();

// check save icon button
await expect(page.getByLabel('save').locator('svg')).toBeVisible();
await expect(
page.getByRole('button', { name: 'Save as View' }),
).toBeVisible();

// Answer tab content
await expect(page.getByLabel('Answer').locator('div').first()).toBeVisible();

await checkThreadResponseBreakdownContent(page);
};

export const followUpQuestionTest = async ({ page, baseURL, question }) => {
export const followUpQuestionTest = async ({ page, question }) => {
await page.goto('/home');
await expect(page).toHaveURL('/home', { timeout: 60000 });

// click existing thread
await page
.getByRole('tree')
.locator('div')
.filter({ hasText: /\W/ })
.nth(2)
.click();
await page.locator('.adm-treeTitle__title').first().click();
await expect(page).toHaveURL(/.*\/home\/\d+/, { timeout: 60000 });

// ask follow up question
await page.getByPlaceholder('Ask to explore your data').fill(question);
await page.getByRole('button', { name: 'Ask' }).click();

// check asking process state and wait for asking task to finish
await checkAskingProcess(page, question);
await waitingForAskingTask(page, baseURL);
await checkCandidatesResult(page);

// click the View SQL
await page
.getByRole('cell', { name: 'Result 1 function View SQL' })
.getByRole('button')
.click();
await page.getByLabel('Close', { exact: true }).click();

const firstResult = await getFirstCandidatesResultSummary(page);

// select the first suggested question if there are two same results
await page.getByRole('cell', { name: firstResult }).first().click();

await checkSkeletonLoading(page, true);
await waitingForThreadResponse(page, baseURL);
await checkSkeletonLoading(page, false);
await waitingForAskingTask(page);
await checkThreadResponseSkeletonLoading(page);

// check question block
await expect(
page.getByLabel('question-circle').locator('svg').last(),
).toBeVisible();
await expect(page.getByText('Question:').last()).toBeVisible();
await expect(page.getByText(question)).toBeVisible();

// check thread summary
await expect(page.getByRole('heading', { name: firstResult })).toBeVisible();
await expect(page.getByLabel('message').locator('svg').last()).toBeVisible();
await expect(page.getByRole('heading', { name: question })).toBeVisible();

await expect(page.locator('.ant-table').last()).toBeVisible();
await expect(page.getByText('Showing up to 500 rows').last()).toBeVisible();

// check up-circle icon with Collapse button
await expect(
page.getByLabel('up-circle').locator('svg').last(),
).toBeVisible();
await expect(
page.getByRole('button', { name: 'Collapse' }).last(),
).toBeVisible();

// click View Full SQL button
await page.getByRole('button', { name: 'View Full SQL' }).last().click();

await expect(page.locator('.ace_editor')).toBeVisible();

// check collapse and copy button
await expect(
page.getByLabel('up-circle').locator('svg').last(),
).toBeVisible();
await expect(
page.getByRole('button', { name: 'Collapse' }).last(),
).toBeVisible();
await expect(page.getByLabel('copy').locator('svg')).toBeVisible();
await expect(page.getByRole('button', { name: 'Copy' })).toBeVisible();

// check save icon button
await expect(page.getByLabel('save').locator('svg').last()).toBeVisible();
await expect(
page.getByRole('button', { name: 'Save as View' }).last(),
).toBeVisible();
await checkThreadResponseBreakdownContent(page);
};

export const saveAsView = async (
{ page, baseURL }: { page: Page; baseURL: string },
{ question, viewName }: { question: string; viewName: string },
) => {
await askSuggestionQuestionTest({
page,
baseURL,
suggestedQuestion: question,
});
await page.goto('/home');
await expect(page).toHaveURL('/home', { timeout: 60000 });

await expect(
page.getByRole('button', { name: 'Save as View' }),
).toBeVisible();
await page.getByPlaceholder('Ask to explore your data').fill(question);
await page.getByRole('button', { name: 'Ask' }).click();

// check asking process state and wait for asking task to finish
await checkAskingProcess(page, question);
await waitingForAskingTask(page);
await checkThreadResponseSkeletonLoading(page);

// click save as view button
await page.getByRole('button', { name: 'Save as View' }).click();

// check save as view modal
Expand Down Expand Up @@ -273,37 +238,13 @@ export const saveAsView = async (
await expect(page).toHaveURL('/home', { timeout: 60000 });

// ask the saved view question
await page.getByText(question).click();
await page.getByPlaceholder('Ask to explore your data').fill(question);
await page.getByRole('button', { name: 'Ask' }).click();

// check asking process state and wait for asking task to finish
await checkAskingProcess(page, question);
await waitingForAskingTask(page, baseURL);
await checkCandidatesResult(page);

// check offer view result
await expect(page.getByText('Result 1')).toBeVisible();
await expect(page.getByLabel('file-add').locator('svg')).toBeVisible();
await expect(page.getByText('Result from a saved view')).toBeVisible();

// hover the 'Result from a saved view' and show tooltip
await page.getByText('Result from a saved view').hover();
await expect(
page
.getByRole('tooltip', {
name: 'This search result corresponds to a saved view:',
})
.locator('svg'),
).toBeVisible();
await expect(
page.getByText('This search result corresponds to a saved view:'),
).toBeVisible();
await expect(page.getByRole('link', { name: viewName })).toBeVisible();

// just waiting to hide the tooltip
await page.getByRole('button', { name: 'Ask' }).hover();

const firstResult = await getFirstCandidatesResultSummary(page);
await page.getByRole('cell', { name: firstResult }).first().click();
await waitingForAskingTask(page);
await checkThreadResponseSkeletonLoading(page);

// check offer view info for thread response UI
await expect(page.getByText('Generated from saved view')).toBeVisible();
Expand Down
Loading

0 comments on commit 4caee5a

Please sign in to comment.