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:
Bruce Martin
2021-08-23 15:01:36 -07:00
committed by GitHub
co-authored by maniarathi Madison Dunitz Severiano Badajoz
parent 295590a7c6
commit eaae6df5e3
253 changed files with 11175 additions and 22271 deletions
+506
View File
@@ -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 */
-597
View File
@@ -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`
@@ -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}']`
+4 -4
View File
@@ -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}`);
}
+131
View File
@@ -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 */
-151
View File
@@ -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 */
-4
View File
@@ -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 {
@@ -1,12 +1,8 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment --- FIXME: disabled temporarily on migrate to TS.
// @ts-ignore FIXME: 'globalSetup.ts' cannot be compiled under '--isola... Remove this comment to see the full error message
const {
SecretsManagerClient,
GetSecretValueCommand,
// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS.
} = require("@aws-sdk/client-secrets-manager");
// eslint-disable-next-line @typescript-eslint/no-var-requires --- FIXME: disabled temporarily on migrate to TS.
const { setup } = require("jest-environment-puppeteer");
const client = new SecretsManagerClient({ region: "us-west-2" });
@@ -20,16 +20,7 @@ describe("cascade", () => {
const reducer = cascadeReducers([
[
"foo",
(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
currentState: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
action: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
nextSharedState: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
prevSharedState: any
) => {
(currentState, action, nextSharedState, prevSharedState) => {
expect(currentState).toBeUndefined();
expect(action).toEqual(topLevelAction);
expect(nextSharedState).toStrictEqual({});
@@ -39,16 +30,7 @@ describe("cascade", () => {
],
[
"bar",
(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
currentState: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
action: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
nextSharedState: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
prevSharedState: any
) => {
(currentState, action, nextSharedState, prevSharedState) => {
expect(currentState).toBeUndefined();
expect(action).toEqual(topLevelAction);
expect(nextSharedState).toStrictEqual({ foo: 0 });
@@ -501,7 +501,6 @@ describe("geneset: set tid", () => {
test("not a number error", () => {
expect(() => {
genesetsReducer(
// @ts-expect-error ts-migrate(2322) FIXME: Type 'number' is not assignable to type 'undefined... Remove this comment to see the full error message
{ lastTid: 1 },
{
type: "geneset: set tid",
@@ -514,7 +513,6 @@ describe("geneset: set tid", () => {
test("decrement error", () => {
expect(() => {
genesetsReducer(
// @ts-expect-error ts-migrate(2322) FIXME: Type 'number' is not assignable to type 'undefined... Remove this comment to see the full error message
{ lastTid: 1 },
{
type: "geneset: set tid",
@@ -1,12 +1,9 @@
import { Reducer } from "redux";
import undoable from "../../src/reducers/undoable";
describe("create", () => {
test("no keys", () => {
expect(() =>
undoable(() => {}, undefined as unknown as string[])
).toThrow();
expect(() => undoable(() => {}, null as unknown as string[])).toThrow();
expect(() => undoable(() => {})).toThrow();
expect(() => undoable(() => {}, null)).toThrow();
expect(() => undoable(() => {}, [])).toThrow();
expect(() => undoable(() => {}, [], {})).toThrow();
});
@@ -26,7 +23,7 @@ describe("create", () => {
describe("undo", () => {
test("expected state modifications", () => {
const initialState = { a: 0, b: 1000 };
const reducer: Reducer = (state) => ({ a: state.a + 1, b: state.b + 1 });
const reducer = (state) => ({ a: state.a + 1, b: state.b + 1 });
const undoableReducer = undoable(reducer, ["a"]);
const s1 = undoableReducer(initialState, { type: "test" });
@@ -44,8 +41,8 @@ describe("undo", () => {
describe("redo", () => {
const initialState = { a: 0, b: 1000 };
const reducer: Reducer = (state) => ({ a: state.a + 1, b: state.b + 1 });
let UR: Reducer;
const reducer = (state) => ({ a: state.a + 1, b: state.b + 1 });
let UR;
beforeEach(() => {
UR = undoable(reducer, ["a"]);
@@ -5,6 +5,5 @@ the jest test environment).
import { TextDecoder, TextEncoder } from "util";
// @ts-expect-error ts-migrate(2322) FIXME: Type 'typeof TextDecoder' is not assignable to typ... Remove this comment to see the full error message
global.TextDecoder = TextDecoder;
global.TextEncoder = TextEncoder;
@@ -11,18 +11,14 @@ describe("rangeEncodeIndices", () => {
test("sorted flag", () => {
expect(rangeEncodeIndices([1, 9, 432], 10, true)).toMatchObject([
1,
9,
432,
1, 9, 432,
]);
expect(rangeEncodeIndices([1, 9, 432], 10, false)).toMatchObject([
1,
9,
432,
1, 9, 432,
]);
expect(
rangeEncodeIndices([0, 1, 2, 3, 9, 10, 432], 2, true)
).toMatchObject([[0, 3], [9, 10], 432]);
expect(rangeEncodeIndices([0, 1, 2, 3, 9, 10, 432], 2, true)).toMatchObject(
[[0, 3], [9, 10], 432]
);
expect(
rangeEncodeIndices([0, 1, 2, 3, 9, 10, 432], 2, false)
).toMatchObject([[0, 3], [9, 10], 432]);
@@ -10,18 +10,14 @@ import {
isubsetMask,
} from "../../../src/annoMatrix";
import { Dataframe } from "../../../src/util/dataframe";
import { Field } from "../../../src/common/types/schema";
enableFetchMocks();
describe("AnnoMatrix", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let annoMatrix: any;
let annoMatrix;
beforeEach(async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).resetMocks(); // reset all fetch mocking state
// reset all fetch mocking state
fetch.resetMocks(); // reset all fetch mocking state
annoMatrix = new AnnoMatrixLoader(
serverMocks.baseDataURL,
serverMocks.schema.schema
@@ -35,67 +31,58 @@ describe("AnnoMatrix", () => {
expect(annoMatrix.nObs).toEqual(serverMocks.schema.schema.dataframe.nObs);
expect(annoMatrix.nVar).toEqual(serverMocks.schema.schema.dataframe.nVar);
expect(annoMatrix.isView).toBeFalsy();
expect(annoMatrix.viewOf).toBe(annoMatrix);
expect(annoMatrix.viewOf).toBeUndefined();
expect(annoMatrix.rowIndex).toBeDefined();
});
test("simple single column fetch", async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(serverMocks.annotationsObs(["name_0"]));
fetch.once(serverMocks.annotationsObs(["name_0"]));
const df = await annoMatrix.fetch(Field.obs, "name_0");
const df = await annoMatrix.fetch("obs", "name_0");
expect(df).toBeInstanceOf(Dataframe);
expect(df.colIndex.labels()).toEqual(["name_0"]);
expect(df.dims).toEqual([annoMatrix.nObs, 1]);
});
test("simple multi column fetch", async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any)
fetch
.once(serverMocks.annotationsObs(["name_0"]))
.once(serverMocks.annotationsObs(["n_genes"]));
await expect(
annoMatrix.fetch(Field.obs, ["name_0", "n_genes"])
annoMatrix.fetch("obs", ["name_0", "n_genes"])
).resolves.toBeInstanceOf(Dataframe);
});
describe("fetch from field", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const getLastTwo = async (field: any) => {
const getLastTwo = async (field) => {
const columnNames = annoMatrix.getMatrixColumns(field).slice(-2);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockResponses(
...columnNames.map(() => serverMocks.responder)
);
fetch.mockResponses(...columnNames.map(() => serverMocks.responder));
await expect(
annoMatrix.fetch(field, columnNames)
).resolves.toBeInstanceOf(Dataframe);
};
test(Field.obs, async () => getLastTwo(Field.obs));
test("obs", async () => getLastTwo("obs"));
test("var", async () => getLastTwo("var"));
test("emb", async () => getLastTwo("emb"));
});
test("fetch - test all query forms", async () => {
// single string is a column name
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(serverMocks.annotationsObs(["n_genes"]));
await expect(
annoMatrix.fetch(Field.obs, "n_genes")
).resolves.toBeInstanceOf(Dataframe);
fetch.once(serverMocks.annotationsObs(["n_genes"]));
await expect(annoMatrix.fetch("obs", "n_genes")).resolves.toBeInstanceOf(
Dataframe
);
// array of column names, expecting n_genes to be cached.
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(serverMocks.annotationsObs(["percent_mito"]));
fetch.once(serverMocks.annotationsObs(["percent_mito"]));
await expect(
annoMatrix.fetch(Field.obs, ["n_genes", "percent_mito"])
annoMatrix.fetch("obs", ["n_genes", "percent_mito"])
).resolves.toBeInstanceOf(Dataframe);
// more complex value filter query, enumerated
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(serverMocks.responder);
fetch.once(serverMocks.responder);
await expect(
annoMatrix.fetch("X", {
where: {
@@ -108,8 +95,7 @@ describe("AnnoMatrix", () => {
// more complex value filter query, range
const varIndex = annoMatrix.schema.annotations.var.index;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any)
fetch
.once(
serverMocks.withExpected("/data/var", [[`var:${varIndex}`, "SUMO3"]])
)
@@ -152,9 +138,9 @@ describe("AnnoMatrix", () => {
test("schema accessors", () => {
expect(annoMatrix.getMatrixFields()).toEqual(
expect.arrayContaining(["X", Field.obs, "emb", "var"])
expect.arrayContaining(["X", "obs", "emb", "var"])
);
expect(annoMatrix.getMatrixColumns(Field.obs)).toEqual(
expect(annoMatrix.getMatrixColumns("obs")).toEqual(
expect.arrayContaining(["name_0", "n_genes", "louvain"])
);
expect(annoMatrix.getColumnSchema("emb", "umap")).toEqual({
@@ -172,7 +158,7 @@ describe("AnnoMatrix", () => {
test the mask & label access to subset via isubset and isubsetMask
*/
test("isubset", async () => {
const rowList = new Int32Array([0, 10]);
const rowList = [0, 10];
const rowMask = new Uint8Array(annoMatrix.nObs);
for (let i = 0; i < rowList.length; i += 1) {
rowMask[rowList[i]] = 1;
@@ -185,14 +171,11 @@ describe("AnnoMatrix", () => {
expect(am1.nObs).toEqual(am2.nObs);
expect(am1.nVar).toEqual(am2.nVar);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any)
fetch
.once(serverMocks.annotationsObs(["n_genes"]))
.once(serverMocks.annotationsObs(["n_genes"]));
const ng1 = (await am1.fetch(Field.obs, "n_genes")) as Dataframe;
const ng2 = (await am2.fetch(Field.obs, "n_genes")) as Dataframe;
expect(ng1).toBeDefined();
expect(ng2).toBeDefined();
const ng1 = await am1.fetch("obs", "n_genes");
const ng2 = await am2.fetch("obs", "n_genes");
expect(ng1).toHaveLength(ng2.length);
expect(ng1.colIndex.labels()).toEqual(ng2.colIndex.labels());
expect(ng1.col("n_genes").asArray()).toEqual(
@@ -202,12 +185,10 @@ describe("AnnoMatrix", () => {
});
describe("add/drop column", () => {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type.
async function addDrop(base) {
expect(base.getMatrixColumns(Field.obs)).not.toContain("foo");
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(base.fetch(Field.obs, "foo")).rejects.toThrow(
expect(base.getMatrixColumns("obs")).not.toContain("foo");
fetch.mockRejectOnce(new Error("unknown column name"));
await expect(base.fetch("obs", "foo")).rejects.toThrow(
"unknown column name"
);
@@ -217,9 +198,9 @@ describe("AnnoMatrix", () => {
Float32Array,
0
);
expect(base.getMatrixColumns(Field.obs)).not.toContain("foo");
expect(am1.getMatrixColumns(Field.obs)).toContain("foo");
const foo: Dataframe = await am1.fetch(Field.obs, "foo");
expect(base.getMatrixColumns("obs")).not.toContain("foo");
expect(am1.getMatrixColumns("obs")).toContain("foo");
const foo = await am1.fetch("obs", "foo");
expect(foo).toBeDefined();
expect(foo).toBeInstanceOf(Dataframe);
expect(foo).toHaveLength(am1.nObs);
@@ -229,11 +210,10 @@ describe("AnnoMatrix", () => {
/* drop */
const am2 = am1.dropObsColumn("foo");
expect(base.getMatrixColumns(Field.obs)).not.toContain("foo");
expect(am2.getMatrixColumns(Field.obs)).not.toContain("foo");
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(am2.fetch(Field.obs, "foo")).rejects.toThrow(
expect(base.getMatrixColumns("obs")).not.toContain("foo");
expect(am2.getMatrixColumns("obs")).not.toContain("foo");
fetch.mockRejectOnce(new Error("unknown column name"));
await expect(am2.fetch("obs", "foo")).rejects.toThrow(
"unknown column name"
);
}
@@ -246,25 +226,23 @@ describe("AnnoMatrix", () => {
const am1 = clip(annoMatrix, 0.1, 0.9);
await addDrop(am1);
const am2 = isubset(am1, new Int32Array([0, 1, 2, 20, 30, 400]));
const am2 = isubset(am1, [0, 1, 2, 20, 30, 400]);
await addDrop(am2);
const am3 = isubset(annoMatrix, new Int32Array([10, 0, 7, 3]));
const am3 = isubset(annoMatrix, [10, 0, 7, 3]);
await addDrop(am3);
const am4 = clip(am3, 0, 1);
await addDrop(am4);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockResponse(serverMocks.responder);
fetch.mockResponse(serverMocks.responder);
await am1.fetch(Field.obs, am1.getMatrixColumns(Field.obs));
await am2.fetch(Field.obs, am2.getMatrixColumns(Field.obs));
await am3.fetch(Field.obs, am3.getMatrixColumns(Field.obs));
await am4.fetch(Field.obs, am4.getMatrixColumns(Field.obs));
await am1.fetch("obs", am1.getMatrixColumns("obs"));
await am2.fetch("obs", am2.getMatrixColumns("obs"));
await am3.fetch("obs", am3.getMatrixColumns("obs"));
await am4.fetch("obs", am4.getMatrixColumns("obs"));
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).resetMocks();
fetch.resetMocks();
await addDrop(am1);
await addDrop(am2);
@@ -274,7 +252,6 @@ describe("AnnoMatrix", () => {
});
describe("setObsColumnValues", () => {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type.
async function addSetDrop(base) {
/* add column */
let am = base.addObsColumn(
@@ -288,7 +265,7 @@ describe("AnnoMatrix", () => {
"unassigned"
);
const testVal = await am.fetch(Field.obs, "test");
const testVal = await am.fetch("obs", "test");
expect(testVal.col("test").asArray()).toEqual(
new Array(am.nObs).fill("unassigned")
);
@@ -296,7 +273,7 @@ describe("AnnoMatrix", () => {
/* set values in column */
const whichRows = [1, 2, 10];
const am1 = await am.setObsColumnValues("test", whichRows, "yo");
const testVal1 = await am1.fetch(Field.obs, "test");
const testVal1 = await am1.fetch("obs", "test");
const expt = new Array(am1.nObs).fill("unassigned");
for (let i = 0; i < whichRows.length; i += 1) {
const offset = am1.rowIndex.getOffset(whichRows[i]);
@@ -304,16 +281,15 @@ describe("AnnoMatrix", () => {
}
expect(testVal1).not.toBe(testVal);
expect(testVal1.col("test").asArray()).toEqual(expt);
expect(am1.getColumnSchema(Field.obs, "test").type).toBe("categorical");
expect(am1.getColumnSchema(Field.obs, "test").categories).toEqual(
expect(am1.getColumnSchema("obs", "test").type).toBe("categorical");
expect(am1.getColumnSchema("obs", "test").categories).toEqual(
expect.arrayContaining(["unassigned", "red", "green", "yo"])
);
/* drop column */
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
fetch.mockRejectOnce(new Error("unknown column name"));
am = am1.dropObsColumn("test");
await expect(am.fetch(Field.obs, "test")).rejects.toThrow(
await expect(am.fetch("obs", "test")).rejects.toThrow(
"unknown column name"
);
}
@@ -326,18 +302,17 @@ describe("AnnoMatrix", () => {
const am1 = clip(annoMatrix, 0.1, 0.9);
await addSetDrop(am1);
const am2 = isubset(am1, new Int32Array([0, 1, 2, 10, 20, 30, 400]));
const am2 = isubset(am1, [0, 1, 2, 10, 20, 30, 400]);
await addSetDrop(am2);
const am3 = isubset(annoMatrix, new Int32Array([10, 1, 0, 30, 2]));
const am3 = isubset(annoMatrix, [10, 1, 0, 30, 2]);
await addSetDrop(am3);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockResponse(serverMocks.responder);
fetch.mockResponse(serverMocks.responder);
await am1.fetch(Field.obs, am1.getMatrixColumns(Field.obs));
await am2.fetch(Field.obs, am2.getMatrixColumns(Field.obs));
await am3.fetch(Field.obs, am3.getMatrixColumns(Field.obs));
await am1.fetch("obs", am1.getMatrixColumns("obs"));
await am2.fetch("obs", am2.getMatrixColumns("obs"));
await am3.fetch("obs", am3.getMatrixColumns("obs"));
await addSetDrop(am1);
await addSetDrop(am2);
@@ -12,25 +12,19 @@ import {
AnnoMatrixObsCrossfilter,
isubsetMask,
} from "../../../src/annoMatrix";
import { Dataframe } from "../../../src/util/dataframe";
import { rangeFill } from "../../../src/util/range";
import { Field, Schema } from "../../../src/common/types/schema";
enableFetchMocks();
describe("AnnoMatrixCrossfilter", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let annoMatrix: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let crossfilter: any;
let annoMatrix;
let crossfilter;
beforeEach(async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).resetMocks(); // reset all fetch mocking state
// reset all fetch mocking state
fetch.resetMocks(); // reset all fetch mocking state
annoMatrix = new AnnoMatrixLoader(
serverMocks.baseDataURL,
serverMocks.schema.schema as Schema
serverMocks.schema.schema
);
crossfilter = new AnnoMatrixObsCrossfilter(annoMatrix);
});
@@ -73,11 +67,8 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.obsCrossfilter.hasDimension("obs/louvain")
).toBeFalsy();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
let newCrossfilter = await crossfilter.select(Field.obs, "louvain", {
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain]));
let newCrossfilter = await crossfilter.select("obs", "louvain", {
mode: "none",
});
@@ -85,10 +76,9 @@ describe("AnnoMatrixCrossfilter", () => {
expect(
newCrossfilter.obsCrossfilter.hasDimension("obs/louvain")
).toBeTruthy();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
expect((fetch as any).mock.calls).toHaveLength(1);
expect(fetch.mock.calls).toHaveLength(1);
newCrossfilter = await crossfilter.select(Field.obs, "louvain", {
newCrossfilter = await crossfilter.select("obs", "louvain", {
mode: "all",
});
expect(newCrossfilter.countSelected()).toEqual(annoMatrix.nObs);
@@ -97,11 +87,8 @@ describe("AnnoMatrixCrossfilter", () => {
test("simple column select", async () => {
let xfltr;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
xfltr = await crossfilter.select(Field.obs, "louvain", {
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain]));
xfltr = await crossfilter.select("obs", "louvain", {
mode: "exact",
values: ["NK cells", "B cells"],
});
@@ -118,7 +105,6 @@ describe("AnnoMatrixCrossfilter", () => {
expect(xfltr.allSelectedLabels()).toEqual(
Int32Array.from(
obsLouvain.reduce((acc, val, idx) => {
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number' is not assignable to par... Remove this comment to see the full error message
if (val === "NK cells" || val === "B cells") acc.push(idx);
return acc;
}, [])
@@ -134,20 +120,17 @@ describe("AnnoMatrixCrossfilter", () => {
)
);
const df: Dataframe = await annoMatrix.fetch(Field.obs, "louvain");
const df = await annoMatrix.fetch("obs", "louvain");
const values = df.col("louvain").asArray();
const selected = xfltr.allSelectedMask();
values.every(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(val: any, idx: any) =>
!["NK cells", "B cells"].includes(val) !== !selected[idx]
(val, idx) => !["NK cells", "B cells"].includes(val) !== !selected[idx]
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(
fetch.once(
serverMocks.dataframeResponse(["n_genes"], [new Int32Array(obsNGenes)])
);
xfltr = await xfltr.select(Field.obs, "n_genes", {
xfltr = await xfltr.select("obs", "n_genes", {
mode: "range",
lo: 0,
hi: 500,
@@ -163,7 +146,6 @@ describe("AnnoMatrixCrossfilter", () => {
val < 500 &&
(louvain === "NK cells" || louvain === "B cells")
)
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number' is not assignable to par... Remove this comment to see the full error message
acc.push(idx);
return acc;
}, [])
@@ -178,8 +160,7 @@ describe("AnnoMatrixCrossfilter", () => {
const varIndex = annoMatrix.schema.annotations.var.index;
const { nObs } = annoMatrix.schema.dataframe;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(
fetch.once(
serverMocks.dataframeResponse(
["TEST"],
[rangeFill(new Float32Array(nObs), 0, 0.1)]
@@ -215,19 +196,14 @@ describe("AnnoMatrixCrossfilter", () => {
});
const values = df.icol(0).asArray();
const selected = xfltr.allSelectedMask();
values.every(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(val: any, idx: any) => !(val >= 0 && val <= 50) !== !selected[idx]
values.every((val, idx) => !(val >= 0 && val <= 50) !== !selected[idx]);
expect(selected.reduce((acc, val) => (val ? acc + 1 : acc), 0)).toEqual(
xfltr.countSelected()
);
expect(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
selected.reduce((acc: any, val: any) => (val ? acc + 1 : acc), 0)
).toEqual(xfltr.countSelected());
});
test("spatial column select", async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(
fetch.once(
serverMocks.dataframeResponse(
["umap_0", "umap_1"],
[Float32Array.from(embUmap[0]), Float32Array.from(embUmap[1])]
@@ -246,7 +222,6 @@ describe("AnnoMatrixCrossfilter", () => {
test("select on subset", async () => {
const mask = new Uint8Array(annoMatrix.nObs).fill(0);
for (let i = 0; i < mask.length; i += 2) {
// @ts-expect-error ts-migrate(2322) FIXME: Type 'boolean' is not assignable to type 'number'.
mask[i] = true;
}
const annoMatrixSubset = isubsetMask(annoMatrix, mask);
@@ -255,11 +230,8 @@ describe("AnnoMatrixCrossfilter", () => {
let xfltr = new AnnoMatrixObsCrossfilter(annoMatrixSubset);
expect(xfltr.countSelected()).toEqual(annoMatrixSubset.nObs);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
xfltr = await xfltr.select(Field.obs, "louvain", {
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain]));
xfltr = await xfltr.select("obs", "louvain", {
mode: "exact",
values: ["NK cells", "B cells"],
});
@@ -267,17 +239,11 @@ describe("AnnoMatrixCrossfilter", () => {
expect(xfltr).toBeDefined();
expect(xfltr.countSelected()).toEqual(240);
const df: Dataframe = (await annoMatrixSubset.fetch(
Field.obs,
"louvain"
)) as Dataframe;
expect(df).toBeDefined();
const df = await annoMatrixSubset.fetch("obs", "louvain");
const values = df.col("louvain").asArray();
const selected = xfltr.allSelectedMask();
values.every(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(val: any, idx: any) =>
!["NK cells", "B cells"].includes(val) !== !selected[idx]
(val, idx) => !["NK cells", "B cells"].includes(val) !== !selected[idx]
);
});
@@ -290,9 +256,8 @@ describe("AnnoMatrixCrossfilter", () => {
"unable to obsSelect upon the var dimension"
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(crossfilter.select(Field.obs, "foo")).rejects.toThrow(
fetch.mockRejectOnce(new Error("unknown column name"));
await expect(crossfilter.select("obs", "foo")).rejects.toThrow(
"unknown column name"
);
});
@@ -302,32 +267,27 @@ describe("AnnoMatrixCrossfilter", () => {
/*
test the matrix mutators via crossfilter proxy
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
async function helperAddTestCol(cf: any, colName: any, colSchema = null) {
async function helperAddTestCol(cf, colName, colSchema = null) {
expect(
cf.annoMatrix.getMatrixColumns(Field.obs).includes(colName)
cf.annoMatrix.getMatrixColumns("obs").includes(colName)
).toBeFalsy();
if (colSchema === null) {
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ name: any; type: string; categories: strin... Remove this comment to see the full error message
colSchema = {
name: colName,
type: "categorical",
categories: ["toasty"],
};
}
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
colSchema.name = colName;
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
const initValue = colSchema.categories[0];
const xfltr = cf.addObsColumn(colSchema, Array, initValue);
expect(
xfltr.annoMatrix.schema.annotations.obs.columns.filter(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(v: any) => v.name === colName
(v) => v.name === colName
)
).toHaveLength(1);
const df = await xfltr.annoMatrix.fetch(Field.obs, colName);
const df = await xfltr.annoMatrix.fetch("obs", colName);
expect(df.hasCol(colName)).toBeTruthy();
return xfltr;
}
@@ -335,7 +295,7 @@ describe("AnnoMatrixCrossfilter", () => {
test("addObsColumn", async () => {
expect(crossfilter.countSelected()).toBe(annoMatrix.nObs);
expect(
crossfilter.annoMatrix.getMatrixColumns(Field.obs).includes("foo")
crossfilter.annoMatrix.getMatrixColumns("obs").includes("foo")
).toBeFalsy();
const xfltr = crossfilter.addObsColumn(
{ name: "foo", type: "categorical", categories: ["A"] },
@@ -346,7 +306,7 @@ describe("AnnoMatrixCrossfilter", () => {
// check schema updates correctly.
expect(xfltr.countSelected()).toBe(annoMatrix.nObs);
expect(
xfltr.annoMatrix.getMatrixColumns(Field.obs).includes("foo")
xfltr.annoMatrix.getMatrixColumns("obs").includes("foo")
).toBeTruthy();
expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toMatchObject({
name: "foo",
@@ -354,18 +314,17 @@ describe("AnnoMatrixCrossfilter", () => {
});
expect(
xfltr.annoMatrix.schema.annotations.obs.columns.filter(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(v: any) => v.name === "foo"
(v) => v.name === "foo"
)
).toHaveLength(1);
// check data update.
const df: Dataframe = await xfltr.annoMatrix.fetch(Field.obs, "foo");
const df = await xfltr.annoMatrix.fetch("obs", "foo");
expect(
df
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "A")
.asArray()
.every((v) => v === "A")
).toBeTruthy();
// check that we catch dups
@@ -402,30 +361,27 @@ describe("AnnoMatrixCrossfilter", () => {
xfltr = xfltr.dropObsColumn("foo");
expect(
xfltr.annoMatrix.schema.annotations.obs.columns.filter(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(v: any) => v.name === "foo"
(v) => v.name === "foo"
)
).toHaveLength(0);
expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toBeUndefined();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch(Field.obs, "foo")).rejects.toThrow(
fetch.mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow(
"unknown column name"
);
// now same, but ensure we have built an index before doing the drop
xfltr = await helperAddTestCol(crossfilter, "bar");
xfltr = await xfltr.select(Field.obs, "bar", {
xfltr = await xfltr.select("obs", "bar", {
mode: "exact",
values: "whatever",
});
xfltr = xfltr.dropObsColumn("bar");
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(
xfltr.select(Field.obs, "bar", { mode: "all" })
).rejects.toThrow("unknown column name");
fetch.mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow(
"unknown column name"
);
});
test("renameObsColumn", async () => {
@@ -442,43 +398,38 @@ describe("AnnoMatrixCrossfilter", () => {
// add a column, then rename it.
xfltr = await helperAddTestCol(crossfilter, "foo");
xfltr = xfltr.renameObsColumn("foo", "bar");
expect(
xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")
).toBeUndefined();
expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "bar")).toMatchObject({
expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toBeUndefined();
expect(xfltr.annoMatrix.getColumnSchema("obs", "bar")).toMatchObject({
name: "bar",
type: "categorical",
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch(Field.obs, "foo")).rejects.toThrow(
fetch.mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow(
"unknown column name"
);
const df = await xfltr.annoMatrix.fetch(Field.obs, "bar");
const df = await xfltr.annoMatrix.fetch("obs", "bar");
expect(df.hasCol("bar")).toBeTruthy();
// now same, but ensure we have built an index before doing the rename
xfltr = await helperAddTestCol(crossfilter, "bar");
xfltr = await xfltr.select(Field.obs, "bar", {
xfltr = await xfltr.select("obs", "bar", {
mode: "exact",
values: "whatever",
});
xfltr = xfltr.renameObsColumn("bar", "xyz");
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).mockRejectOnce(new Error("unknown column name"));
fetch.mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow(
"unknown column name"
);
await expect(
xfltr.select(Field.obs, "bar", { mode: "all" })
).rejects.toThrow("unknown column name");
await expect(
xfltr.select(Field.obs, "xyz", { mode: "none" })
xfltr.select("obs", "xyz", { mode: "none" })
).resolves.toBeInstanceOf(AnnoMatrixObsCrossfilter);
});
test("addObsAnnoCategory", async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let xfltr: any;
let xfltr;
// catch unknown or readonly columns
expect(() => crossfilter.addObsAnnoCategory("louvain", "mumble")).toThrow(
@@ -489,14 +440,13 @@ describe("AnnoMatrixCrossfilter", () => {
).toThrow("Unknown or readonly obs column");
// add a column and then add category to it
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo",
type: "categorical",
categories: ["unassigned"],
});
xfltr = xfltr.addObsAnnoCategory("foo", "a-new-label");
expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject({
expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo",
type: "categorical",
categories: expect.arrayContaining(["a-new-label", "unassigned"]),
@@ -508,18 +458,17 @@ describe("AnnoMatrixCrossfilter", () => {
);
// now same, but ensure we have built an index before doing the operation
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
xfltr = await helperAddTestCol(crossfilter, "bar", {
name: "bar",
type: "categorical",
categories: ["unassigned"],
});
xfltr = await xfltr.select(Field.obs, "bar", {
xfltr = await xfltr.select("obs", "bar", {
mode: "exact",
values: "something",
});
xfltr = xfltr.addObsAnnoCategory("bar", "a-new-label");
expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "bar")).toMatchObject({
expect(xfltr.annoMatrix.getColumnSchema("obs", "bar")).toMatchObject({
name: "bar",
type: "categorical",
categories: expect.arrayContaining(["a-new-label", "unassigned"]),
@@ -537,20 +486,19 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.removeObsAnnoCategory("undefined-name", "mumble")
).rejects.toThrow("Unknown or readonly obs column");
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo",
type: "categorical",
categories: ["unassigned", "red", "green", "blue"],
});
xfltr = await xfltr.select(Field.obs, "foo", { mode: "all" });
xfltr = await xfltr.select("obs", "foo", { mode: "all" });
expect(
(await xfltr.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "unassigned")
.asArray()
.every((v) => v === "unassigned")
).toBeTruthy();
expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject({
expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo",
type: "categorical",
categories: expect.arrayContaining([
@@ -564,23 +512,21 @@ describe("AnnoMatrixCrossfilter", () => {
// remove an unused category
const xfltr1 = await xfltr.removeObsAnnoCategory("foo", "red", "mumble");
expect(
(await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "unassigned")
.asArray()
.every((v) => v === "unassigned")
).toBeTruthy();
expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
{
name: "foo",
type: "categorical",
categories: expect.arrayContaining([
"unassigned",
"green",
"blue",
"mumble",
]),
}
);
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo",
type: "categorical",
categories: expect.arrayContaining([
"unassigned",
"green",
"blue",
"mumble",
]),
});
// remove a used category
const xfltr2 = await xfltr.removeObsAnnoCategory(
@@ -589,18 +535,16 @@ describe("AnnoMatrixCrossfilter", () => {
"red"
);
expect(
(await xfltr2.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr2.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "red")
.asArray()
.every((v) => v === "red")
).toBeTruthy();
expect(xfltr2.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
{
name: "foo",
type: "categorical",
categories: expect.arrayContaining(["green", "blue", "red"]),
}
);
expect(xfltr2.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo",
type: "categorical",
categories: expect.arrayContaining(["green", "blue", "red"]),
});
});
test("setObsColumnValues", async () => {
@@ -612,13 +556,12 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.setObsColumnValues("undefined-name", [0], "mumble")
).rejects.toThrow("Unknown or readonly obs column");
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
let xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo",
type: "categorical",
categories: ["unassigned", "red", "green", "blue"],
});
xfltr = await xfltr.select(Field.obs, "foo", { mode: "all" });
xfltr = await xfltr.select("obs", "foo", { mode: "all" });
// catch unknown row label
await expect(() =>
@@ -627,43 +570,40 @@ describe("AnnoMatrixCrossfilter", () => {
// set a few rows
expect(
(await xfltr.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "unassigned")
.asArray()
.every((v) => v === "unassigned")
).toBeTruthy();
const xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple");
expect(
(await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray()
.every(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(v: any, i: any) =>
(v, i) =>
v === "unassigned" || (v === "purple" && (i === 0 || i === 10))
)
).toBeTruthy();
expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
{
name: "foo",
type: "categorical",
categories: expect.arrayContaining([
"unassigned",
"red",
"green",
"blue",
"purple",
]),
}
);
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo",
type: "categorical",
categories: expect.arrayContaining([
"unassigned",
"red",
"green",
"blue",
"purple",
]),
});
expect(xfltr1.countSelected()).toEqual(xfltr1.annoMatrix.nObs);
const xfltr2 = await xfltr1.select(Field.obs, "foo", {
const xfltr2 = await xfltr1.select("obs", "foo", {
mode: "exact",
values: ["purple"],
});
expect(xfltr2.countSelected()).toEqual(2);
expect(xfltr2.allSelectedLabels()).toEqual(Array.from([0, 10]));
expect(xfltr2.allSelectedLabels()).toEqual(Int32Array.from([0, 10]));
});
test("resetObsColumnValues", async () => {
@@ -675,13 +615,12 @@ describe("AnnoMatrixCrossfilter", () => {
crossfilter.resetObsColumnValues("undefined-name", "red", "blue")
).rejects.toThrow("Unknown or readonly obs column");
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: string; type: string; ca... Remove this comment to see the full error message
let xfltr = await helperAddTestCol(crossfilter, "foo", {
name: "foo",
type: "categorical",
categories: ["unassigned", "red", "green", "blue"],
});
xfltr = await xfltr.select(Field.obs, "foo", {
xfltr = await xfltr.select("obs", "foo", {
mode: "exact",
values: "red",
});
@@ -692,60 +631,54 @@ describe("AnnoMatrixCrossfilter", () => {
).rejects.toThrow("unknown category");
let xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple");
xfltr1 = await xfltr1.select(Field.obs, "foo", {
xfltr1 = await xfltr1.select("obs", "foo", {
mode: "exact",
values: "purple",
});
expect(
(await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((v: any) => v === "purple")
.asArray()
.filter((v) => v === "purple")
).toHaveLength(2);
xfltr1 = await xfltr1.resetObsColumnValues("foo", "purple", "magenta");
expect(
(await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((v: any) => v === "magenta")
.asArray()
.filter((v) => v === "magenta")
).toHaveLength(2);
expect(
(await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
(await xfltr1.annoMatrix.fetch("obs", "foo"))
.col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((v: any) => v === "purple")
.asArray()
.filter((v) => v === "purple")
).toHaveLength(0);
expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
{
name: "foo",
type: "categorical",
categories: expect.arrayContaining([
"unassigned",
"red",
"green",
"blue",
"purple",
"magenta",
]),
}
);
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({
name: "foo",
type: "categorical",
categories: expect.arrayContaining([
"unassigned",
"red",
"green",
"blue",
"purple",
"magenta",
]),
});
});
});
describe("edge cases", () => {
test("transition from empty annoMatrix", async () => {
// select before fetch needs to work
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain])
);
const xfltr = await crossfilter.select(Field.obs, "louvain", {
fetch.once(serverMocks.dataframeResponse(["louvain"], [obsLouvain]));
const xfltr = await crossfilter.select("obs", "louvain", {
mode: "exact",
values: "B cells",
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
expect((fetch as any).mock.calls).toHaveLength(1);
expect(fetch.mock.calls).toHaveLength(1);
expect(xfltr.obsCrossfilter.hasDimension("obs/louvain")).toBeTruthy();
expect(xfltr.obsCrossfilter.all()).toBe(xfltr.annoMatrix._cache.obs);
expect(xfltr.countSelected()).toEqual(
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,6 @@
export const baseDataURL = "https://a.fake.url/api/v0.2";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(window as any).CELLXGENE = {
window.CELLXGENE = {
API: {
prefix: baseDataURL,
version: "v0.2/",
@@ -0,0 +1,211 @@
import { schema } from "./schema";
import { Dataframe, KeyIndex } from "../../../../src/util/dataframe";
import { encodeMatrixFBS } from "../../../../src/util/stateManager/matrix";
const indexedSchema = {
obsByName: Object.fromEntries(
schema.schema.annotations.obs.columns.map((v) => [v.name, v]) ?? []
),
varByName: Object.fromEntries(
schema.schema.annotations.var.columns.map((v) => [v.name, v]) ?? []
),
embByName: Object.fromEntries(
schema.schema.layout.obs.map((v) => [v.name, v]) ?? []
),
};
function makeMockColumn(s, length) {
const { type } = s;
switch (type) {
case "int32":
return new Int32Array(length).fill(Math.floor(99 * Math.random()));
case "string":
return new Array(length).fill("test");
case "float32":
return new Float32Array(length).fill(99 * Math.random());
case "boolean":
return new Array(length).fill(false);
case "categorical":
return new Array(length).fill(s.categories[0]);
default:
throw new Error("unkonwn type");
}
}
function getEncodedDataframe(colNames, length, colSchemas) {
const colIndex = new KeyIndex(colNames);
const columns = colSchemas.map((s) => makeMockColumn(s, length));
const df = new Dataframe([length, colNames.length], columns, null, colIndex);
const body = encodeMatrixFBS(df);
return body;
}
export function dataframeResponse(colNames, columns) {
const colIndex = new KeyIndex(colNames);
const df = new Dataframe(
[columns[0].length, colNames.length],
columns,
null,
colIndex
);
const body = encodeMatrixFBS(df);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return () => Promise.resolve({ body, init: { status: 200, headers } });
}
function annotationObsResponse(request) {
const url = new URL(request.url);
const params = Array.from(url.searchParams.entries());
const names = params
.filter(([k]) => k === "annotation-name")
.map(([, v]) => v);
if (!names.every((n) => indexedSchema.obsByName[n])) {
return Promise.reject(new Error("bad obs annotation name in URL"));
}
const colSchemas = names.map((n) => indexedSchema.obsByName[n]);
const body = getEncodedDataframe(
names,
schema.schema.dataframe.nObs,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
function annotationVarResponse(request) {
const url = new URL(request.url);
const params = Array.from(url.searchParams.entries());
const names = params
.filter(([k]) => k === "annotation-name")
.map(([, v]) => v);
if (!names.every((n) => indexedSchema.varByName[n])) {
return Promise.reject(new Error("bad var annotation name in URL"));
}
const colSchemas = names.map((n) => indexedSchema.varByName[n]);
const body = getEncodedDataframe(
names,
schema.schema.dataframe.nVar,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
function layoutObsResponse(request) {
const url = new URL(request.url);
const params = Array.from(url.searchParams.entries());
const names = params.filter(([k]) => k === "layout-name").map(([, v]) => v);
if (!names.every((n) => indexedSchema.embByName[n])) {
return Promise.reject(new Error("bad layout name in URL"));
}
const dims = names.map((n) => indexedSchema.embByName[n].dims).flat();
const colSchemas = names
.map((n) => [indexedSchema.embByName[n], indexedSchema.embByName[n]])
.flat();
const body = getEncodedDataframe(
dims,
schema.schema.dataframe.nObs,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
function dataVarResponse(request) {
const url = new URL(request.url);
const params = Array.from(url.searchParams.entries());
const colNames = params.map((v) => `${v[0]}/${v[1]}`);
const colSchemas = colNames.map(() => schema.schema.dataframe);
const body = getEncodedDataframe(
colNames,
schema.schema.dataframe.nObs,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
export function responder(request) {
const url = new URL(request.url);
const { pathname } = url;
if (pathname.endsWith("/annotations/obs")) {
return annotationObsResponse(request);
}
if (pathname.endsWith("/annotations/var")) {
return annotationVarResponse(request);
}
if (pathname.endsWith("/layout/obs")) {
return layoutObsResponse(request);
}
if (pathname.endsWith("/data/var")) {
return dataVarResponse(request);
}
return Promise.reject(new Error("bad URL"));
}
export function withExpected(expectedURL, expectedParams) {
/*
Do some additional error checking
*/
return (request) => {
// if URL is bogus, reject the promise
const url = new URL(request.url);
if (!url.pathname.endsWith(expectedURL)) {
return Promise.reject(new Error("Unexpected URL!"));
}
const params = Array.from(url.searchParams.entries()).sort(
(a, b) => a[0] < b[0]
);
expectedParams = expectedParams.slice().sort((a, b) => a[0] < b[0]);
if (
params.length !== expectedParams.length ||
!params.every(
(p, i) => p[0] === expectedParams[i][0] && p[1] === expectedParams[i][1]
)
) {
return Promise.reject(new Error("unexpected name requested in URL"));
}
return responder(request);
};
}
export function annotationsObs(names) {
return withExpected(
"/annotations/obs",
names.map((name) => ["annotation-name", name])
);
}
@@ -1,249 +0,0 @@
import { schema } from "./schema";
import { Dataframe, KeyIndex } from "../../../../src/util/dataframe";
import { encodeMatrixFBS } from "../../../../src/util/stateManager/matrix";
const indexedSchema = {
obsByName: Object.fromEntries(
schema.schema.annotations.obs.columns.map((v) => [v.name, v]) ?? []
),
varByName: Object.fromEntries(
schema.schema.annotations.var.columns.map((v) => [v.name, v]) ?? []
),
embByName: Object.fromEntries(
schema.schema.layout.obs.map((v) => [v.name, v]) ?? []
),
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function makeMockColumn(s: any, length: any) {
const { type } = s;
switch (type) {
case "int32":
return new Int32Array(length).fill(Math.floor(99 * Math.random()));
case "string":
return new Array(length).fill("test");
case "float32":
return new Float32Array(length).fill(99 * Math.random());
case "boolean":
return new Array(length).fill(false);
case "categorical":
return new Array(length).fill(s.categories[0]);
default:
throw new Error("unknown type");
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function getEncodedDataframe(colNames: any, length: any, colSchemas: any) {
const colIndex = new KeyIndex(colNames);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const columns = colSchemas.map((s: any) => makeMockColumn(s, length));
const df = new Dataframe([length, colNames.length], columns, null, colIndex);
const body = encodeMatrixFBS(df);
return body;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function dataframeResponse(colNames: any, columns: any) {
const colIndex = new KeyIndex(colNames);
const df = new Dataframe(
[columns[0].length, colNames.length],
columns,
null,
colIndex
);
const body = encodeMatrixFBS(df);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return () => Promise.resolve({ body, init: { status: 200, headers } });
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function annotationObsResponse(request: any) {
const url = new URL(request.url);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const params = Array.from((url.searchParams as any).entries());
const names = params
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
.filter(([k]) => k === "annotation-name")
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '([, v]: [any, any]) => any' is n... Remove this comment to see the full error message
.map(([, v]) => v);
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
if (!names.every((n) => indexedSchema.obsByName[n])) {
return Promise.reject(new Error("bad obs annotation name in URL"));
}
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
const colSchemas = names.map((n) => indexedSchema.obsByName[n]);
const body = getEncodedDataframe(
names,
schema.schema.dataframe.nObs,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function annotationVarResponse(request: any) {
const url = new URL(request.url);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const params = Array.from((url.searchParams as any).entries());
const names = params
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
.filter(([k]) => k === "annotation-name")
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '([, v]: [any, any]) => any' is n... Remove this comment to see the full error message
.map(([, v]) => v);
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
if (!names.every((n) => indexedSchema.varByName[n])) {
return Promise.reject(new Error("bad var annotation name in URL"));
}
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
const colSchemas = names.map((n) => indexedSchema.varByName[n]);
const body = getEncodedDataframe(
names,
schema.schema.dataframe.nVar,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function layoutObsResponse(request: any) {
const url = new URL(request.url);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const params = Array.from((url.searchParams as any).entries());
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
const names = params.filter(([k]) => k === "layout-name").map(([, v]) => v);
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
if (!names.every((n) => indexedSchema.embByName[n])) {
return Promise.reject(new Error("bad layout name in URL"));
}
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
const dims = names.map((n) => indexedSchema.embByName[n].dims).flat();
const colSchemas = names
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
.map((n) => [indexedSchema.embByName[n], indexedSchema.embByName[n]])
.flat();
const body = getEncodedDataframe(
dims,
schema.schema.dataframe.nObs,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function dataVarResponse(request: any) {
const url = new URL(request.url);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const params = Array.from((url.searchParams as any).entries());
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const colNames = params.map((v) => `${(v as any)[0]}/${(v as any)[1]}`);
const colSchemas = colNames.map(() => schema.schema.dataframe);
const body = getEncodedDataframe(
colNames,
schema.schema.dataframe.nObs,
colSchemas
);
const headers = new Headers({
"Content-Type": "application/octet-stream",
});
return Promise.resolve({
body,
init: { status: 200, headers },
});
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function responder(request: any) {
const url = new URL(request.url);
const { pathname } = url;
if (pathname.endsWith("/annotations/obs")) {
return annotationObsResponse(request);
}
if (pathname.endsWith("/annotations/var")) {
return annotationVarResponse(request);
}
if (pathname.endsWith("/layout/obs")) {
return layoutObsResponse(request);
}
if (pathname.endsWith("/data/var")) {
return dataVarResponse(request);
}
return Promise.reject(new Error("bad URL"));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function withExpected(expectedURL: any, expectedParams: any) {
/*
Do some additional error checking
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
return (request: any) => {
// if URL is bogus, reject the promise
const url = new URL(request.url);
if (!url.pathname.endsWith(expectedURL)) {
return Promise.reject(new Error("Unexpected URL!"));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const params = Array.from((url.searchParams as any).entries()).sort(
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '(a: unknown, b: unknown) => bool... Remove this comment to see the full error message
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(a, b) => (a as any)[0] < (b as any)[0]
);
expectedParams = expectedParams
.slice() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.sort((a: any, b: any) => a[0] < b[0]);
if (
params.length !== expectedParams.length ||
!params.every(
(p, i) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(p as any)[0] === expectedParams[i][0] && // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(p as any)[1] === expectedParams[i][1]
)
) {
return Promise.reject(new Error("unexpected name requested in URL"));
}
return responder(request);
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function annotationsObs(names: any) {
return withExpected(
"/annotations/obs",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
names.map((name: any) => ["annotation-name", name])
);
}
@@ -1,6 +1,4 @@
import { RawSchema } from "../../../../src/common/types/schema";
export const schema: { schema: RawSchema } = {
export const schema = {
schema: {
annotations: {
obs: {
File diff suppressed because it is too large Load Diff
@@ -4,34 +4,13 @@ import {
_whereCacheCreate,
_whereCacheMerge,
} from "../../../src/annoMatrix/whereCache";
import { Field, Schema } from "../../../src/common/types/schema";
import { Query } from "../../../src/annoMatrix/query";
const schema = {} as Schema;
const schema = {};
describe("whereCache", () => {
test("whereCacheGet - where query, missing cache values", () => {
expect(
_whereCacheGet({}, schema, Field.X, {
where: {
field: Field.var,
column: "foo",
value: "bar",
},
})
).toEqual([undefined]);
expect(
_whereCacheGet({}, schema, Field.X, {
summarize: {
method: "mean",
field: Field.var,
column: "foo",
values: ["bar"],
},
})
).toEqual([undefined]);
expect(
_whereCacheGet({ where: { X: {} } }, schema, Field.X, {
_whereCacheGet({}, schema, "X", {
where: {
field: "var",
column: "foo",
@@ -40,7 +19,25 @@ describe("whereCache", () => {
})
).toEqual([undefined]);
expect(
_whereCacheGet({ where: { X: { var: new Map() } } }, schema, Field.X, {
_whereCacheGet({}, schema, "X", {
summarize: {
field: "var",
column: "foo",
values: ["bar"],
},
})
).toEqual([undefined]);
expect(
_whereCacheGet({ where: { X: {} } }, schema, "X", {
where: {
field: "var",
column: "foo",
value: "bar",
},
})
).toEqual([undefined]);
expect(
_whereCacheGet({ where: { X: { var: new Map() } } }, schema, "X", {
where: {
field: "var",
column: "foo",
@@ -52,7 +49,7 @@ describe("whereCache", () => {
_whereCacheGet(
{ where: { X: { var: new Map([["foo", new Map()]]) } } },
schema,
Field.X,
"X",
{
where: {
field: "var",
@@ -66,7 +63,7 @@ describe("whereCache", () => {
test("whereCacheGet - summarize query, missing cache values", () => {
expect(
_whereCacheGet({}, schema, Field.X, {
_whereCacheGet({}, schema, "X", {
summarize: {
method: "mean",
field: "var",
@@ -79,7 +76,7 @@ describe("whereCache", () => {
_whereCacheGet(
{ summarize: { X: { mean: { var: new Map() } } } },
schema,
Field.X,
"X",
{
summarize: {
method: "mean",
@@ -125,7 +122,7 @@ describe("whereCache", () => {
};
expect(
_whereCacheGet(whereCache, schema, Field.X, {
_whereCacheGet(whereCache, schema, "X", {
where: {
field: "var",
column: "foo",
@@ -134,7 +131,7 @@ describe("whereCache", () => {
})
).toEqual([0]);
expect(
_whereCacheGet(whereCache, schema, Field.X, {
_whereCacheGet(whereCache, schema, "X", {
summarize: {
method: "mean",
field: "var",
@@ -144,7 +141,7 @@ describe("whereCache", () => {
})
).toEqual([0]);
expect(
_whereCacheGet(whereCache, schema, Field.X, {
_whereCacheGet(whereCache, schema, "X", {
where: {
field: "var",
column: "foo",
@@ -153,7 +150,7 @@ describe("whereCache", () => {
})
).toEqual([1, 2]);
expect(
_whereCacheGet(whereCache, schema, Field.X, {
_whereCacheGet(whereCache, schema, "X", {
summarize: {
method: "mean",
field: "var",
@@ -162,12 +159,9 @@ describe("whereCache", () => {
},
})
).toEqual([1, 2]);
expect(_whereCacheGet(whereCache, schema, "Y", {})).toEqual([undefined]);
expect(
// Force invalid field value Y
_whereCacheGet(whereCache, schema, "Y" as Field, {} as Query)
).toEqual([undefined]);
expect(
_whereCacheGet(whereCache, schema, Field.X, {
_whereCacheGet(whereCache, schema, "X", {
where: {
field: "whoknows",
column: "whatever",
@@ -176,7 +170,7 @@ describe("whereCache", () => {
})
).toEqual([undefined]);
expect(
_whereCacheGet(whereCache, schema, Field.X, {
_whereCacheGet(whereCache, schema, "X", {
where: {
field: "var",
column: "whatever",
@@ -185,7 +179,7 @@ describe("whereCache", () => {
})
).toEqual([undefined]);
expect(
_whereCacheGet(whereCache, schema, Field.X, {
_whereCacheGet(whereCache, schema, "X", {
where: {
field: "var",
column: "foo",
@@ -204,7 +198,7 @@ describe("whereCache", () => {
},
};
const wc = _whereCacheCreate(
Field.obs,
"field",
{
where: {
field: "queryField",
@@ -218,27 +212,18 @@ describe("whereCache", () => {
expect(wc).toEqual(
expect.objectContaining({
where: {
[Field.obs]: {
field: {
queryField: expect.any(Map),
},
},
})
);
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
expect((wc.where as any)[Field.obs].queryField.has("queryColumn")).toEqual(true);
expect(wc.where.field.queryField.has("queryColumn")).toEqual(true);
expect(wc.where.field.queryField.get("queryColumn")).toBeInstanceOf(Map);
expect(
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(wc.where as any)[Field.obs].queryField.get("queryColumn")
).toBeInstanceOf(Map);
expect(
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(wc.where as any)[Field.obs].queryField.get("queryColumn").has("queryValue")
wc.where.field.queryField.get("queryColumn").has("queryValue")
).toEqual(true);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
expect(_whereCacheGet(wc!, schema, Field.obs, query)).toEqual([0, 1, 2]);
expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]);
});
test("whereCacheCreate, summarize query", () => {
@@ -250,14 +235,12 @@ describe("whereCache", () => {
values: ["queryValue"],
},
};
const wc = _whereCacheCreate(Field.obs, query, [0, 1, 2]);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
expect(_whereCacheGet(wc!, schema, Field.obs, query)).toEqual([0, 1, 2]);
const wc = _whereCacheCreate("field", query, [0, 1, 2]);
expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]);
});
test("whereCacheCreate, unknown query type", () => {
// @ts-expect-error --- force invalid query {foobar: true}
expect(_whereCacheCreate(Field.obs, { foobar: true }, [1])).toEqual({});
expect(_whereCacheCreate("field", { foobar: true }, [1])).toEqual({});
});
test("whereCacheMerge, where queries", () => {
@@ -265,20 +248,19 @@ describe("whereCache", () => {
// remember, will mutate dst
const src = _whereCacheCreate(
Field.obs,
"field",
{ where: { field: "queryField", column: "queryColumn", value: "foo" } },
["foo"]
);
const dst1 = _whereCacheCreate(
Field.obs,
"field",
{ where: { field: "queryField", column: "queryColumn", value: "bar" } },
["dst1"]
);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert dst1 and src to be non-null
wc = _whereCacheMerge(dst1!, src!);
wc = _whereCacheMerge(dst1, src);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
where: {
field: "queryField",
column: "queryColumn",
@@ -287,7 +269,7 @@ describe("whereCache", () => {
})
).toEqual(["foo"]);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
where: {
field: "queryField",
column: "queryColumn",
@@ -297,14 +279,13 @@ describe("whereCache", () => {
).toEqual(["dst1"]);
const dst2 = _whereCacheCreate(
Field.obs,
"field",
{ where: { field: "queryField", column: "queryColumn", value: "bar" } },
["dst2"]
);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert dst2m, dst1 and src to be non-null
wc = _whereCacheMerge(dst2!, dst1!, src!);
wc = _whereCacheMerge(dst2, dst1, src);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
where: {
field: "queryField",
column: "queryColumn",
@@ -313,7 +294,7 @@ describe("whereCache", () => {
})
).toEqual(["foo"]);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
where: {
field: "queryField",
column: "queryColumn",
@@ -322,20 +303,17 @@ describe("whereCache", () => {
})
).toEqual(["dst1"]);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert src to be non-null
wc = _whereCacheMerge({}, src!);
wc = _whereCacheMerge({}, src);
expect(wc).toEqual(src);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert src to be non-null
wc = _whereCacheMerge({ where: { obs: { queryField: new Map() } } }, src!);
wc = _whereCacheMerge({ where: { field: { queryField: new Map() } } }, src);
expect(wc).toEqual(src);
});
test("whereCacheMerge, mixed queries", () => {
const wc = _whereCacheMerge(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
_whereCacheCreate(
Field.obs,
"field",
{
where: {
field: "queryField",
@@ -344,10 +322,9 @@ describe("whereCache", () => {
},
},
["a"]
)!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
),
_whereCacheCreate(
Field.obs,
"field",
{
summarize: {
method: "mean",
@@ -357,11 +334,11 @@ describe("whereCache", () => {
},
},
["b"]
)!
)
);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
where: {
field: "queryField",
column: "queryColumn",
@@ -371,7 +348,7 @@ describe("whereCache", () => {
).toEqual(["a"]);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
summarize: {
method: "mean",
field: "queryField",
@@ -382,7 +359,7 @@ describe("whereCache", () => {
).toEqual(["b"]);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
where: {
field: "queryField",
column: "queryColumn",
@@ -392,7 +369,7 @@ describe("whereCache", () => {
).toEqual([undefined]);
expect(
_whereCacheGet(wc, schema, Field.obs, {
_whereCacheGet(wc, schema, "field", {
summarize: {
method: "no-such-method",
field: "queryField",
@@ -1,19 +1,16 @@
import cloneDeep from "lodash.clonedeep";
import { NumberArray } from "../../src/common/types/arraytypes";
import calcCentroid from "../../src/util/centroid";
import quantile from "../../src/util/quantile";
import { matrixFBSToDataframe } from "../../src/util/stateManager/matrix";
import * as REST from "./stateManager/sampleResponses";
import { indexEntireSchema } from "../../src/util/stateManager/schemaHelpers";
import { normalizeWritableCategoricalSchema } from "../../src/annoMatrix/normalize";
import { Dataframe } from "../../src/util/dataframe";
describe("centroid", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let schema: any;
let obsAnnotations: Dataframe;
let obsLayout: Dataframe;
let schema;
let obsAnnotations;
let obsLayout;
beforeAll(() => {
schema = indexEntireSchema(cloneDeep(REST.schema.schema));
@@ -43,12 +40,11 @@ describe("centroid", () => {
// This expected result assumes that all cells belong in all categorical values inside of sample response
const expectedResult = [
quantile([0.5], obsLayout.col("umap_0").asArray() as NumberArray)[0],
quantile([0.5], obsLayout.col("umap_1").asArray() as NumberArray)[0],
quantile([0.5], obsLayout.col("umap_0").asArray())[0],
quantile([0.5], obsLayout.col("umap_1").asArray())[0],
];
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
centroidResult.forEach((coordinate: any) => {
centroidResult.forEach((coordinate) => {
expect(coordinate).toEqual(expectedResult);
});
});
@@ -68,12 +64,11 @@ describe("centroid", () => {
// This expected result assumes that all cells belong in all categorical values inside of sample response
const expectedResult = [
quantile([0.5], obsLayout.col("umap_0").asArray() as NumberArray)[0],
quantile([0.5], obsLayout.col("umap_1").asArray() as NumberArray)[0],
quantile([0.5], obsLayout.col("umap_0").asArray())[0],
quantile([0.5], obsLayout.col("umap_1").asArray())[0],
];
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
centroidResult.forEach((coordinate: any) => {
centroidResult.forEach((coordinate) => {
expect(coordinate).toEqual(expectedResult);
});
});
@@ -6,8 +6,7 @@ describe("dataframe constructor", () => {
expect(df).toBeDefined();
expect(df.dims).toEqual([0, 0]);
expect(df).toHaveLength(0);
expect(df.ihasCol(0)).toBeFalsy();
expect(() => df.icol(0)).toThrow(RangeError);
expect(df.icol(0)).not.toBeDefined();
});
test("create with default indices", () => {
@@ -24,13 +23,6 @@ describe("dataframe constructor", () => {
expect(df.at(2, 1)).toEqual(1);
expect(df.iat(0, 0)).toEqual(0);
expect(df.iat(2, 1)).toEqual(1);
expect(Array.from(df.rowIndex.labels())).toEqual(
df.rowIndex.getLabels(df.rowIndex.getOffsets(df.rowIndex.labels()))
);
expect(Array.from(df.colIndex.labels())).toEqual(
df.colIndex.getLabels(df.colIndex.getOffsets(df.colIndex.labels()))
);
});
test("create with labelled indices", () => {
@@ -129,9 +121,7 @@ describe("simple data access", () => {
expect(df.has(3, "foo")).toBeFalsy();
expect(df.has(-1, "numbers")).toBeFalsy();
expect(df.has(-1, -1)).toBeFalsy();
expect(
df.has(null as unknown as number, null as unknown as number)
).toBeFalsy();
expect(df.has(null, null)).toBeFalsy();
expect(df.has(0, "foo")).toBeFalsy();
expect(df.has(99, "numbers")).toBeFalsy();
expect(df.has(99, "foo")).toBeFalsy();
@@ -259,12 +249,11 @@ describe("dataframe subsetting", () => {
const df = sourceDf.subset(
null,
["int32", "float32"],
new Dataframe.DenseInt32Index([2, 1])
new Dataframe.DenseInt32Index([3, 2, 1])
);
expect(df.dims).toEqual([2, 2]);
expect(df.colIndex).toBeInstanceOf(Dataframe.KeyIndex);
expect(df.rowIndex).toBeInstanceOf(Dataframe.DenseInt32Index);
expect(df.at(2, "int32")).toEqual(df.iat(0, 0));
expect(df.at(3, "int32")).toEqual(df.iat(0, 0));
});
test("withRowIndex error checks", () => {
@@ -843,7 +832,7 @@ describe("dataframe factories", () => {
});
describe("dataframe col", () => {
let df: Dataframe.Dataframe;
let df = null;
beforeEach(() => {
df = new Dataframe.Dataframe(
[2, 2],
@@ -860,8 +849,8 @@ describe("dataframe col", () => {
expect(df).toBeDefined();
expect(df.col("A")).toBe(df.icol(0));
expect(df.col("B")).toBe(df.icol(1));
expect(() => df.col("undefined")).toThrow(RangeError);
expect(() => df.icol("undefined" as unknown as number)).toThrow(RangeError);
expect(df.col("undefined")).toBeUndefined();
expect(df.icol("undefined")).toBeUndefined();
const colA = df.col("A");
expect(colA).toBeInstanceOf(Function);
@@ -915,13 +904,13 @@ describe("dataframe col", () => {
expect(df.col("A").indexOf(true)).toEqual(0);
expect(df.col("A").indexOf(false)).toEqual(1);
expect(df.col("A").indexOf(99)).toBeUndefined();
expect(df.col("A").indexOf(undefined as unknown as number)).toBeUndefined();
expect(df.col("A").indexOf(undefined)).toBeUndefined();
expect(df.col("A").indexOf(1)).toBeUndefined();
expect(df.col("B").indexOf(1)).toEqual(0);
expect(df.col("B").indexOf(0)).toEqual(1);
expect(df.col("B").indexOf(99)).toBeUndefined();
expect(df.col("B").indexOf(undefined as unknown as number)).toBeUndefined();
expect(df.col("B").indexOf(undefined)).toBeUndefined();
expect(df.col("B").indexOf(true)).toBeUndefined();
});
});
@@ -964,7 +953,7 @@ describe("label indexing", () => {
test("offsets", () => {
expect(idx.getOffset(1)).toEqual(1);
expect(idx.getOffsets([1, 3])).toEqual(new Int32Array([1, 3]));
expect(idx.getOffsets([1, 3])).toEqual([1, 3]);
});
test("subset", () => {
@@ -1042,7 +1031,7 @@ describe("label indexing", () => {
false,
])
.labels()
).toEqual([]);
).toEqual(new Int32Array([]));
expect(
idx
.isubsetMask([
@@ -1136,14 +1125,16 @@ describe("label indexing", () => {
expect(idx.labels()).toEqual(new Int32Array([99, 1002, 48, 0, 22]));
expect(idx.size()).toEqual(5);
expect(idx.getLabel(0)).toEqual(99);
expect(idx.getLabels(new Int32Array([2, 4]))).toEqual([48, 22]);
expect(idx.getLabels(new Int32Array([2, 4]))).toEqual(
new Int32Array([48, 22])
);
expect(idx.getLabels([2, 4])).toEqual([48, 22]);
});
test("offsets", () => {
expect(idx.getOffset(1002)).toEqual(1);
expect(idx.getOffset(0)).toEqual(3);
expect(idx.getOffsets([0, 48])).toEqual(new Int32Array([3, 2]));
expect(idx.getOffsets([0, 48])).toEqual([3, 2]);
});
test("subset", () => {
@@ -1170,7 +1161,7 @@ describe("label indexing", () => {
);
expect(
idx.isubsetMask([false, false, false, false, false]).labels()
).toEqual([]);
).toEqual(new Int32Array([]));
expect(idx.isubsetMask([true, true, false, true, true]).labels()).toEqual(
new Int32Array([99, 1002, 0, 22])
);
@@ -1202,7 +1193,6 @@ describe("label indexing", () => {
test("create", () => {
expect(Dataframe.isLabelIndex(idx)).toBeTruthy();
expect(() => new Dataframe.KeyIndex(["dup", "dup"])).toThrow(Error);
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
expect(new Dataframe.KeyIndex().size()).toEqual(0);
});
@@ -1272,67 +1262,59 @@ describe("corner cases", () => {
const idx = new Dataframe.IdentityInt32Index(10);
expect(idx.getOffset(0)).toBe(0);
expect(idx.getOffset(9)).toBe(9);
expect(idx.getOffset(10)).toBe(-1);
expect(idx.getOffset(-1)).toBe(-1);
expect(idx.getOffset("sort")).toBe(-1);
expect(idx.getOffset("length")).toBe(-1);
expect(idx.getOffset(true as unknown as string)).toBe(-1);
expect(idx.getOffset(0.001)).toBe(-1);
expect(idx.getOffset({} as unknown as string)).toBe(-1);
expect(idx.getOffset([] as unknown as string)).toBe(-1);
expect(idx.getOffset(new Float32Array() as unknown as string)).toBe(-1);
expect(idx.getOffset("__proto__")).toBe(-1);
expect(idx.getOffset(10)).toBeUndefined();
expect(idx.getOffset(-1)).toBeUndefined();
expect(idx.getOffset("sort")).toBeUndefined();
expect(idx.getOffset("length")).toBeUndefined();
expect(idx.getOffset(true)).toBeUndefined();
expect(idx.getOffset(0.001)).toBeUndefined();
expect(idx.getOffset({})).toBeUndefined();
expect(idx.getOffset([])).toBeUndefined();
expect(idx.getOffset(new Float32Array())).toBeUndefined();
expect(idx.getOffset("__proto__")).toBeUndefined();
expect(idx.getLabel(0)).toBe(0);
expect(idx.getLabel(9)).toBe(9);
expect(idx.getLabel(10)).toBeUndefined();
expect(idx.getLabel(-1)).toBeUndefined();
expect(idx.getLabel("sort" as unknown as number)).toBeUndefined();
expect(idx.getLabel("length" as unknown as number)).toBeUndefined();
expect(idx.getLabel(true as unknown as number)).toBeUndefined();
expect(idx.getLabel("sort")).toBeUndefined();
expect(idx.getLabel("length")).toBeUndefined();
expect(idx.getLabel(true)).toBeUndefined();
expect(idx.getLabel(0.001)).toBeUndefined();
expect(idx.getLabel({} as unknown as number)).toBeUndefined();
expect(idx.getLabel([] as unknown as number)).toBeUndefined();
expect(
idx.getLabel(new Float32Array() as unknown as number)
).toBeUndefined();
expect(idx.getLabel("__proto__" as unknown as number)).toBeUndefined();
expect(idx.getLabel({})).toBeUndefined();
expect(idx.getLabel([])).toBeUndefined();
expect(idx.getLabel(new Float32Array())).toBeUndefined();
expect(idx.getLabel("__proto__")).toBeUndefined();
});
test("dense integer index rejects non-integer labels", () => {
const idx = new Dataframe.DenseInt32Index([-10, 0, 3, 9, 10]);
expect(idx.getOffset(-10)).toBe(0);
expect(idx.getOffset(0)).toBe(1);
expect(idx.getOffset(3)).toBe(2);
expect(idx.getOffset(9)).toBe(3);
expect(idx.getOffset(10)).toBe(4);
expect(idx.getOffset(1)).toBe(-1);
expect(idx.getOffset(11)).toBe(-1);
expect(idx.getOffset(-1)).toBe(-1);
expect(idx.getOffset("sort")).toBe(-1);
expect(idx.getOffset("length")).toBe(-1);
expect(idx.getOffset(true as unknown as string)).toBe(-1);
expect(idx.getOffset(0.001)).toBe(-1);
expect(idx.getOffset({} as unknown as string)).toBe(-1);
expect(idx.getOffset([] as unknown as string)).toBe(-1);
expect(idx.getOffset(new Float32Array() as unknown as string)).toBe(-1);
expect(idx.getOffset("__proto__")).toBe(-1);
expect(idx.getOffset(1)).toBeUndefined();
expect(idx.getOffset(11)).toBeUndefined();
expect(idx.getOffset(-1)).toBeUndefined();
expect(idx.getOffset("sort")).toBeUndefined();
expect(idx.getOffset("length")).toBeUndefined();
expect(idx.getOffset(true)).toBeUndefined();
expect(idx.getOffset(0.001)).toBeUndefined();
expect(idx.getOffset({})).toBeUndefined();
expect(idx.getOffset([])).toBeUndefined();
expect(idx.getOffset(new Float32Array())).toBeUndefined();
expect(idx.getOffset("__proto__")).toBeUndefined();
expect(idx.getLabel(0)).toBe(-10);
expect(idx.getLabel(4)).toBe(10);
expect(idx.getLabel(10)).toBeUndefined();
expect(idx.getLabel(-1)).toBeUndefined();
expect(idx.getLabel("sort" as unknown as number)).toBeUndefined();
expect(idx.getLabel("length" as unknown as number)).toBeUndefined();
expect(idx.getLabel(true as unknown as number)).toBeUndefined();
expect(idx.getLabel("sort")).toBeUndefined();
expect(idx.getLabel("length")).toBeUndefined();
expect(idx.getLabel(true)).toBeUndefined();
expect(idx.getLabel(0.001)).toBeUndefined();
expect(idx.getLabel({} as unknown as number)).toBeUndefined();
expect(idx.getLabel([] as unknown as number)).toBeUndefined();
expect(
idx.getLabel(new Float32Array() as unknown as number)
).toBeUndefined();
expect(idx.getLabel("__proto__" as unknown as number)).toBeUndefined();
expect(idx.getLabel({})).toBeUndefined();
expect(idx.getLabel([])).toBeUndefined();
expect(idx.getLabel(new Float32Array())).toBeUndefined();
expect(idx.getLabel("__proto__")).toBeUndefined();
});
test("Empty dataframe rejects bogus labels", () => {
@@ -1340,55 +1322,39 @@ describe("corner cases", () => {
expect(df.hasCol("sort")).toBeFalsy();
expect(df.hasCol(0)).toBeFalsy();
expect(df.hasCol(true as unknown as number)).toBeFalsy();
expect(df.hasCol(false as unknown as number)).toBeFalsy();
expect(df.hasCol([] as unknown as number)).toBeFalsy();
expect(df.hasCol({} as unknown as number)).toBeFalsy();
expect(df.hasCol(null as unknown as number)).toBeFalsy();
expect(df.hasCol(undefined as unknown as number)).toBeFalsy();
expect(df.hasCol(true)).toBeFalsy();
expect(df.hasCol(false)).toBeFalsy();
expect(df.hasCol([])).toBeFalsy();
expect(df.hasCol({})).toBeFalsy();
expect(df.hasCol(null)).toBeFalsy();
expect(df.hasCol(undefined)).toBeFalsy();
expect(() => df.col("sort")).toThrow(RangeError);
expect(() => df.col(0)).toThrow(RangeError);
expect(() => df.col(true as unknown as string)).toThrow(RangeError);
expect(() => df.col(false as unknown as string)).toThrow(RangeError);
expect(() => df.col([] as unknown as string)).toThrow(RangeError);
expect(() => df.col({} as unknown as string)).toThrow(RangeError);
expect(() => df.col(null as unknown as string)).toThrow(RangeError);
expect(() => df.col(undefined as unknown as string)).toThrow(RangeError);
expect(df.col("sort")).toBeUndefined();
expect(df.col(0)).toBeUndefined();
expect(df.col(true)).toBeUndefined();
expect(df.col(false)).toBeUndefined();
expect(df.col([])).toBeUndefined();
expect(df.col({})).toBeUndefined();
expect(df.col(null)).toBeUndefined();
expect(df.col(undefined)).toBeUndefined();
expect(() => df.icol("sort" as unknown as number)).toThrow(RangeError);
expect(() => df.icol(0)).toThrow(RangeError);
expect(() => df.icol(true as unknown as number)).toThrow(RangeError);
expect(() => df.icol(false as unknown as number)).toThrow(RangeError);
expect(() => df.icol([] as unknown as number)).toThrow(RangeError);
expect(() => df.icol({} as unknown as number)).toThrow(RangeError);
expect(() => df.icol(null as unknown as number)).toThrow(RangeError);
expect(() => df.icol(undefined as unknown as number)).toThrow(RangeError);
expect(df.icol("sort")).toBeUndefined();
expect(df.icol(0)).toBeUndefined();
expect(df.icol(true)).toBeUndefined();
expect(df.icol(false)).toBeUndefined();
expect(df.icol([])).toBeUndefined();
expect(df.icol({})).toBeUndefined();
expect(df.icol(null)).toBeUndefined();
expect(df.icol(undefined)).toBeUndefined();
expect(
df.ihas("sort" as unknown as number, "length" as unknown as number)
).toBeFalsy();
expect(
df.ihas("0" as unknown as number, "0" as unknown as number)
).toBeFalsy();
expect(
df.ihas("" as unknown as number, "" as unknown as number)
).toBeFalsy();
expect(
df.ihas(null as unknown as number, null as unknown as number)
).toBeFalsy();
expect(
df.ihas(undefined as unknown as number, undefined as unknown as number)
).toBeFalsy();
expect(
df.ihas(true as unknown as number, true as unknown as number)
).toBeFalsy();
expect(
df.ihas([] as unknown as number, [] as unknown as number)
).toBeFalsy();
expect(
df.ihas({} as unknown as number, {} as unknown as number)
).toBeFalsy();
expect(df.ihas("sort", "length")).toBeFalsy();
expect(df.ihas("0", "0")).toBeFalsy();
expect(df.ihas("", "")).toBeFalsy();
expect(df.ihas(null, null)).toBeFalsy();
expect(df.ihas(undefined, undefined)).toBeFalsy();
expect(df.ihas(true, true)).toBeFalsy();
expect(df.ihas([], [])).toBeFalsy();
expect(df.ihas({}, {})).toBeFalsy();
});
test("Dataframe rejects bogus labels", () => {
@@ -1405,58 +1371,51 @@ describe("corner cases", () => {
expect(df.hasCol("sort")).toBeFalsy();
expect(df.hasCol("__proto__")).toBeFalsy();
expect(df.hasCol(0)).toBeFalsy();
expect(df.hasCol(true as unknown as string)).toBeFalsy();
expect(df.hasCol(false as unknown as string)).toBeFalsy();
expect(df.hasCol([] as unknown as string)).toBeFalsy();
expect(df.hasCol({} as unknown as string)).toBeFalsy();
expect(df.hasCol(null as unknown as string)).toBeFalsy();
expect(df.hasCol(undefined as unknown as string)).toBeFalsy();
expect(df.hasCol(true)).toBeFalsy();
expect(df.hasCol(false)).toBeFalsy();
expect(df.hasCol([])).toBeFalsy();
expect(df.hasCol({})).toBeFalsy();
expect(df.hasCol(null)).toBeFalsy();
expect(df.hasCol(undefined)).toBeFalsy();
expect(() => df.col("sort")).toThrow(RangeError);
expect(() => df.col("__proto__")).toThrow(RangeError);
expect(() => df.col(0)).toThrow(RangeError);
expect(() => df.col(true as unknown as string)).toThrow(RangeError);
expect(() => df.col(false as unknown as string)).toThrow(RangeError);
expect(() => df.col([] as unknown as string)).toThrow(RangeError);
expect(() => df.col({} as unknown as string)).toThrow(RangeError);
expect(() => df.col(null as unknown as string)).toThrow(RangeError);
expect(() => df.col(undefined as unknown as string)).toThrow(RangeError);
expect(df.col("sort")).toBeUndefined();
expect(df.col("__proto__")).toBeUndefined();
expect(df.col(0)).toBeUndefined();
expect(df.col(true)).toBeUndefined();
expect(df.col(false)).toBeUndefined();
expect(df.col([])).toBeUndefined();
expect(df.col({})).toBeUndefined();
expect(df.col(null)).toBeUndefined();
expect(df.col(undefined)).toBeUndefined();
expect(() => df.icol("sort" as unknown as number)).toThrow(RangeError);
expect(() => df.icol("__proto__" as unknown as number)).toThrow(RangeError);
expect(() => df.icol(-1)).toThrow(RangeError);
expect(() => df.icol(true as unknown as number)).toThrow(RangeError);
expect(() => df.icol(false as unknown as number)).toThrow(RangeError);
expect(() => df.icol([] as unknown as number)).toThrow(RangeError);
expect(() => df.icol({} as unknown as number)).toThrow(RangeError);
expect(() => df.icol(null as unknown as number)).toThrow(RangeError);
expect(() => df.icol(undefined as unknown as number)).toThrow(RangeError);
expect(df.icol("sort")).toBeUndefined();
expect(df.icol("__proto__")).toBeUndefined();
expect(df.icol(-1)).toBeUndefined();
expect(df.icol(true)).toBeUndefined();
expect(df.icol(false)).toBeUndefined();
expect(df.icol([])).toBeUndefined();
expect(df.icol({})).toBeUndefined();
expect(df.icol(null)).toBeUndefined();
expect(df.icol(undefined)).toBeUndefined();
expect(
df.ihas("sort" as unknown as number, "length" as unknown as number)
).toBeFalsy();
expect(
df.ihas(
"__proto__" as unknown as number,
"__proto__" as unknown as number
)
).toBeFalsy();
expect(df.ihas("sort", "length")).toBeFalsy();
expect(df.ihas("__proto__", "__proto__")).toBeFalsy();
expect(df.ihas(-1, 0)).toBeFalsy();
expect(df.ihas("0" as unknown as number, 0)).toBeFalsy();
expect(df.ihas("" as unknown as number, 0)).toBeFalsy();
expect(df.ihas(null as unknown as number, 0)).toBeFalsy();
expect(df.ihas(undefined as unknown as number, 0)).toBeFalsy();
expect(df.ihas([] as unknown as number, 0)).toBeFalsy();
expect(df.ihas({} as unknown as number, 0)).toBeFalsy();
expect(df.ihas("0", 0)).toBeFalsy();
expect(df.ihas("", 0)).toBeFalsy();
expect(df.ihas(null, 0)).toBeFalsy();
expect(df.ihas(undefined, 0)).toBeFalsy();
expect(df.ihas([], 0)).toBeFalsy();
expect(df.ihas({}, 0)).toBeFalsy();
expect(df.ihas(0, -1)).toBeFalsy();
expect(df.ihas(0, "0" as unknown as number)).toBeFalsy();
expect(df.ihas(0, "" as unknown as number)).toBeFalsy();
expect(df.ihas(0, null as unknown as number)).toBeFalsy();
expect(df.ihas(0, undefined as unknown as number)).toBeFalsy();
expect(df.ihas(0, [] as unknown as number)).toBeFalsy();
expect(df.ihas(0, {} as unknown as number)).toBeFalsy();
expect(df.ihas(0, "0")).toBeFalsy();
expect(df.ihas(0, "")).toBeFalsy();
expect(df.ihas(0, null)).toBeFalsy();
expect(df.ihas(0, undefined)).toBeFalsy();
expect(df.ihas(0, [])).toBeFalsy();
expect(df.ihas(0, {})).toBeFalsy();
expect(df.has("sort", "length")).toBeFalsy();
expect(df.has("length", "sort")).toBeFalsy();
@@ -1465,17 +1424,17 @@ describe("corner cases", () => {
expect(df.has(-1, "A")).toBeFalsy();
expect(df.has("0", "A")).toBeFalsy();
expect(df.has("", "A")).toBeFalsy();
expect(df.has(null as unknown as string, "A")).toBeFalsy();
expect(df.has(undefined as unknown as string, "A")).toBeFalsy();
expect(df.has([] as unknown as string, "A")).toBeFalsy();
expect(df.has({} as unknown as string, "A")).toBeFalsy();
expect(df.has(null, "A")).toBeFalsy();
expect(df.has(undefined, "A")).toBeFalsy();
expect(df.has([], "A")).toBeFalsy();
expect(df.has({}, "A")).toBeFalsy();
expect(df.has(0, -1)).toBeFalsy();
expect(df.has(0, "0")).toBeFalsy();
expect(df.has(0, "")).toBeFalsy();
expect(df.has(0, null as unknown as string)).toBeFalsy();
expect(df.has(0, undefined as unknown as string)).toBeFalsy();
expect(df.has(0, [] as unknown as string)).toBeFalsy();
expect(df.has(0, {} as unknown as string)).toBeFalsy();
expect(df.has(0, null)).toBeFalsy();
expect(df.has(0, undefined)).toBeFalsy();
expect(df.has(0, [])).toBeFalsy();
expect(df.has(0, {})).toBeFalsy();
});
});
@@ -9,7 +9,7 @@ describe("Dataframe column histogram", () => {
new Dataframe.KeyIndex(["name", "cat", "value"])
);
const h1 = df.col("cat").histogramCategoricalBy(df.col("name"));
const h1 = df.col("cat").histogram(df.col("name"));
expect(h1).toMatchObject(
new Map([
["n1", new Map([["c1", 1]])],
@@ -18,9 +18,7 @@ describe("Dataframe column histogram", () => {
])
);
// memoized?
expect(df.col("cat").histogramCategoricalBy(df.col("name"))).toMatchObject(
h1
);
expect(df.col("cat").histogram(df.col("name"))).toMatchObject(h1);
});
test("continuous by categorical", () => {
@@ -31,7 +29,7 @@ describe("Dataframe column histogram", () => {
new Dataframe.KeyIndex(["name", "cat", "value"])
);
const h1 = df.col("value").histogramContinuousBy(3, [0, 2], df.col("name"));
const h1 = df.col("value").histogram(3, [0, 2], df.col("name"));
expect(h1).toMatchObject(
new Map([
["n1", [1, 0, 0]],
@@ -40,9 +38,9 @@ describe("Dataframe column histogram", () => {
])
);
// memoized?
expect(
df.col("value").histogramContinuousBy(3, [0, 2], df.col("name"))
).toMatchObject(h1);
expect(df.col("value").histogram(3, [0, 2], df.col("name"))).toMatchObject(
h1
);
});
test("categorical", () => {
@@ -53,7 +51,7 @@ describe("Dataframe column histogram", () => {
new Dataframe.KeyIndex(["name", "cat", "value"])
);
const h1 = df.col("cat").histogramCategorical();
const h1 = df.col("cat").histogram();
expect(h1).toMatchObject(
new Map([
["c1", 1],
@@ -62,7 +60,7 @@ describe("Dataframe column histogram", () => {
])
);
// memoized?
expect(df.col("cat").histogramCategorical()).toMatchObject(h1);
expect(df.col("value").histogram(3, [0, 2])).toMatchObject(h1);
});
test("continuous", () => {
@@ -73,10 +71,10 @@ describe("Dataframe column histogram", () => {
new Dataframe.KeyIndex(["name", "cat", "value"])
);
const h1 = df.col("value").histogramContinuous(3, [0, 2]);
const h1 = df.col("value").histogram(3, [0, 2]);
expect(h1).toMatchObject([1, 1, 1]);
// memoized?
expect(df.col("value").histogramContinuous(3, [0, 2])).toMatchObject(h1);
expect(df.col("value").histogram(3, [0, 2])).toMatchObject(h1);
});
test("continuous thesholds correct", () => {
@@ -86,10 +84,10 @@ describe("Dataframe column histogram", () => {
[new Int32Array(vals), new Float32Array(vals)]
);
expect(df.col(0).histogramContinuous(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
expect(df.col(1).histogramContinuous(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
expect(df.col(0).histogramContinuous(2, [0, 10])).toEqual([2, 2]);
expect(df.col(0).histogramContinuous(10, [0, 100])).toEqual([
expect(df.col(0).histogram(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
expect(df.col(1).histogram(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
expect(df.col(0).histogram(2, [0, 10])).toEqual([2, 2]);
expect(df.col(0).histogram(10, [0, 100])).toEqual([
3, 2, 1, 0, 0, 0, 0, 0, 0, 2,
]);
});
@@ -1,14 +1,13 @@
import * as Dataframe from "../../../src/util/dataframe";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function float32Conversion(f: any) {
function float32Conversion(f) {
return new Float32Array([f])[0];
}
describe("Dataframe column summary", () => {
test("empty column test", () => {
const df = Dataframe.Dataframe.create([0, 1], [[]]);
const summary = df.icol(0).summarizeCategorical();
const summary = df.icol(0).summarize();
expect(summary).toEqual(
expect.objectContaining({
categorical: true,
@@ -41,7 +40,7 @@ describe("Dataframe column summary", () => {
])
);
expect(df.icol(0).summarizeCategorical()).toEqual(
expect(df.icol(0).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: ["n1"],
@@ -49,7 +48,7 @@ describe("Dataframe column summary", () => {
numCategories: 1,
})
);
expect(df.icol(1).summarizeCategorical()).toEqual(
expect(df.icol(1).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: ["hi"],
@@ -57,7 +56,7 @@ describe("Dataframe column summary", () => {
numCategories: 1,
})
);
expect(df.icol(2).summarizeCategorical()).toEqual(
expect(df.icol(2).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: [true],
@@ -65,7 +64,7 @@ describe("Dataframe column summary", () => {
numCategories: 1,
})
);
expect(df.icol(3).summarizeContinuous()).toEqual(
expect(df.icol(3).summarize()).toEqual(
expect.objectContaining({
categorical: false,
min: float32Conversion(39.3),
@@ -75,7 +74,7 @@ describe("Dataframe column summary", () => {
pinf: 0,
})
);
expect(df.icol(4).summarizeContinuous()).toEqual(
expect(df.icol(4).summarize()).toEqual(
expect.objectContaining({
categorical: false,
min: 99,
@@ -85,7 +84,7 @@ describe("Dataframe column summary", () => {
pinf: 0,
})
);
expect(df.icol(5).summarizeCategorical()).toEqual(
expect(df.icol(5).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: [1],
@@ -117,7 +116,7 @@ describe("Dataframe column summary", () => {
])
);
expect(df.icol(0).summarizeCategorical()).toEqual(
expect(df.icol(0).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining(["n0", "n1", "n2"]),
@@ -129,7 +128,7 @@ describe("Dataframe column summary", () => {
numCategories: 3,
})
);
expect(df.icol(1).summarizeCategorical()).toEqual(
expect(df.icol(1).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining(["hi", "bye"]),
@@ -140,7 +139,7 @@ describe("Dataframe column summary", () => {
numCategories: 2,
})
);
expect(df.icol(2).summarizeCategorical()).toEqual(
expect(df.icol(2).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining([true, false]),
@@ -151,7 +150,7 @@ describe("Dataframe column summary", () => {
numCategories: 2,
})
);
expect(df.icol(3).summarizeContinuous()).toEqual(
expect(df.icol(3).summarize()).toEqual(
expect.objectContaining({
categorical: false,
min: 0,
@@ -161,7 +160,7 @@ describe("Dataframe column summary", () => {
pinf: 0,
})
);
expect(df.icol(4).summarizeContinuous()).toEqual(
expect(df.icol(4).summarize()).toEqual(
expect.objectContaining({
categorical: false,
min: 99,
@@ -171,11 +170,10 @@ describe("Dataframe column summary", () => {
pinf: 0,
})
);
expect(df.icol(5).summarizeCategorical()).toEqual(
expect(df.icol(5).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining([1, false, "0"]),
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
categoryCounts: new Map([
[1, 1],
[false, 1],
@@ -213,7 +211,7 @@ describe("Dataframe column summary", () => {
])
);
expect(df.icol(0).summarizeCategorical()).toEqual(
expect(df.icol(0).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining(["n0", "n1", "n2"]),
@@ -225,7 +223,7 @@ describe("Dataframe column summary", () => {
numCategories: 3,
})
);
expect(df.icol(1).summarizeCategorical()).toEqual(
expect(df.icol(1).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining(["hi", "bye"]),
@@ -236,7 +234,7 @@ describe("Dataframe column summary", () => {
numCategories: 2,
})
);
expect(df.icol(2).summarizeCategorical()).toEqual(
expect(df.icol(2).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining([true, false]),
@@ -247,7 +245,7 @@ describe("Dataframe column summary", () => {
numCategories: 2,
})
);
expect(df.icol(3).summarizeContinuous()).toEqual(
expect(df.icol(3).summarize()).toEqual(
expect.objectContaining({
categorical: false,
min: float32Conversion(39.3),
@@ -257,7 +255,7 @@ describe("Dataframe column summary", () => {
pinf: 1,
})
);
expect(df.icol(4).summarizeContinuous()).toEqual(
expect(df.icol(4).summarize()).toEqual(
expect.objectContaining({
categorical: false,
min: 99,
@@ -267,11 +265,10 @@ describe("Dataframe column summary", () => {
pinf: 0,
})
);
expect(df.icol(5).summarizeCategorical()).toEqual(
expect(df.icol(5).summarize()).toEqual(
expect.objectContaining({
categorical: true,
categories: expect.arrayContaining([1, false, "0"]),
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
categoryCounts: new Map([
[1, 1],
[false, 1],
@@ -1,8 +1,7 @@
import PromiseLimit from "../../src/util/promiseLimit";
import { range } from "../../src/util/range";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const delay = (t: any) => new Promise((resolve) => setTimeout(resolve, t));
const delay = (t) => new Promise((resolve) => setTimeout(resolve, t));
describe("PromiseLimit", () => {
test("simple evaluation, concurrency 1", async () => {
@@ -52,7 +51,7 @@ describe("PromiseLimit", () => {
running -= 1;
};
await Promise.all(range(10).map(() => plimit.add(() => callback())));
await Promise.all(range(10).map((i) => plimit.add(() => callback(i))));
expect(maxRunning).toEqual(2);
});
@@ -19,11 +19,7 @@ describe("quantile", () => {
test("multi q", () => {
const arr = new Float32Array([9, 3, 5, 6, 0]);
expect(quantile([0, 0.25, 0.5, 0.75, 1.0], arr)).toMatchObject([
0,
3,
5,
6,
9,
0, 3, 5, 6, 9,
]);
});
});
@@ -95,7 +95,6 @@ describe("categorical color helpers", () => {
const data = obsDataframe.col("categoricalColumn").asArray();
const cats = schema.annotations.obsByName.categoricalColumn.categories;
for (let i = 0; i < schema.dataframe.nObs; i += 1) {
// @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
expect(makeScale(ct.rgb[i])).toEqual(ct.scale(cats.indexOf(data[i])));
}
});
@@ -113,7 +112,6 @@ describe("categorical color helpers", () => {
const data = obsDataframe.col("categoricalColumn").asArray();
const cats = schemaClone.annotations.obsByName.categoricalColumn.categories;
for (let i = 0; i < schemaClone.dataframe.nObs; i += 1) {
// @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
expect(makeScale(ct.rgb[i])).toEqual(ct.scale(cats.indexOf(data[i])));
}
});
@@ -124,8 +122,7 @@ describe("categorical color helpers", () => {
Array.from(schema.annotations.obsByName.categoricalColumn.categories)
);
const userDefinedColorTable = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
categoricalColumn: shuffleCats.reduce((acc: any, label: any) => {
categoricalColumn: shuffleCats.reduce((acc, label) => {
acc[label] = randRGBColor();
return acc;
}, {}),
@@ -139,14 +136,12 @@ describe("categorical color helpers", () => {
"categoricalColumn",
obsDataframe,
schema,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{}' is not assignable to paramet... Remove this comment to see the full error message
userColors
);
expect(ct).toBeDefined();
const data = obsDataframe.col("categoricalColumn").asArray();
for (let i = 0; i < schema.dataframe.nObs; i += 1) {
expect(makeScale(ct.rgb[i])).toEqual(
// @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
ct.scale(cats.indexOf(data[i])).toString()
);
}
@@ -159,38 +154,31 @@ TODO:
2. user defined colors
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function indexSchema(schema: any) {
function indexSchema(schema) {
schema.annotations.obsByName = Object.fromEntries(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema.annotations?.obs?.columns?.map((v: any) => [v.name, v]) ?? []
schema.annotations?.obs?.columns?.map((v) => [v.name, v]) ?? []
);
schema.annotations.varByName = Object.fromEntries(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema.annotations?.var?.columns?.map((v: any) => [v.name, v]) ?? []
schema.annotations?.var?.columns?.map((v) => [v.name, v]) ?? []
);
schema.layout.obsByName = Object.fromEntries(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema.layout?.obs?.map((v: any) => [v.name, v]) ?? []
schema.layout?.obs?.map((v) => [v.name, v]) ?? []
);
schema.layout.varByName = Object.fromEntries(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
schema.layout?.var?.map((v: any) => [v.name, v]) ?? []
schema.layout?.var?.map((v) => [v.name, v]) ?? []
);
return schema;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function makeScale(rgb: any) {
function makeScale(rgb) {
// make a scale string from a rgb float triple
return `rgb(${(rgb[0] * 255) >>> 0}, ${(rgb[1] * 255) >>> 0}, ${
(rgb[2] * 256) >>> 0
})`;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function shuffle(array: any) {
function shuffle(array) {
for (let i = array.length - 1; i > 0; i -= 1) {
const j = (Math.random() * (i + 1)) >>> 0;
[array[i], array[j]] = [array[j], array[i]];
@@ -5,7 +5,6 @@ import zip from "lodash.zip";
import _ from "lodash";
import { flatbuffers } from "flatbuffers";
import { NetEncoding } from "../../../src/util/stateManager/matrix_generated";
import { RawSchema } from "../../../src/common/types/schema";
/*
test data mocking REST 0.2 API responses. Used in several tests.
@@ -30,7 +29,7 @@ const aConfigResponse = {
},
};
const aSchemaResponse: { schema: RawSchema } = {
const aSchemaResponse = {
schema: {
dataframe: {
nObs,
@@ -41,30 +40,28 @@ const aSchemaResponse: { schema: RawSchema } = {
obs: {
index: "name",
columns: [
{ name: "name", type: "string", writable: false },
{ name: "field1", type: "int32", writable: false },
{ name: "field2", type: "float32", writable: false },
{ name: "field3", type: "boolean", writable: false },
{ name: "name", type: "string" },
{ name: "field1", type: "int32" },
{ name: "field2", type: "float32" },
{ name: "field3", type: "boolean" },
{
name: "field4",
type: "categorical",
categories: field4Categories,
writable: false,
},
],
},
var: {
index: "name",
columns: [
{ name: "name", type: "string", writable: false },
{ name: "fieldA", type: "int32", writable: false },
{ name: "fieldB", type: "float32", writable: false },
{ name: "fieldC", type: "boolean", writable: false },
{ name: "name", type: "string" },
{ name: "fieldA", type: "int32" },
{ name: "fieldB", type: "float32" },
{ name: "fieldC", type: "boolean" },
{
name: "fieldD",
type: "categorical",
categories: fieldDCategories,
writable: false,
},
],
},
@@ -78,7 +75,6 @@ const aSchemaResponse: { schema: RawSchema } = {
const anAnnotationsObsJSONResponse = {
names: ["name", "field1", "field2", "field3", "field4"],
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
data: _()
.range(nObs)
.map((idx) => [
@@ -95,7 +91,6 @@ const anAnnotationsObsJSONResponse = {
const anAnnotationsVarJSONResponse = {
names: ["fieldA", "fieldB", "fieldC", "fieldD", "name"],
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
data: _()
.range(nVar)
.map((idx) => [
@@ -110,11 +105,8 @@ const anAnnotationsVarJSONResponse = {
.value(),
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function encodeTypedArray(builder: any, uType: any, uData: any) {
// @ts-expect-error --- FIXME: Element implicitly has an 'any' type.
function encodeTypedArray(builder, uType, uData) {
const uTypeName = NetEncoding.TypedArray[uType];
// @ts-expect-error --- FIXME: Element implicitly has an 'any' type.
const ArrayType = NetEncoding[uTypeName];
const dv = ArrayType.createDataVector(builder, uData);
builder.startObject(1);
@@ -122,8 +114,7 @@ function encodeTypedArray(builder: any, uType: any, uData: any) {
return builder.endObject();
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function encodeMatrix(columns: any, colIndex = undefined) {
function encodeMatrix(columns, colIndex = undefined) {
/*
IMPORTANT: this is not a general purpose encoder. in particular,
it doesn't correctly handle all column index types, nor does it
@@ -132,7 +123,6 @@ function encodeMatrix(columns: any, colIndex = undefined) {
encodeMatrixFBS in matrix.py is more general. This is used only
as a testing santity check (alt implementation).
*/
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
const utf8Encoder = new TextEncoder("utf-8");
const builder = new flatbuffers.Builder(1024);
const cols = map(columns, (carr) => {
@@ -182,13 +172,11 @@ function encodeMatrix(columns: any, colIndex = undefined) {
const anAnnotationsObsFBSResponse = (() => {
const columns = zip(...anAnnotationsObsJSONResponse.data).slice(1);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
return encodeMatrix(columns, anAnnotationsObsJSONResponse.names);
})();
const anAnnotationsVarFBSResponse = (() => {
const columns = zip(...anAnnotationsVarJSONResponse.data).slice(1);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
return encodeMatrix(columns, anAnnotationsVarJSONResponse.names);
})();
@@ -197,13 +185,11 @@ const aLayoutFBSResponse = (() => {
new Float32Array(nObs).fill(Math.random()),
new Float32Array(nObs).fill(Math.random()),
];
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
return encodeMatrix(coords, ["umap_0", "umap_1"]);
})();
const aDataObsResponse = {
var: [2, 4, 29],
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
obs: _()
.range(nObs)
.map((idx) => [idx, Math.random(), Math.random(), Math.random()])
@@ -126,8 +126,7 @@ const someData = [
},
];
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let payments: any = null;
let payments = null;
beforeEach(() => {
payments = new Crossfilter(someData);
});
@@ -139,13 +138,7 @@ describe("ImmutableTypedCrossfilter", () => {
expect(payments.all()).toEqual(someData);
const p = payments
.addDimension(
"quantity",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, d: any) => d[i].quantity,
Int32Array
)
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array)
.select("quantity", { mode: "all" });
expect(p).toBeDefined();
expect(p.all()).toEqual(someData);
@@ -165,8 +158,7 @@ describe("ImmutableTypedCrossfilter", () => {
const p2 = payments.addDimension(
"quantity",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, data: any) => data[i].quantity,
(i, data) => data[i].quantity,
Int32Array
);
@@ -183,22 +175,10 @@ describe("ImmutableTypedCrossfilter", () => {
test("select all and none", () => {
let p = payments
.addDimension(
"quantity",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, d: any) => d[i].quantity,
Int32Array
) // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.addDimension("tip", "scalar", (i: any, d: any) => d[i].tip, Float32Array)
.addDimension(
"total",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, d: any) => d[i].total,
Float32Array
) // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.addDimension("type", "enum", (i: any, d: any) => d[i].type);
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array)
.addDimension("tip", "scalar", (i, d) => d[i].tip, Float32Array)
.addDimension("total", "scalar", (i, d) => d[i].total, Float32Array)
.addDimension("type", "enum", (i, d) => d[i].type);
expect(p).toBeDefined();
/* expect all records to be selected - default init state */
@@ -250,24 +230,11 @@ describe("ImmutableTypedCrossfilter", () => {
});
describe("scalar dimension", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let p: any;
let p;
beforeEach(() => {
p = payments
.addDimension(
"quantity",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, d: any) => d[i].quantity,
Int32Array
)
.addDimension(
"tip",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, d: any) => d[i].tip,
Float32Array
)
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array)
.addDimension("tip", "scalar", (i, d) => d[i].tip, Float32Array)
.select("tip", { mode: "all" });
});
@@ -310,11 +277,9 @@ describe("ImmutableTypedCrossfilter", () => {
});
describe("enum dimension", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let p: any;
let p;
beforeEach(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
p = payments.addDimension("type", "enum", (i: any, d: any) => d[i].type);
p = payments.addDimension("type", "enum", (i, d) => d[i].type);
});
test("all", () => {
@@ -352,8 +317,7 @@ describe("ImmutableTypedCrossfilter", () => {
});
describe("spatial dimension", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let p: any;
let p;
beforeEach(() => {
const X = someData.map((r) => r.coords[0]);
const Y = someData.map((r) => r.coords[1]);
@@ -442,22 +406,14 @@ describe("ImmutableTypedCrossfilter", () => {
});
describe("non-finite scalars", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let p: any;
let p;
beforeEach(() => {
p = payments
.addDimension(
"quantity",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, d: any) => d[i].quantity,
Int32Array
)
.addDimension("quantity", "scalar", (i, d) => d[i].quantity, Int32Array)
.addDimension(
"nonFinite",
"scalar",
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(i: any, d: any) => d[i].nonFinite,
(i, d) => d[i].nonFinite,
Float32Array
)
.select("quantity", { mode: "all" });
@@ -151,9 +151,9 @@ describe("intersection", () => {
[1, 2],
[6, 9],
]);
expect(
PositiveIntervals.intersection([[0, 2638]], [[1363, 2638]])
).toEqual([[1363, 2638]]);
expect(PositiveIntervals.intersection([[0, 2638]], [[1363, 2638]])).toEqual(
[[1363, 2638]]
);
expect(PositiveIntervals.intersection([[1, 2]], [[1, 2]])).toEqual([
[1, 2],
]);
@@ -15,8 +15,7 @@ paths for:
const pInf = Number.POSITIVE_INFINITY;
const nInf = Number.NEGATIVE_INFINITY;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function fillRange(arr: any, start = 0) {
function fillRange(arr, start = 0) {
const larr = arr;
for (let i = 0, len = larr.length; i < len; i += 1) {
larr[i] = i + start;
@@ -24,8 +23,7 @@ function fillRange(arr: any, start = 0) {
return larr;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function fillRand(arr: any) {
function fillRand(arr) {
for (let i = 0, len = arr.length; i < len; i += 1) {
arr[i] = Math.random();
}
@@ -50,22 +48,16 @@ describe("sortArray", () => {
describe("finite numbers", () => {
[Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) =>
test(Type.name, () => {
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
expect(sortArray(Type.from([6, 5, 4, 3, 2, 1, 0]))).toMatchObject(
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
Type.from([0, 1, 2, 3, 4, 5, 6])
);
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
expect(sortArray(Type.from([6, 5, 4, 3, 2, 1]))).toMatchObject(
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
Type.from([1, 2, 3, 4, 5, 6])
);
const source = fillRand(new Type(1000));
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
expect(sortArray(Type.from(source))).toMatchObject(
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
Type.from(source).sort()
);
})
@@ -138,27 +130,22 @@ describe("sortIndex", () => {
describe("finite numbers", () => {
[Array, Float32Array, Uint32Array, Int32Array, Float64Array].map((Type) =>
test(Type.name, () => {
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
const source1 = Type.from([6, 5, 4, 3, 2, 1, 0]);
const index1 = fillRange(new Uint32Array(source1.length));
expect(sortIndex(index1, source1)).toMatchObject(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
index1.sort((a: any, b: any) => source1[a] - source1[b])
index1.sort((a, b) => source1[a] - source1[b])
);
// @ts-expect-error ts-migrate(2349) FIXME: This expression is not callable.
const source2 = Type.from([6, 5, 4, 3, 2, 1]);
const index2 = fillRange(new Uint32Array(source2.length));
expect(sortIndex(index2, source2)).toMatchObject(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
index2.sort((a: any, b: any) => source1[a] - source1[b])
index2.sort((a, b) => source1[a] - source1[b])
);
const source3 = fillRand(new Type(1000));
const index3 = fillRange(new Uint32Array(source3.length));
expect(sortIndex(index3, source3)).toMatchObject(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
index3.sort((a: any, b: any) => source1[a] - source1[b])
index3.sort((a, b) => source1[a] - source1[b])
);
})
);