mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-30 05:18:11 +08:00
TS Revert (1) (#2402)
* revert all commits to before Typescript migration * update compat workflow to match latest deps (#2335) * update compat workflow to match latest deps * attempt to debug * attempt to debug * remove debugging code * typo * update deps to match desktop (#2340) * fix: don't run lint with `--fix` on push tests (#2273) * fix: don't run lint with `--fix` on push tests * npx Co-authored-by: maniarathi <mani.arathi@gmail.com> Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com> * rename X_approx_distribution to X_approximate_distribution (#2337) * Correctly handle non-finite numbers in heuristic determination of X distribution (#2342) * handle non-finites explicitly * improve and test edge case handling for distribution estimation * revert debugging changes * code readability * clean up type inferencing (#2332) * unit tests for 64 bit conversion * clean up type handling * type inference tests * more type inference fixes * use schema to determine user intent for data typing * stop using deprecated API * fbs type encoding test * add missing test * add more tests * correctly infer X type for CXG adaptor * lint * fix typo * ts migration * cleanup from PR review * lint * PR review changes * remove unused packages from client (#2359) * remove unused packages from client * add missing peer dep * fix: disable FE auth testing on compatibility tests (#2377) * update: release process (#2277) Co-authored-by: maniarathi <mani.arathi@gmail.com> * fix: remove spaces in param setup (#2380) * delete deploy workflow (#2396) * undo reformatting which now does not pass lint * fix snapshots which changed due to npm dep changes * add missing quoting to snapshot * another snapshot typo fix * TS Revert (2) - replay PR #2347 and #2354 (#2403) * replay edits from PR 2347 * TS Revert (3) - replay edits in PR #2327 (#2404) * replay edits in PR 2327 * TS Revert (4) - replay PR #2355 (#2405) * replay edits in PR 2355 * add additional babel config * reformat with new prettier config Co-authored-by: Severiano Badajoz <sbadajoz@chanzuckerberg.com> Co-authored-by: maniarathi <mani.arathi@gmail.com> Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>
This commit is contained in:
co-authored by
maniarathi
Madison Dunitz
Severiano Badajoz
parent
295590a7c6
commit
eaae6df5e3
@@ -0,0 +1,506 @@
|
||||
/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
import { strict as assert } from "assert";
|
||||
import {
|
||||
clearInputAndTypeInto,
|
||||
clickOn,
|
||||
getAllByClass,
|
||||
getOneElementInnerText,
|
||||
typeInto,
|
||||
waitByID,
|
||||
waitByClass,
|
||||
waitForAllByIds,
|
||||
clickOnUntil,
|
||||
getTestClass,
|
||||
getTestId,
|
||||
isElementPresent,
|
||||
goToPage,
|
||||
} from "./puppeteerUtils";
|
||||
|
||||
import { appUrlBase, TEST_EMAIL, TEST_PASSWORD } from "./config";
|
||||
|
||||
export async function drag(testId, start, end, lasso = false) {
|
||||
const layout = await waitByID(testId);
|
||||
const elBox = await layout.boxModel();
|
||||
const x1 = elBox.content[0].x + start.x;
|
||||
const x2 = elBox.content[0].x + end.x;
|
||||
const y1 = elBox.content[0].y + start.y;
|
||||
const y2 = elBox.content[0].y + end.y;
|
||||
await page.mouse.move(x1, y1);
|
||||
await page.mouse.down();
|
||||
if (lasso) {
|
||||
await page.mouse.move(x2, y1);
|
||||
await page.mouse.move(x2, y2);
|
||||
await page.mouse.move(x1, y2);
|
||||
await page.mouse.move(x1, y1);
|
||||
} else {
|
||||
await page.mouse.move(x2, y2);
|
||||
}
|
||||
await page.mouse.up();
|
||||
}
|
||||
|
||||
export async function clickOnCoordinate(testId, coord) {
|
||||
const layout = await expect(page).toMatchElement(getTestId(testId));
|
||||
const elBox = await layout.boxModel();
|
||||
|
||||
if (!elBox) {
|
||||
throw Error("Layout's boxModel is not available!");
|
||||
}
|
||||
|
||||
const x = elBox.content[0].x + coord.x;
|
||||
const y = elBox.content[0].y + coord.y;
|
||||
await page.mouse.click(x, y);
|
||||
}
|
||||
|
||||
export async function getAllHistograms(testclass, testIds) {
|
||||
const histTestIds = testIds.map((tid) => `histogram-${tid}`);
|
||||
|
||||
// these load asynchronously, so we need to wait for each histogram individually,
|
||||
// and they may be quite slow in some cases.
|
||||
await waitForAllByIds(histTestIds, { timeout: 4 * 60 * 1000 });
|
||||
|
||||
const allHistograms = await getAllByClass(testclass);
|
||||
|
||||
const testIDs = await Promise.all(
|
||||
allHistograms.map((hist) => page.evaluate((elem) => elem.dataset.testid, hist))
|
||||
);
|
||||
|
||||
return testIDs.map((id) => id.replace(/^histogram-/, ""));
|
||||
}
|
||||
|
||||
export async function getAllCategoriesAndCounts(category) {
|
||||
// these load asynchronously, so we have to wait for the specific category.
|
||||
await waitByID(`category-${category}`);
|
||||
|
||||
return page.$$eval(
|
||||
`[data-testid="category-${category}"] [data-testclass='categorical-row']`,
|
||||
(rows) =>
|
||||
Object.fromEntries(
|
||||
rows.map((row) => {
|
||||
const cat = row
|
||||
.querySelector("[data-testclass='categorical-value']")
|
||||
.getAttribute("aria-label");
|
||||
|
||||
const count = row.querySelector(
|
||||
"[data-testclass='categorical-value-count']"
|
||||
).innerText;
|
||||
|
||||
return [cat, count];
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export async function getCellSetCount(num) {
|
||||
await clickOn(`cellset-button-${num}`);
|
||||
return getOneElementInnerText(`[data-testid='cellset-count-${num}']`);
|
||||
}
|
||||
|
||||
export async function resetCategory(category) {
|
||||
const checkboxId = `${category}:category-select`;
|
||||
await waitByID(checkboxId);
|
||||
const checkedPseudoclass = await page.$eval(
|
||||
`[data-testid='${checkboxId}']`,
|
||||
(el) => el.matches(":checked")
|
||||
);
|
||||
if (!checkedPseudoclass) await clickOn(checkboxId);
|
||||
|
||||
const categoryRow = await waitByID(`${category}:category-expand`);
|
||||
|
||||
const isExpanded = await categoryRow.$(
|
||||
"[data-testclass='category-expand-is-expanded']"
|
||||
);
|
||||
|
||||
if (isExpanded) await clickOn(`${category}:category-expand`);
|
||||
}
|
||||
|
||||
export async function calcCoordinate(testId, xAsPercent, yAsPercent) {
|
||||
const el = await waitByID(testId);
|
||||
const size = await el.boxModel();
|
||||
return {
|
||||
x: Math.floor(size.width * xAsPercent),
|
||||
y: Math.floor(size.height * yAsPercent),
|
||||
};
|
||||
}
|
||||
|
||||
export async function calcDragCoordinates(testId, coordinateAsPercent) {
|
||||
return {
|
||||
start: await calcCoordinate(
|
||||
testId,
|
||||
coordinateAsPercent.x1,
|
||||
coordinateAsPercent.y1
|
||||
),
|
||||
end: await calcCoordinate(
|
||||
testId,
|
||||
coordinateAsPercent.x2,
|
||||
coordinateAsPercent.y2
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export async function selectCategory(category, values, reset = true) {
|
||||
if (reset) await resetCategory(category);
|
||||
|
||||
await clickOn(`${category}:category-expand`);
|
||||
await clickOn(`${category}:category-select`);
|
||||
|
||||
for (const value of values) {
|
||||
await clickOn(`categorical-value-select-${category}-${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function expandCategory(category) {
|
||||
const expand = await waitByID(`${category}:category-expand`);
|
||||
const notExpanded = await expand.$(
|
||||
"[data-testclass='category-expand-is-not-expanded']"
|
||||
);
|
||||
if (notExpanded) await clickOn(`${category}:category-expand`);
|
||||
}
|
||||
|
||||
export async function clip(min = 0, max = 100) {
|
||||
await clickOn("visualization-settings");
|
||||
await clearInputAndTypeInto("clip-min-input", min);
|
||||
await clearInputAndTypeInto("clip-max-input", max);
|
||||
await clickOn("clip-commit");
|
||||
}
|
||||
|
||||
export async function createCategory(categoryName) {
|
||||
await clickOnUntil("open-annotation-dialog", async () => {
|
||||
await expect(page).toMatchElement(getTestId("new-category-name"));
|
||||
});
|
||||
|
||||
await typeInto("new-category-name", categoryName);
|
||||
await clickOn("submit-category");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
GENESET
|
||||
|
||||
*/
|
||||
|
||||
export async function colorByGeneset(genesetName) {
|
||||
await clickOn(`${genesetName}:colorby-entire-geneset`);
|
||||
}
|
||||
|
||||
export async function colorByGene(gene) {
|
||||
await clickOn(`colorby-${gene}`);
|
||||
}
|
||||
|
||||
export async function assertColorLegendLabel(label) {
|
||||
const handle = await waitByID("continuous_legend_color_by_label");
|
||||
|
||||
const result = await handle.evaluate((node) => node.getAttribute("aria-label"));
|
||||
|
||||
return expect(result).toBe(label);
|
||||
}
|
||||
|
||||
export async function expandGeneset(genesetName) {
|
||||
const expand = await waitByID(`${genesetName}:geneset-expand`);
|
||||
const notExpanded = await expand.$(
|
||||
"[data-testclass='geneset-expand-is-not-expanded']"
|
||||
);
|
||||
if (notExpanded) await clickOn(`${genesetName}:geneset-expand`);
|
||||
}
|
||||
|
||||
export async function createGeneset(genesetName) {
|
||||
await clickOnUntil("open-create-geneset-dialog", async () => {
|
||||
await expect(page).toMatchElement(getTestId("create-geneset-input"));
|
||||
});
|
||||
|
||||
await typeInto("create-geneset-input", genesetName);
|
||||
await clickOn("submit-geneset");
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
export async function editGenesetName(genesetName, editText) {
|
||||
const editButton = `${genesetName}:edit-genesetName-mode`;
|
||||
const submitButton = `${genesetName}:submit-geneset`;
|
||||
await clickOnUntil(`${genesetName}:see-actions`, async () => {
|
||||
await expect(page).toMatchElement(getTestId(editButton));
|
||||
});
|
||||
await clickOn(editButton);
|
||||
await typeInto("rename-geneset-modal", editText);
|
||||
await clickOn(submitButton);
|
||||
}
|
||||
|
||||
export async function deleteGeneset(genesetName) {
|
||||
const targetId = `${genesetName}:delete-geneset`;
|
||||
|
||||
await clickOnUntil(`${genesetName}:see-actions`, async () => {
|
||||
await expect(page).toMatchElement(getTestId(targetId));
|
||||
});
|
||||
|
||||
await clickOn(targetId);
|
||||
|
||||
await assertGenesetDoesNotExist(genesetName);
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
export async function assertGenesetDoesNotExist(genesetName) {
|
||||
const result = await isElementPresent(
|
||||
getTestId(`${genesetName}:geneset-name`)
|
||||
);
|
||||
await expect(result).toBe(false);
|
||||
}
|
||||
|
||||
export async function assertGenesetExists(genesetName) {
|
||||
const handle = await waitByID(`${genesetName}:geneset-name`);
|
||||
|
||||
const result = await handle.evaluate((node) => node.getAttribute("aria-label"));
|
||||
|
||||
return expect(result).toBe(genesetName);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
GENE
|
||||
|
||||
*/
|
||||
|
||||
export async function addGeneToSet(genesetName, geneToAddToSet) {
|
||||
const submitButton = `${genesetName}:submit-gene`;
|
||||
|
||||
await clickOn(`${genesetName}:add-new-gene-to-geneset`);
|
||||
await typeInto("add-genes", geneToAddToSet);
|
||||
await clickOn(submitButton);
|
||||
}
|
||||
|
||||
export async function removeGene(geneSymbol) {
|
||||
const targetId = `delete-from-geneset:${geneSymbol}`;
|
||||
|
||||
await clickOn(targetId);
|
||||
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
export async function assertGeneExistsInGeneset(geneSymbol) {
|
||||
const handle = await waitByID(`${geneSymbol}:gene-label`);
|
||||
|
||||
const result = await handle.evaluate((node) => node.getAttribute("aria-label"));
|
||||
|
||||
return expect(result).toBe(geneSymbol);
|
||||
}
|
||||
|
||||
export async function assertGeneDoesNotExist(geneSymbol) {
|
||||
const result = await isElementPresent(getTestId(`${geneSymbol}:gene-label`));
|
||||
|
||||
await expect(result).toBe(false);
|
||||
}
|
||||
|
||||
export async function expandGene(geneSymbol) {
|
||||
await clickOn(`maximize-${geneSymbol}`);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
CATEGORY
|
||||
|
||||
*/
|
||||
|
||||
export async function duplicateCategory(categoryName) {
|
||||
await clickOn("open-annotation-dialog");
|
||||
|
||||
await typeInto("new-category-name", categoryName);
|
||||
|
||||
const dropdownOptionClass = "duplicate-category-dropdown-option";
|
||||
|
||||
await clickOnUntil("duplicate-category-dropdown", async () => {
|
||||
await expect(page).toMatchElement(getTestClass(dropdownOptionClass));
|
||||
});
|
||||
|
||||
const option = await expect(page).toMatchElement(
|
||||
getTestClass(dropdownOptionClass)
|
||||
);
|
||||
|
||||
await option.click();
|
||||
|
||||
await clickOnUntil("submit-category", async () => {
|
||||
await expect(page).toMatchElement(
|
||||
getTestId(`${categoryName}:category-expand`)
|
||||
);
|
||||
});
|
||||
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
export async function renameCategory(oldCategoryName, newCategoryName) {
|
||||
await clickOn(`${oldCategoryName}:see-actions`);
|
||||
await clickOn(`${oldCategoryName}:edit-category-mode`);
|
||||
await clearInputAndTypeInto(
|
||||
`${oldCategoryName}:edit-category-name-text`,
|
||||
newCategoryName
|
||||
);
|
||||
await clickOn(`${oldCategoryName}:submit-category-edit`);
|
||||
}
|
||||
|
||||
export async function deleteCategory(categoryName) {
|
||||
const targetId = `${categoryName}:delete-category`;
|
||||
|
||||
await clickOnUntil(`${categoryName}:see-actions`, async () => {
|
||||
await expect(page).toMatchElement(getTestId(targetId));
|
||||
});
|
||||
|
||||
await clickOn(targetId);
|
||||
|
||||
await assertCategoryDoesNotExist();
|
||||
}
|
||||
|
||||
export async function createLabel(categoryName, labelName) {
|
||||
/**
|
||||
* (thuang): This explicit wait is needed, since currently showing
|
||||
* the modal again quickly after the previous action dismissing the
|
||||
* modal will persist the input value from the previous action.
|
||||
*
|
||||
* To reproduce:
|
||||
* 1. Click on the plus sign to show the modal to add a new label to the category
|
||||
* 2. Type `123` in the input box
|
||||
* 3. Hover over your mouse over the plus sign and double click to quickly dismiss and
|
||||
* invoke the modal again
|
||||
* 4. You will see `123` is persisted in the input box
|
||||
* 5. Expected behavior is to get an empty input box
|
||||
*/
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await clickOn(`${categoryName}:see-actions`);
|
||||
|
||||
await clickOn(`${categoryName}:add-new-label-to-category`);
|
||||
|
||||
await typeInto(`${categoryName}:new-label-name`, labelName);
|
||||
|
||||
await clickOn(`${categoryName}:submit-label`);
|
||||
}
|
||||
|
||||
export async function deleteLabel(categoryName, labelName) {
|
||||
await expandCategory(categoryName);
|
||||
await clickOn(`${categoryName}:${labelName}:see-actions`);
|
||||
await clickOn(`${categoryName}:${labelName}:delete-label`);
|
||||
}
|
||||
|
||||
export async function renameLabel(categoryName, oldLabelName, newLabelName) {
|
||||
await expandCategory(categoryName);
|
||||
await clickOn(`${categoryName}:${oldLabelName}:see-actions`);
|
||||
await clickOn(`${categoryName}:${oldLabelName}:edit-label`);
|
||||
await clearInputAndTypeInto(
|
||||
`${categoryName}:${oldLabelName}:edit-label-name`,
|
||||
newLabelName
|
||||
);
|
||||
await clickOn(`${categoryName}:${oldLabelName}:submit-label-edit`);
|
||||
}
|
||||
|
||||
export async function addGeneToSearch(geneName) {
|
||||
await typeInto("gene-search", geneName);
|
||||
await page.keyboard.press("Enter");
|
||||
await page.waitForSelector(`[data-testid='histogram-${geneName}']`);
|
||||
}
|
||||
|
||||
export async function subset(coordinatesAsPercent) {
|
||||
// In order to deselect the selection after the subset, make sure we have some clear part
|
||||
// of the scatterplot we can click on
|
||||
assert(coordinatesAsPercent.x2 < 0.99 || coordinatesAsPercent.y2 < 0.99);
|
||||
const lassoSelection = await calcDragCoordinates(
|
||||
"layout-graph",
|
||||
coordinatesAsPercent
|
||||
);
|
||||
await drag("layout-graph", lassoSelection.start, lassoSelection.end, true);
|
||||
await clickOn("subset-button");
|
||||
const clearCoordinate = await calcCoordinate("layout-graph", 0.5, 0.99);
|
||||
await clickOnCoordinate("layout-graph", clearCoordinate);
|
||||
}
|
||||
|
||||
export async function setSellSet(cellSet, cellSetNum) {
|
||||
const selections = cellSet.filter((sel) => sel.kind === "categorical");
|
||||
|
||||
for (const selection of selections) {
|
||||
await selectCategory(selection.metadata, selection.values, true);
|
||||
}
|
||||
|
||||
await getCellSetCount(cellSetNum);
|
||||
}
|
||||
|
||||
export async function runDiffExp(cellSet1, cellSet2) {
|
||||
await setSellSet(cellSet1, 1);
|
||||
await setSellSet(cellSet2, 2);
|
||||
await clickOn("diffexp-button");
|
||||
}
|
||||
|
||||
export async function bulkAddGenes(geneNames) {
|
||||
await clickOn("section-bulk-add");
|
||||
await typeInto("input-bulk-add", geneNames.join(","));
|
||||
await page.keyboard.press("Enter");
|
||||
}
|
||||
|
||||
export async function assertCategoryDoesNotExist(categoryName) {
|
||||
const result = await isElementPresent(
|
||||
getTestId(`${categoryName}:category-label`)
|
||||
);
|
||||
|
||||
await expect(result).toBe(false);
|
||||
}
|
||||
|
||||
export async function login() {
|
||||
await goToPage(appUrlBase);
|
||||
|
||||
await clickOn("log-in");
|
||||
|
||||
// (thuang): Auth0 form is unstable and unsafe for input until verified
|
||||
await waitUntilFormFieldStable('[name="email"]');
|
||||
|
||||
await expect(page).toFillForm("form", {
|
||||
email: TEST_EMAIL,
|
||||
password: TEST_PASSWORD,
|
||||
});
|
||||
|
||||
await Promise.all([
|
||||
page.waitForNavigation({ waitUntil: "networkidle0" }),
|
||||
expect(page).toClick('[name="submit"]'),
|
||||
]);
|
||||
|
||||
expect(page.url()).toContain(appUrlBase);
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
await clickOnUntil("user-info", async () => {
|
||||
await waitByID("log-out");
|
||||
await Promise.all([
|
||||
page.waitForNavigation({ waitUntil: "networkidle0" }),
|
||||
clickOn("log-out"),
|
||||
]);
|
||||
});
|
||||
|
||||
await waitByID("log-in");
|
||||
}
|
||||
|
||||
async function waitUntilFormFieldStable(selector) {
|
||||
const MAX_RETRY = 10;
|
||||
const WAIT_FOR_MS = 200;
|
||||
|
||||
const EXPECTED_VALUE = "aaa";
|
||||
|
||||
let retry = 0;
|
||||
|
||||
while (retry < MAX_RETRY) {
|
||||
try {
|
||||
await expect(page).toFill(selector, EXPECTED_VALUE);
|
||||
|
||||
const fieldHandle = await expect(page).toMatchElement(selector);
|
||||
|
||||
const fieldValue = await page.evaluate(
|
||||
(input) => input.value,
|
||||
fieldHandle
|
||||
);
|
||||
|
||||
expect(fieldValue).toBe(EXPECTED_VALUE);
|
||||
|
||||
break;
|
||||
} catch (error) {
|
||||
retry += 1;
|
||||
|
||||
await page.waitForTimeout(WAIT_FOR_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry === MAX_RETRY) {
|
||||
throw Error("clickOnUntil() assertion failed!");
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
@@ -1,597 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
import { strict as assert } from "assert";
|
||||
import {
|
||||
clearInputAndTypeInto,
|
||||
clickOn,
|
||||
getAllByClass,
|
||||
getOneElementInnerText,
|
||||
typeInto,
|
||||
waitByID,
|
||||
waitByClass,
|
||||
waitForAllByIds,
|
||||
clickOnUntil,
|
||||
getTestClass,
|
||||
getTestId,
|
||||
isElementPresent,
|
||||
goToPage,
|
||||
} from "./puppeteerUtils";
|
||||
|
||||
import { appUrlBase, TEST_EMAIL, TEST_PASSWORD } from "./config";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function drag(testId: any, start: any, end: any, lasso = false) {
|
||||
const layout = await waitByID(testId);
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const elBox = await layout.boxModel();
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const x1 = elBox.content[0].x + start.x;
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const x2 = elBox.content[0].x + end.x;
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const y1 = elBox.content[0].y + start.y;
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const y2 = elBox.content[0].y + end.y;
|
||||
await page.mouse.move(x1, y1);
|
||||
await page.mouse.down();
|
||||
if (lasso) {
|
||||
await page.mouse.move(x2, y1);
|
||||
await page.mouse.move(x2, y2);
|
||||
await page.mouse.move(x1, y2);
|
||||
await page.mouse.move(x1, y1);
|
||||
} else {
|
||||
await page.mouse.move(x2, y2);
|
||||
}
|
||||
await page.mouse.up();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function clickOnCoordinate(testId: any, coord: any) {
|
||||
const layout = await expect(page).toMatchElement(getTestId(testId));
|
||||
const elBox = await layout.boxModel();
|
||||
|
||||
if (!elBox) {
|
||||
throw Error("Layout's boxModel is not available!");
|
||||
}
|
||||
|
||||
const x = elBox.content[0].x + coord.x;
|
||||
const y = elBox.content[0].y + coord.y;
|
||||
await page.mouse.click(x, y);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function getAllHistograms(testclass: any, testIds: any) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const histTestIds = testIds.map((tid: any) => `histogram-${tid}`);
|
||||
|
||||
// these load asynchronously, so we need to wait for each histogram individually,
|
||||
// and they may be quite slow in some cases.
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 2.
|
||||
await waitForAllByIds(histTestIds, { timeout: 4 * 60 * 1000 });
|
||||
|
||||
const allHistograms = await getAllByClass(testclass);
|
||||
|
||||
const testIDs = await Promise.all(
|
||||
allHistograms.map((hist) =>
|
||||
page.evaluate((elem) => elem.dataset.testid, hist)
|
||||
)
|
||||
);
|
||||
|
||||
return testIDs.map((id) => id.replace(/^histogram-/, ""));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function getAllCategoriesAndCounts(category: any) {
|
||||
// these load asynchronously, so we have to wait for the specific category.
|
||||
await waitByID(`category-${category}`);
|
||||
|
||||
return page.$$eval(
|
||||
`[data-testid="category-${category}"] [data-testclass='categorical-row']`,
|
||||
(rows) =>
|
||||
Object.fromEntries(
|
||||
rows.map((row) => {
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const cat = row
|
||||
.querySelector("[data-testclass='categorical-value']")
|
||||
.getAttribute("aria-label");
|
||||
|
||||
const count = (
|
||||
row.querySelector(
|
||||
"[data-testclass='categorical-value-count']"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
) as any
|
||||
).innerText;
|
||||
|
||||
return [cat, count];
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function getCellSetCount(num: any) {
|
||||
await clickOn(`cellset-button-${num}`);
|
||||
return getOneElementInnerText(`[data-testid='cellset-count-${num}']`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function resetCategory(category: any) {
|
||||
const checkboxId = `${category}:category-select`;
|
||||
await waitByID(checkboxId);
|
||||
const checkedPseudoclass = await page.$eval(
|
||||
`[data-testid='${checkboxId}']`,
|
||||
(el) => el.matches(":checked")
|
||||
);
|
||||
if (!checkedPseudoclass) await clickOn(checkboxId);
|
||||
|
||||
const categoryRow = await waitByID(`${category}:category-expand`);
|
||||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const isExpanded = await categoryRow.$(
|
||||
"[data-testclass='category-expand-is-expanded']"
|
||||
);
|
||||
|
||||
if (isExpanded) await clickOn(`${category}:category-expand`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function calcCoordinate(
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
testId: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
xAsPercent: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
yAsPercent: any
|
||||
) {
|
||||
const el = await waitByID(testId);
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const size = await el.boxModel();
|
||||
return {
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
x: Math.floor(size.width * xAsPercent),
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
y: Math.floor(size.height * yAsPercent),
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function calcDragCoordinates(
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
testId: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
coordinateAsPercent: any
|
||||
) {
|
||||
return {
|
||||
start: await calcCoordinate(
|
||||
testId,
|
||||
coordinateAsPercent.x1,
|
||||
coordinateAsPercent.y1
|
||||
),
|
||||
end: await calcCoordinate(
|
||||
testId,
|
||||
coordinateAsPercent.x2,
|
||||
coordinateAsPercent.y2
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function selectCategory(category: any, values: any, reset = true) {
|
||||
if (reset) await resetCategory(category);
|
||||
|
||||
await clickOn(`${category}:category-expand`);
|
||||
await clickOn(`${category}:category-select`);
|
||||
|
||||
for (const value of values) {
|
||||
await clickOn(`categorical-value-select-${category}-${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function expandCategory(category: any) {
|
||||
const expand = await waitByID(`${category}:category-expand`);
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const notExpanded = await expand.$(
|
||||
"[data-testclass='category-expand-is-not-expanded']"
|
||||
);
|
||||
if (notExpanded) await clickOn(`${category}:category-expand`);
|
||||
}
|
||||
|
||||
export async function clip(min = "0", max = "100"): Promise<void> {
|
||||
await clickOn("visualization-settings");
|
||||
await clearInputAndTypeInto("clip-min-input", min);
|
||||
await clearInputAndTypeInto("clip-max-input", max);
|
||||
await clickOn("clip-commit");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function createCategory(categoryName: any) {
|
||||
await clickOnUntil("open-annotation-dialog", async () => {
|
||||
await expect(page).toMatchElement(getTestId("new-category-name"));
|
||||
});
|
||||
|
||||
await typeInto("new-category-name", categoryName);
|
||||
await clickOn("submit-category");
|
||||
}
|
||||
|
||||
/**
|
||||
* GENESET
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function colorByGeneset(genesetName: any) {
|
||||
await clickOn(`${genesetName}:colorby-entire-geneset`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function colorByGene(gene: any) {
|
||||
await clickOn(`colorby-${gene}`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function assertColorLegendLabel(label: any) {
|
||||
const handle = await waitByID("continuous_legend_color_by_label");
|
||||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const result = await handle.evaluate((node) =>
|
||||
node.getAttribute("aria-label")
|
||||
);
|
||||
|
||||
return expect(result).toBe(label);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function expandGeneset(genesetName: any) {
|
||||
const expand = await waitByID(`${genesetName}:geneset-expand`);
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const notExpanded = await expand.$(
|
||||
"[data-testclass='geneset-expand-is-not-expanded']"
|
||||
);
|
||||
if (notExpanded) await clickOn(`${genesetName}:geneset-expand`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function createGeneset(genesetName: any) {
|
||||
await clickOnUntil("open-create-geneset-dialog", async () => {
|
||||
await expect(page).toMatchElement(getTestId("create-geneset-input"));
|
||||
});
|
||||
|
||||
await typeInto("create-geneset-input", genesetName);
|
||||
await clickOn("submit-geneset");
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function editGenesetName(genesetName: any, editText: any) {
|
||||
const editButton = `${genesetName}:edit-genesetName-mode`;
|
||||
const submitButton = `${genesetName}:submit-geneset`;
|
||||
await clickOnUntil(`${genesetName}:see-actions`, async () => {
|
||||
await expect(page).toMatchElement(getTestId(editButton));
|
||||
});
|
||||
await clickOn(editButton);
|
||||
await typeInto("rename-geneset-modal", editText);
|
||||
await clickOn(submitButton);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function deleteGeneset(genesetName: any) {
|
||||
const targetId = `${genesetName}:delete-geneset`;
|
||||
|
||||
await clickOnUntil(`${genesetName}:see-actions`, async () => {
|
||||
await expect(page).toMatchElement(getTestId(targetId));
|
||||
});
|
||||
|
||||
await clickOn(targetId);
|
||||
|
||||
await assertGenesetDoesNotExist(genesetName);
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function assertGenesetDoesNotExist(genesetName: any) {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
const result = await isElementPresent(
|
||||
getTestId(`${genesetName}:geneset-name`)
|
||||
);
|
||||
await expect(result).toBe(false);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function assertGenesetExists(genesetName: any) {
|
||||
const handle = await waitByID(`${genesetName}:geneset-name`);
|
||||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const result = await handle.evaluate((node) =>
|
||||
node.getAttribute("aria-label")
|
||||
);
|
||||
|
||||
return expect(result).toBe(genesetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* GENE
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function addGeneToSet(genesetName: any, geneToAddToSet: any) {
|
||||
const submitButton = `${genesetName}:submit-gene`;
|
||||
|
||||
await clickOn(`${genesetName}:add-new-gene-to-geneset`);
|
||||
await typeInto("add-genes", geneToAddToSet);
|
||||
await clickOn(submitButton);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function removeGene(geneSymbol: any) {
|
||||
const targetId = `delete-from-geneset:${geneSymbol}`;
|
||||
|
||||
await clickOn(targetId);
|
||||
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function assertGeneExistsInGeneset(geneSymbol: any) {
|
||||
const handle = await waitByID(`${geneSymbol}:gene-label`);
|
||||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const result = await handle.evaluate((node) =>
|
||||
node.getAttribute("aria-label")
|
||||
);
|
||||
|
||||
return expect(result).toBe(geneSymbol);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function assertGeneDoesNotExist(geneSymbol: any) {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
const result = await isElementPresent(getTestId(`${geneSymbol}:gene-label`));
|
||||
|
||||
await expect(result).toBe(false);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function expandGene(geneSymbol: any) {
|
||||
await clickOn(`maximize-${geneSymbol}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* CATEGORY
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function duplicateCategory(categoryName: any) {
|
||||
await clickOn("open-annotation-dialog");
|
||||
|
||||
await typeInto("new-category-name", categoryName);
|
||||
|
||||
const dropdownOptionClass = "duplicate-category-dropdown-option";
|
||||
|
||||
await clickOnUntil("duplicate-category-dropdown", async () => {
|
||||
await expect(page).toMatchElement(getTestClass(dropdownOptionClass));
|
||||
});
|
||||
|
||||
const option = await expect(page).toMatchElement(
|
||||
getTestClass(dropdownOptionClass)
|
||||
);
|
||||
|
||||
await option.click();
|
||||
|
||||
await clickOnUntil("submit-category", async () => {
|
||||
await expect(page).toMatchElement(
|
||||
getTestId(`${categoryName}:category-expand`)
|
||||
);
|
||||
});
|
||||
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function renameCategory(
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
oldCategoryName: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
newCategoryName: any
|
||||
) {
|
||||
await clickOn(`${oldCategoryName}:see-actions`);
|
||||
await clickOn(`${oldCategoryName}:edit-category-mode`);
|
||||
await clearInputAndTypeInto(
|
||||
`${oldCategoryName}:edit-category-name-text`,
|
||||
newCategoryName
|
||||
);
|
||||
await clickOn(`${oldCategoryName}:submit-category-edit`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function deleteCategory(categoryName: any) {
|
||||
const targetId = `${categoryName}:delete-category`;
|
||||
|
||||
await clickOnUntil(`${categoryName}:see-actions`, async () => {
|
||||
await expect(page).toMatchElement(getTestId(targetId));
|
||||
});
|
||||
|
||||
await clickOn(targetId);
|
||||
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
|
||||
await assertCategoryDoesNotExist();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function createLabel(categoryName: any, labelName: any) {
|
||||
/**
|
||||
* (thuang): This explicit wait is needed, since currently showing
|
||||
* the modal again quickly after the previous action dismissing the
|
||||
* modal will persist the input value from the previous action.
|
||||
*
|
||||
* To reproduce:
|
||||
* 1. Click on the plus sign to show the modal to add a new label to the category
|
||||
* 2. Type `123` in the input box
|
||||
* 3. Hover over your mouse over the plus sign and double click to quickly dismiss and
|
||||
* invoke the modal again
|
||||
* 4. You will see `123` is persisted in the input box
|
||||
* 5. Expected behavior is to get an empty input box
|
||||
*/
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await clickOn(`${categoryName}:see-actions`);
|
||||
|
||||
await clickOn(`${categoryName}:add-new-label-to-category`);
|
||||
|
||||
await typeInto(`${categoryName}:new-label-name`, labelName);
|
||||
|
||||
await clickOn(`${categoryName}:submit-label`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function deleteLabel(categoryName: any, labelName: any) {
|
||||
await expandCategory(categoryName);
|
||||
await clickOn(`${categoryName}:${labelName}:see-actions`);
|
||||
await clickOn(`${categoryName}:${labelName}:delete-label`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function renameLabel(
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
categoryName: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
oldLabelName: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
newLabelName: any
|
||||
) {
|
||||
await expandCategory(categoryName);
|
||||
await clickOn(`${categoryName}:${oldLabelName}:see-actions`);
|
||||
await clickOn(`${categoryName}:${oldLabelName}:edit-label`);
|
||||
await clearInputAndTypeInto(
|
||||
`${categoryName}:${oldLabelName}:edit-label-name`,
|
||||
newLabelName
|
||||
);
|
||||
await clickOn(`${categoryName}:${oldLabelName}:submit-label-edit`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function addGeneToSearch(geneName: any) {
|
||||
await typeInto("gene-search", geneName);
|
||||
await page.keyboard.press("Enter");
|
||||
await page.waitForSelector(`[data-testid='histogram-${geneName}']`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function subset(coordinatesAsPercent: any) {
|
||||
// In order to deselect the selection after the subset, make sure we have some clear part
|
||||
// of the scatterplot we can click on
|
||||
assert(coordinatesAsPercent.x2 < 0.99 || coordinatesAsPercent.y2 < 0.99);
|
||||
const lassoSelection = await calcDragCoordinates(
|
||||
"layout-graph",
|
||||
coordinatesAsPercent
|
||||
);
|
||||
await drag("layout-graph", lassoSelection.start, lassoSelection.end, true);
|
||||
await clickOn("subset-button");
|
||||
const clearCoordinate = await calcCoordinate("layout-graph", 0.5, 0.99);
|
||||
await clickOnCoordinate("layout-graph", clearCoordinate);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function setSellSet(cellSet: any, cellSetNum: any) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const selections = cellSet.filter((sel: any) => sel.kind === "categorical");
|
||||
|
||||
for (const selection of selections) {
|
||||
await selectCategory(selection.metadata, selection.values, true);
|
||||
}
|
||||
|
||||
await getCellSetCount(cellSetNum);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function runDiffExp(cellSet1: any, cellSet2: any) {
|
||||
await setSellSet(cellSet1, 1);
|
||||
await setSellSet(cellSet2, 2);
|
||||
await clickOn("diffexp-button");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function bulkAddGenes(geneNames: any) {
|
||||
await clickOn("section-bulk-add");
|
||||
await typeInto("input-bulk-add", geneNames.join(","));
|
||||
await page.keyboard.press("Enter");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function assertCategoryDoesNotExist(categoryName: any) {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
const result = await isElementPresent(
|
||||
getTestId(`${categoryName}:category-label`)
|
||||
);
|
||||
|
||||
await expect(result).toBe(false);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function login() {
|
||||
await goToPage(appUrlBase);
|
||||
|
||||
await clickOn("log-in");
|
||||
|
||||
// (thuang): Auth0 form is unstable and unsafe for input until verified
|
||||
await waitUntilFormFieldStable('[name="email"]');
|
||||
|
||||
await expect(page).toFillForm("form", {
|
||||
email: TEST_EMAIL,
|
||||
password: TEST_PASSWORD,
|
||||
});
|
||||
|
||||
await Promise.all([
|
||||
page.waitForNavigation({ waitUntil: "networkidle0" }),
|
||||
expect(page).toClick('[name="submit"]'),
|
||||
]);
|
||||
|
||||
expect(page.url()).toContain(appUrlBase);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function logout() {
|
||||
await clickOnUntil("user-info", async () => {
|
||||
await waitByID("log-out");
|
||||
await Promise.all([
|
||||
page.waitForNavigation({ waitUntil: "networkidle0" }),
|
||||
clickOn("log-out"),
|
||||
]);
|
||||
});
|
||||
|
||||
await waitByID("log-in");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function waitUntilFormFieldStable(selector: any) {
|
||||
const MAX_RETRY = 10;
|
||||
const WAIT_FOR_MS = 200;
|
||||
|
||||
const EXPECTED_VALUE = "aaa";
|
||||
|
||||
let retry = 0;
|
||||
|
||||
while (retry < MAX_RETRY) {
|
||||
try {
|
||||
await expect(page).toFill(selector, EXPECTED_VALUE);
|
||||
|
||||
const fieldHandle = await expect(page).toMatchElement(selector);
|
||||
|
||||
const fieldValue = await page.evaluate(
|
||||
(input) => input.value,
|
||||
fieldHandle
|
||||
);
|
||||
|
||||
expect(fieldValue).toBe(EXPECTED_VALUE);
|
||||
|
||||
break;
|
||||
} catch (error) {
|
||||
retry += 1;
|
||||
|
||||
await page.waitForTimeout(WAIT_FOR_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry === MAX_RETRY) {
|
||||
throw Error("clickOnUntil() assertion failed!");
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
@@ -58,12 +58,10 @@ describe("metadata loads", () => {
|
||||
const categories = await getAllCategoriesAndCounts(label);
|
||||
|
||||
expect(Object.keys(categories)).toMatchObject(
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
Object.keys(data.categorical[label])
|
||||
);
|
||||
|
||||
expect(Object.values(categories)).toMatchObject(
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
Object.values(data.categorical[label])
|
||||
);
|
||||
}
|
||||
@@ -161,12 +159,10 @@ describe("subset", () => {
|
||||
const categories = await getAllCategoriesAndCounts(label);
|
||||
|
||||
expect(Object.keys(categories)).toMatchObject(
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
Object.keys(data.subset.categorical[label])
|
||||
);
|
||||
|
||||
expect(Object.values(categories)).toMatchObject(
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
Object.values(data.subset.categorical[label])
|
||||
);
|
||||
}
|
||||
@@ -258,7 +254,6 @@ describe("centroid labels", () => {
|
||||
const generatedLabels = await getAllByClass("centroid-label");
|
||||
// Number of labels generated should be equal to size of the object
|
||||
expect(generatedLabels).toHaveLength(
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
Object.keys(data.categorical[label]).length
|
||||
);
|
||||
}
|
||||
@@ -280,7 +275,6 @@ describe("graph overlay", () => {
|
||||
data.pan["coordinates-as-percent"]
|
||||
);
|
||||
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
const categoryValue = Object.keys(data.categorical[category])[0];
|
||||
const initialCoordinates = await getElementCoordinates(
|
||||
`${categoryValue}-centroid-label`
|
||||
+9
-29
@@ -82,8 +82,7 @@ const genesetDescriptionID =
|
||||
const genesetDescriptionString = "fourth_gene_set: fourth description";
|
||||
const genesetToCheckForDescription = "fourth_gene_set";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function setup(config: any) {
|
||||
async function setup(config) {
|
||||
await goToPage(appUrlBase);
|
||||
|
||||
if (config.categoricalAnno) {
|
||||
@@ -157,8 +156,7 @@ describe.each([
|
||||
await expect(page).toClick(getTestClass("pop-1-geneset-expand"));
|
||||
|
||||
await page.waitForFunction(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(selector: any) => !document.querySelector(selector),
|
||||
(selector) => !document.querySelector(selector),
|
||||
{},
|
||||
getTestClass("gene-loading-spinner")
|
||||
);
|
||||
@@ -173,8 +171,7 @@ describe.each([
|
||||
await expect(page).toClick(getTestClass("pop-2-geneset-expand"));
|
||||
|
||||
await page.waitForFunction(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(selector: any) => !document.querySelector(selector),
|
||||
(selector) => !document.querySelector(selector),
|
||||
{},
|
||||
getTestClass("gene-loading-spinner")
|
||||
);
|
||||
@@ -405,13 +402,8 @@ describe.each([
|
||||
expect(actualLabelName).toBe(expectedLabelName);
|
||||
expect(actualLabelCount).toBe(expectedLabelCount);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function getInnerText(element: any, className: any) {
|
||||
return element.$eval(
|
||||
getTestClass(className),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(node: any) => node?.innerText
|
||||
);
|
||||
async function getInnerText(element, className) {
|
||||
return element.$eval(getTestClass(className), (node) => node?.innerText);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -436,9 +428,7 @@ describe.each([
|
||||
`categorical-value-count-${perTestCategoryName}-${perTestLabelName}`
|
||||
);
|
||||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
expect(await result.evaluate((node) => node.innerText)).toBe(
|
||||
// @ts-expect-error ts-migrate(2538) FIXME: Type 'boolean' cannot be used as an index type.
|
||||
data.categoryLabel.newCount.bySubsetConfig[config.withSubset]
|
||||
);
|
||||
});
|
||||
@@ -498,7 +488,6 @@ describe.each([
|
||||
await createLabel(perTestCategoryName, labelName);
|
||||
await assertLabelExists(perTestCategoryName, labelName);
|
||||
await clickOn("undo");
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
await assertLabelDoesNotExist(perTestCategoryName);
|
||||
await clickOn("redo");
|
||||
await assertLabelExists(perTestCategoryName, labelName);
|
||||
@@ -508,12 +497,10 @@ describe.each([
|
||||
await setup(config);
|
||||
|
||||
await deleteLabel(perTestCategoryName, perTestLabelName);
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
await assertLabelDoesNotExist(perTestCategoryName);
|
||||
await clickOn("undo");
|
||||
await assertLabelExists(perTestCategoryName, perTestLabelName);
|
||||
await clickOn("redo");
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
await assertLabelDoesNotExist(perTestCategoryName);
|
||||
});
|
||||
|
||||
@@ -544,9 +531,7 @@ describe.each([
|
||||
const labels = await getAllByClass("categorical-row");
|
||||
|
||||
const result = await Promise.all(
|
||||
labels.map((label) =>
|
||||
page.evaluate((element) => element.outerHTML, label)
|
||||
)
|
||||
labels.map((label) => page.evaluate((element) => element.outerHTML, label))
|
||||
);
|
||||
|
||||
expect(result).toMatchSnapshot();
|
||||
@@ -574,11 +559,9 @@ describe.each([
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function assertCategoryExists(categoryName: any) {
|
||||
async function assertCategoryExists(categoryName) {
|
||||
const handle = await waitByID(`${categoryName}:category-label`);
|
||||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
const result = await handle.evaluate((node) =>
|
||||
node.getAttribute("aria-label")
|
||||
);
|
||||
@@ -586,8 +569,7 @@ describe.each([
|
||||
return expect(result).toBe(categoryName);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function assertLabelExists(categoryName: any, labelName: any) {
|
||||
async function assertLabelExists(categoryName, labelName) {
|
||||
await expect(page).toMatchElement(
|
||||
getTestId(`${categoryName}:category-expand`)
|
||||
);
|
||||
@@ -599,13 +581,11 @@ describe.each([
|
||||
);
|
||||
|
||||
expect(
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
await previous.evaluate((node) => node.getAttribute("aria-label"))
|
||||
).toBe(labelName);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function assertLabelDoesNotExist(categoryName: any, labelName: any) {
|
||||
async function assertLabelDoesNotExist(categoryName, labelName) {
|
||||
await expandCategory(categoryName);
|
||||
const result = await page.$(
|
||||
`[data-testid='categorical-value-${categoryName}-${labelName}']`
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"testRunner": "jest-circus/runner",
|
||||
"preset": "jest-puppeteer",
|
||||
"testMatch": ["**/__tests__/**/?(*.)(spec|test).ts?(x)"],
|
||||
"setupFiles": ["../setupMissingGlobals.ts"],
|
||||
"setupFilesAfterEnv": ["expect-puppeteer", "./puppeteer.setup.ts"],
|
||||
"globalSetup": "../globalSetup.ts",
|
||||
"testMatch": ["**/__tests__/**/?(*.)(spec|test).js?(x)"],
|
||||
"setupFiles": ["../setupMissingGlobals.js"],
|
||||
"setupFilesAfterEnv": ["expect-puppeteer", "./puppeteer.setup.js"],
|
||||
"globalSetup": "../globalSetup.js",
|
||||
"globalTeardown": "jest-environment-puppeteer/teardown",
|
||||
"testEnvironment": "./screenshot_env.js"
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ beforeEach(async () => {
|
||||
const userAgent = await browser.userAgent();
|
||||
await page.setUserAgent(`${userAgent}bot`);
|
||||
|
||||
// @ts-expect-error ts-migrate(2341) FIXME: Property '_client' is private and only accessible ... Remove this comment to see the full error message
|
||||
await page._client.send("Animation.setPlaybackRate", { playbackRate: 12 });
|
||||
|
||||
page.on("pageerror", (err) => {
|
||||
@@ -50,8 +49,7 @@ beforeEach(async () => {
|
||||
}
|
||||
const errorMsgText = await Promise.all(
|
||||
// TODO can we do this without internal properties?
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
msg.args().map((arg: any) => arg._remoteObject.description)
|
||||
msg.args().map((arg) => arg._remoteObject.description)
|
||||
);
|
||||
throw new Error(`Console error: ${errorMsgText}`);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
export function getTestId(id) {
|
||||
return `[data-testid='${id}']`;
|
||||
}
|
||||
|
||||
export function getTestClass(className) {
|
||||
return `[data-testclass='${className}']`;
|
||||
}
|
||||
|
||||
export async function waitByID(testId, props = {}) {
|
||||
return page.waitForSelector(getTestId(testId), props);
|
||||
}
|
||||
|
||||
export async function waitByClass(testClass, props = {}) {
|
||||
return page.waitForSelector(`[data-testclass='${testClass}']`, props);
|
||||
}
|
||||
|
||||
export async function waitForAllByIds(testIds) {
|
||||
await Promise.all(
|
||||
testIds.map((testId) => page.waitForSelector(getTestId(testId)))
|
||||
);
|
||||
}
|
||||
|
||||
export async function getAllByClass(testClass) {
|
||||
return page.$$(`[data-testclass=${testClass}]`);
|
||||
}
|
||||
|
||||
export async function typeInto(testId, text) {
|
||||
// blueprint's typeahead is treating typing weird, clicking & waiting first solves this
|
||||
// only works for text without special characters
|
||||
await waitByID(testId);
|
||||
const selector = getTestId(testId);
|
||||
// type ahead can be annoying if you don't pause before you type
|
||||
await page.click(selector);
|
||||
await page.waitForTimeout(200);
|
||||
await page.type(selector, text);
|
||||
}
|
||||
|
||||
export async function clearInputAndTypeInto(testId, text) {
|
||||
await waitByID(testId);
|
||||
const selector = getTestId(testId);
|
||||
// only works for text without special characters
|
||||
// type ahead can be annoying if you don't pause before you type
|
||||
await page.click(selector);
|
||||
await page.waitForTimeout(200);
|
||||
// select all
|
||||
await page.click(selector, { clickCount: 3 });
|
||||
await page.keyboard.press("Backspace");
|
||||
await page.type(selector, text);
|
||||
}
|
||||
|
||||
export async function clickOn(testId, options = {}) {
|
||||
await expect(page).toClick(getTestId(testId), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* (thuang): There are times when Puppeteer clicks on a button and the page doesn't respond.
|
||||
* So I added clickOnUntil() to retry clicking until a given condition is met.
|
||||
*/
|
||||
export async function clickOnUntil(testId, assert) {
|
||||
const MAX_RETRY = 10;
|
||||
const WAIT_FOR_MS = 200;
|
||||
|
||||
let retry = 0;
|
||||
|
||||
while (retry < MAX_RETRY) {
|
||||
try {
|
||||
await clickOn(testId);
|
||||
await assert();
|
||||
|
||||
break;
|
||||
} catch (error) {
|
||||
retry += 1;
|
||||
|
||||
await page.waitForTimeout(WAIT_FOR_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry === MAX_RETRY) {
|
||||
throw Error("clickOnUntil() assertion failed!");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getOneElementInnerHTML(selector, options = {}) {
|
||||
await page.waitForSelector(selector, options);
|
||||
|
||||
return page.$eval(selector, (el) => el.innerHTML);
|
||||
}
|
||||
|
||||
export async function getOneElementInnerText(selector) {
|
||||
expect(page).toMatchElement(selector);
|
||||
|
||||
return page.$eval(selector, (el) => el.innerText);
|
||||
}
|
||||
|
||||
export async function getElementCoordinates(testId) {
|
||||
return page.$eval(getTestId(testId), (elem) => {
|
||||
const { left, top } = elem.getBoundingClientRect();
|
||||
return [left, top];
|
||||
});
|
||||
}
|
||||
|
||||
async function clickTermsOfService() {
|
||||
if (!(await isElementPresent(getTestId("tos-cookies-accept")))) return;
|
||||
|
||||
await clickOn("tos-cookies-accept");
|
||||
}
|
||||
|
||||
async function nameNewAnnotation() {
|
||||
if (await isElementPresent(getTestId("annotation-dialog"))) {
|
||||
await typeInto("new-annotation-name", "ignoreE2E");
|
||||
await clickOn("submit-annotation");
|
||||
|
||||
// wait for the page to load
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
}
|
||||
|
||||
export async function goToPage(url) {
|
||||
await page.goto(url, {
|
||||
waitUntil: "networkidle0",
|
||||
});
|
||||
|
||||
await nameNewAnnotation();
|
||||
await clickTermsOfService();
|
||||
}
|
||||
|
||||
export async function isElementPresent(selector, options) {
|
||||
return Boolean(await page.$(selector, options));
|
||||
}
|
||||
/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
@@ -1,151 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export function getTestId(id: any) {
|
||||
return `[data-testid='${id}']`;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export function getTestClass(className: any) {
|
||||
return `[data-testclass='${className}']`;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function waitByID(testId: any, props = {}) {
|
||||
return page.waitForSelector(getTestId(testId), props);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function waitByClass(testClass: any, props = {}) {
|
||||
return page.waitForSelector(`[data-testclass='${testClass}']`, props);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function waitForAllByIds(testIds: any) {
|
||||
await Promise.all(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
testIds.map((testId: any) => page.waitForSelector(getTestId(testId)))
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function getAllByClass(testClass: any) {
|
||||
return page.$$(`[data-testclass=${testClass}]`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function typeInto(testId: any, text: any) {
|
||||
// blueprint's typeahead is treating typing weird, clicking & waiting first solves this
|
||||
// only works for text without special characters
|
||||
await waitByID(testId);
|
||||
const selector = getTestId(testId);
|
||||
// type ahead can be annoying if you don't pause before you type
|
||||
await page.click(selector);
|
||||
await page.waitForTimeout(200);
|
||||
await page.type(selector, text);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function clearInputAndTypeInto(testId: any, text: any) {
|
||||
await waitByID(testId);
|
||||
const selector = getTestId(testId);
|
||||
// only works for text without special characters
|
||||
// type ahead can be annoying if you don't pause before you type
|
||||
await page.click(selector);
|
||||
await page.waitForTimeout(200);
|
||||
// select all
|
||||
await page.click(selector, { clickCount: 3 });
|
||||
await page.keyboard.press("Backspace");
|
||||
await page.type(selector, text);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function clickOn(testId: any, options = {}) {
|
||||
await expect(page).toClick(getTestId(testId), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* (thuang): There are times when Puppeteer clicks on a button and the page doesn't respond.
|
||||
* So I added clickOnUntil() to retry clicking until a given condition is met.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function clickOnUntil(testId: any, assert: any) {
|
||||
const MAX_RETRY = 10;
|
||||
const WAIT_FOR_MS = 200;
|
||||
|
||||
let retry = 0;
|
||||
|
||||
while (retry < MAX_RETRY) {
|
||||
try {
|
||||
await clickOn(testId);
|
||||
await assert();
|
||||
|
||||
break;
|
||||
} catch (error) {
|
||||
retry += 1;
|
||||
|
||||
await page.waitForTimeout(WAIT_FOR_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry === MAX_RETRY) {
|
||||
throw Error("clickOnUntil() assertion failed!");
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function getOneElementInnerHTML(selector: any, options = {}) {
|
||||
await page.waitForSelector(selector, options);
|
||||
|
||||
return page.$eval(selector, (el) => el.innerHTML);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function getOneElementInnerText(selector: any) {
|
||||
expect(page).toMatchElement(selector);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
return page.$eval(selector, (el) => (el as any).innerText);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function getElementCoordinates(testId: any) {
|
||||
return page.$eval(getTestId(testId), (elem) => {
|
||||
const { left, top } = elem.getBoundingClientRect();
|
||||
return [left, top];
|
||||
});
|
||||
}
|
||||
|
||||
async function clickTermsOfService() {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
if (!(await isElementPresent(getTestId("tos-cookies-accept")))) return;
|
||||
|
||||
await clickOn("tos-cookies-accept");
|
||||
}
|
||||
|
||||
async function nameNewAnnotation() {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
if (await isElementPresent(getTestId("annotation-dialog"))) {
|
||||
await typeInto("new-annotation-name", "ignoreE2E");
|
||||
await clickOn("submit-annotation");
|
||||
|
||||
// wait for the page to load
|
||||
await waitByClass("autosave-complete");
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function goToPage(url: any) {
|
||||
await page.goto(url, {
|
||||
waitUntil: "networkidle0",
|
||||
});
|
||||
|
||||
await nameNewAnnotation();
|
||||
await clickTermsOfService();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function isElementPresent(selector: any, options: any) {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 2.
|
||||
return Boolean(await page.$(selector, options));
|
||||
}
|
||||
/* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */
|
||||
@@ -1,11 +1,7 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS.
|
||||
const PuppeteerEnvironment = require("jest-environment-puppeteer");
|
||||
require("jest-circus");
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS.
|
||||
const ENV_DEFAULT = require("../../../environment.default.json");
|
||||
|
||||
// @ts-expect-error ts-migrate(2451) FIXME: Cannot redeclare block-scoped variable 'takeScreen... Remove this comment to see the full error message
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS.
|
||||
const takeScreenshot = require("./takeScreenshot");
|
||||
|
||||
class ScreenshotEnvironment extends PuppeteerEnvironment {
|
||||
|
||||
Reference in New Issue
Block a user