Skip to content

Commit

Permalink
test: fixed edge case with empty filter option names (#4124)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpaten committed Sep 18, 2024
1 parent 6633bed commit ad04996
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 28 deletions.
10 changes: 10 additions & 0 deletions explorer/e2e/anvil/anvil-filters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ test("Check that the clear all button functions on the files tab", async ({
test('Check that selecting filters through the "Search all Filters" textbox works correctly on the Datasets tab', async ({
page,
}) => {
test.setTimeout(120000);
await testSelectFiltersThroughSearchBar(
page,
ANVIL_TABS.DATASETS,
Expand All @@ -189,6 +190,7 @@ test('Check that selecting filters through the "Search all Filters" textbox work
test('Check that selecting filters through the "Search all Filters" textbox works correctly on the Donors tab', async ({
page,
}) => {
test.setTimeout(120000);
await testSelectFiltersThroughSearchBar(
page,
ANVIL_TABS.DONORS,
Expand All @@ -199,6 +201,7 @@ test('Check that selecting filters through the "Search all Filters" textbox work
test('Check that selecting filters through the "Search all Filters" textbox works correctly on the BioSamples tab', async ({
page,
}) => {
test.setTimeout(120000);
await testSelectFiltersThroughSearchBar(
page,
ANVIL_TABS.BIOSAMPLES,
Expand All @@ -209,6 +212,7 @@ test('Check that selecting filters through the "Search all Filters" textbox work
test('Check that selecting filters through the "Search all Filters" textbox works correctly on the Activities tab', async ({
page,
}) => {
test.setTimeout(120000);
await testSelectFiltersThroughSearchBar(
page,
ANVIL_TABS.ACTIVITIES,
Expand All @@ -219,6 +223,7 @@ test('Check that selecting filters through the "Search all Filters" textbox work
test('Check that selecting filters through the "Search all Filters" textbox works correctly on the Files tab', async ({
page,
}) => {
test.setTimeout(120000);
await testSelectFiltersThroughSearchBar(
page,
ANVIL_TABS.FILES,
Expand All @@ -229,6 +234,7 @@ test('Check that selecting filters through the "Search all Filters" textbox work
test('Check that deselecting filters through the "Search all Filters" textbox works correctly on the Datasets tab', async ({
page,
}) => {
test.setTimeout(120000);
await testDeselectFiltersThroughSearchBar(
page,
ANVIL_TABS.DATASETS,
Expand All @@ -239,6 +245,7 @@ test('Check that deselecting filters through the "Search all Filters" textbox wo
test('Check that deselecting filters through the "Search all Filters" textbox works correctly on the Donors tab', async ({
page,
}) => {
test.setTimeout(120000);
await testDeselectFiltersThroughSearchBar(
page,
ANVIL_TABS.DONORS,
Expand All @@ -249,6 +256,7 @@ test('Check that deselecting filters through the "Search all Filters" textbox wo
test('Check that deselecting filters through the "Search all Filters" textbox works correctly on the BioSamples tab', async ({
page,
}) => {
test.setTimeout(120000);
await testDeselectFiltersThroughSearchBar(
page,
ANVIL_TABS.BIOSAMPLES,
Expand All @@ -259,6 +267,7 @@ test('Check that deselecting filters through the "Search all Filters" textbox wo
test('Check that deselecting filters through the "Search all Filters" textbox works correctly on the Activities tab', async ({
page,
}) => {
test.setTimeout(120000);
await testDeselectFiltersThroughSearchBar(
page,
ANVIL_TABS.ACTIVITIES,
Expand All @@ -269,6 +278,7 @@ test('Check that deselecting filters through the "Search all Filters" textbox wo
test('Check that deselecting filters through the "Search all Filters" textbox works correctly on the Files tab', async ({
page,
}) => {
test.setTimeout(120000);
await testDeselectFiltersThroughSearchBar(
page,
ANVIL_TABS.FILES,
Expand Down
87 changes: 59 additions & 28 deletions explorer/e2e/testFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,32 +408,63 @@ export const getNamedFilterOptionLocator = (
};

/**
* Get a locator for the first filter option. Requires a filter menu to be open
* Get a locator for the nth filter option on the page.
* @param page - a Playwright page object
* @returns a Playwright locator to the filter button
* @param n - the index of the filter option to get
* @returns - a Playwright locator object for the first filter option on the page
*/
export const getFirstFilterOptionLocator = (page: Page): Locator => {
const getNthFilterOptionLocator = (page: Page, n: number): Locator => {
return page
.getByRole("button")
.filter({ has: page.getByRole("checkbox") })
.first();
.nth(n);
};

/**
* Get a locator for the first filter option on the page.
* @param page - a Playwright page object
* @returns - a Playwright locator object for the first filter option on the page
*/
export const getFirstFilterOptionLocator = (page: Page): Locator => {
return getNthFilterOptionLocator(page, 0);
};

interface FilterOptionNameAndLocator {
locator: Locator;
name: string;
}

const MAX_FILTER_OPTIONS_TO_CHECK = 10;

/**
* Gets the name of the filter option associated with a locator
* @param firstFilterOptionLocator - a Playwright locator to the filter option
* @returns the name of the filter option as a promise
* @param page - a Playwright Page object, on which a filter must be currently selected
* @returns the innerText of the first nonempty filter option as a promise
*/
export const getFilterOptionName = async (
firstFilterOptionLocator: Locator
): Promise<string> => {
// Filter options display as "[text]\n[number]" , sometimes with extra whitespace, so we split on newlines and take the first non-empty string
return (
(await firstFilterOptionLocator.innerText())
.split("\n")
.map((x) => x.trim())
.find((x) => x.length > 0) ?? ""
);
const getFirstNonEmptyFilterOptionNameAndLocator = async (
page: Page
): Promise<FilterOptionNameAndLocator> => {
let filterNameToSelect = "";
let filterOptionLocator = undefined;
let i = 0;
while (filterNameToSelect === "" && i < MAX_FILTER_OPTIONS_TO_CHECK) {
// Filter options display as "[text]\n[number]" , sometimes with extra whitespace, so we split on newlines and take the first non-empty string
const regex = /^(.*)\n+([0-9]+)\s*$/;
filterOptionLocator = getNthFilterOptionLocator(page, i);
console.log(await filterOptionLocator.innerText());
filterNameToSelect = ((await filterOptionLocator.innerText()).trim().match(regex) ?? [
"",
"",
])[1];
i += 1;
}

if (filterOptionLocator === undefined) {
throw new Error(
"No locator found within the maximum number of filter options"
);
}
return { locator: filterOptionLocator, name: filterNameToSelect };
};

/**
Expand Down Expand Up @@ -625,16 +656,16 @@ export async function testClearAll(
): Promise<void> {
await page.goto(tab.url);
const selectedFilterNamesList = [];
// Select each filter and get the names of the actual filter text
// Select each filter and get the names of the filter option text
for (const filterName of filterNames) {
await page.getByText(filterRegex(filterName)).dispatchEvent("click");
await getFirstFilterOptionLocator(page).getByRole("checkbox").click();
const filterOptionNameAndLocator =
await getFirstNonEmptyFilterOptionNameAndLocator(page);
await filterOptionNameAndLocator.locator.click();
await expect(
getFirstFilterOptionLocator(page).getByRole("checkbox")
filterOptionNameAndLocator.locator.getByRole("checkbox")
).toBeChecked();
selectedFilterNamesList.push(
await getFilterOptionName(getFirstFilterOptionLocator(page))
);
selectedFilterNamesList.push(filterOptionNameAndLocator.name);
await page.locator("body").click();
}
// Click the "Clear All" button
Expand Down Expand Up @@ -682,9 +713,9 @@ export async function testSelectFiltersThroughSearchBar(
await expect(page.getByText(filterRegex(filterName))).toBeVisible();
await page.getByText(filterRegex(filterName)).dispatchEvent("click");
const firstFilterOptionLocator = getFirstFilterOptionLocator(page);
const filterOptionName = await getFilterOptionName(
firstFilterOptionLocator
);
const filterOptionName = (
await getFirstNonEmptyFilterOptionNameAndLocator(page)
).name;
await page.locator("body").click();
// Search for the filter option
const searchFiltersInputLocator = page.getByPlaceholder(
Expand Down Expand Up @@ -720,10 +751,10 @@ export async function testDeselectFiltersThroughSearchBar(
// Select each filter option
await expect(page.getByText(filterRegex(filterName))).toBeVisible();
await page.getByText(filterRegex(filterName)).dispatchEvent("click");
const firstFilterOptionNameAndLocator =
await getFirstNonEmptyFilterOptionNameAndLocator(page);
const firstFilterOptionLocator = getFirstFilterOptionLocator(page);
const filterOptionName = await getFilterOptionName(
firstFilterOptionLocator
);
const filterOptionName = firstFilterOptionNameAndLocator.name;
await firstFilterOptionLocator.click();
await page.locator("body").click();
// Search for and check the selected filter
Expand Down

0 comments on commit ad04996

Please sign in to comment.