diff --git a/tests/README.md b/tests/README.md index a0ddf85a..90598939 100644 --- a/tests/README.md +++ b/tests/README.md @@ -14,7 +14,7 @@ Ensure npm is installed, and make sure you are in the `/tests` direct npm install --save-dev mocha chai playwright ``` -In the created package.json file, add within the outermost braces (you can append CLI options, like "--timeout" to this as well): +In the created package.json file, add within the outermost braces (you can append CLI options, like "--timeout" to the test alias as well): ```json "scripts": { @@ -48,6 +48,8 @@ When testing the front-end, it is important to test in the same way a user would * Mocha has a nice wiki on Github for do's and don'ts (https://github.com/mochajs/mocha/wiki) +* The default timeout of mocha tests is 2000ms. It may be wise to set sections to a longer timeout with `this.timeout(ms)` + ### Current and pending UI tests #### Account creation diff --git a/tests/test/dataset_curator.test.js b/tests/test/dataset_curator.test.js index 3e2059cc..2483b6ca 100644 --- a/tests/test/dataset_curator.test.js +++ b/tests/test/dataset_curator.test.js @@ -11,6 +11,8 @@ import { expect } from "playwright/test"; import { browsers, gearBase, login, loginFailure, setupBrowserContext, teardownBrowserContext } from "./helpers.js"; +import { mockGetDatasetList } from "./helpers.js"; + let page; const gearUrl = `${gearBase}/dataset_curator.html`; @@ -37,6 +39,93 @@ describe('Dataset Curator', function () { describe(`Browser: ${b.name}`, () => { + it("should populate the dataset list", async () => { + await mockGetDatasetList(page); + const datasetInput = page.locator("css=#dataset_query"); + const datasetTree = page.locator("css=#dataset_tree"); + expect(await datasetTree).toBeVisible(); + expect(await datasetTree.locator("css=.wb-row")).toHaveCount(3); // 3 categories + await datasetInput.fill("Hertzano"); + expect(await page.getByText("(Hertzano/Ament)")).toBeVisible(); + + }); + + describe("plotting", () => { + + it("should plot a scatterplot", async () => {}); + + it("should plot a boxplot", async () => {}); + + it("should plot a line plot", async () => {}); + + it("should plot a violin plot", async () => {}); + + it("should plot a tSNE static plot", async () => {}); + + it("should plot a UMAP static plot", async () => {}); + + it("should plot a SVG plot", async () => {}); + + }); + + describe("options settings", () => { + + describe("common options", () => { + + }); + + describe("plot-specific options", () => { + + }); + + }); + + + describe("logged in", () => { + + beforeEach("Logging in", async () => { + await login(page, gearUrl); + }); + + it('should login', async () => { + expect(await page.title()).toEqual("gEAR dataset curator page"); + }); + + it("should prevent user from deleting a display owned by another user", async () => {}); + + it("should be able to delete a display owned by the user", async () => {}); + + it("Should be able to switch default displays", async () => {}); + + describe("saving", () => { + + it("should save a new display", async () => {}); + + it("should save a new display as a new default", async () => {}); + + }); + + }) + + describe("not logged in", () => { + + it('should fail to login with incorrect password', async () => { + await loginFailure(page, gearUrl); + // Check that the error message is displayed + const incorrectPw = page.getByText("Incorrect password"); + await expect(incorrectPw).toBeVisible(); + expect(await page.title()).toEqual("gEAR dataset curator page"); + }); + + it("should prevent user from selecting a default display", async () => {}) + + it("should prevent user from saving a display", async () => {}); + + it("should prevent user from deteting a display", async () => {}); + + + }) + }); } }); \ No newline at end of file diff --git a/tests/test/helpers.js b/tests/test/helpers.js index 536726d8..d3f9eac8 100644 --- a/tests/test/helpers.js +++ b/tests/test/helpers.js @@ -195,4 +195,94 @@ export const mockGetOrganismList = async (page, organism) => { }; await route.fulfill({ json }); }); -} \ No newline at end of file +} +export const mockGetDatasetList = async (page) => { + await page.route(`${gearBase}/cgi/get_h5ad_dataset_list.cgi`, async route => { + const json = { + "shared_with_user": { + "datasets": [] + }, + "user": { + "datasets": [ + { + "id": "dcfb4818-5302-83b5-4cc1-e586a5f81f74", + "owner_id": 662, + "title": "RNAseq, Deiters' cells,pillar cells, Inner Hair Cells and Outer Hair Cells,workshop (He)", + "organism_id": 1, + "pubmed_id": "30327589", + "geo_id": "GSE111347", + "is_public": null, + "ldesc": "RNA extracted from Deiters' cells,pillar cells, Inner Hair Cells and Outer Hair Cells. three biological replicates, each with two technical repeats for Deiter and pillar cells, two biological replicates of IHCs and three biological replicates of OHCs, each with two technical repeats. They was seuqenced by Illumina HiSeq 2500.", + "date_added": "2022-05-25 15:21:30", + "dtype": "bulk-rnaseq", + "schematic_image": null, + "share_id": "711a8330", + "math_default": "raw", + "marked_for_removal": 0, + "load_status": "completed", + "has_h5ad": 1, + "platform_id": null, + "instrument_model": null, + "library_selection": null, + "library_source": null, + "library_strategy": null, + "contact_email": null, + "contact_institute": null, + "contact_name": null, + "annotation_source": null, + "plot_default": null, + "annotation_release": null, + "gene_count": null, + "obs_count": null, + "has_tarball": 0, + "displays": [], + "tags": [], + "layouts": [], + "links": [] + } + ] + }, + "public": { + "datasets": [ + { + "id": "1b12dde9-1762-7564-8fbd-1b07b750505f", + "owner_id": 3, + "title": "P2, mouse, scRNA-seq, cochlea (Hertzano/Ament)", + "organism_id": 1, + "pubmed_id": "None", + "geo_id": "None", + "is_public": 1, + "ldesc": "Cochleae of P2 C57BL/6N wild type mice were dissociated. Gene expression was measured using the 10x scRNA-seq platform. This is an unpublished dataest from the laboratories of Drs. Hertzano and Ament from the University of Maryland School of Medicine (UMSOM).\n\nThis dataset has a limited number of cells. Hair cells were identified as a single cluster. Inner and outer hair cells cluster together. ", + "date_added": "2019-02-01 15:29:49", + "dtype": "single-cell-rnaseq", + "schematic_image": null, + "share_id": "2050da31", + "math_default": "raw", + "marked_for_removal": 0, + "load_status": "completed", + "has_h5ad": 1, + "platform_id": null, + "instrument_model": null, + "library_selection": null, + "library_source": null, + "library_strategy": null, + "contact_email": null, + "contact_institute": null, + "contact_name": null, + "annotation_source": null, + "plot_default": null, + "annotation_release": null, + "gene_count": null, + "obs_count": null, + "has_tarball": 0, + "displays": [], + "tags": [], + "layouts": [], + "links": [] + } + ] + } + } + await route.fulfill({ json }); + }); +}; \ No newline at end of file diff --git a/tests/test/multigene_curator.test.js b/tests/test/multigene_curator.test.js new file mode 100644 index 00000000..03f5ab02 --- /dev/null +++ b/tests/test/multigene_curator.test.js @@ -0,0 +1,148 @@ +#!/usr/bin/env mocha + +/* + Unit tests for dataset_curator.js +*/ + +// Some setup help by https://publishing-project.rivendellweb.net/testing-front-end-with-mocha-and-playwright-2/ + +import "mocha" // to set global variables like describe, it, etc. +import { expect } from "playwright/test"; + +import { browsers, gearBase, login, loginFailure, setupBrowserContext, teardownBrowserContext } from "./helpers.js"; + +import { mockGetDatasetList } from "./helpers.js"; + + +let page; + +const gearUrl = `${gearBase}/multigene_curator.html`; + + +describe('Dataset Curator', function () { + this.retries(3); + + this.timeout(10000); // default is 2000 + + let browserIndex = 0; + + beforeEach("Setting up", async () => { + + page = await setupBrowserContext(browserIndex); + await page.goto(gearUrl); + }); + + afterEach("Closing", async () => { + await teardownBrowserContext(); + }); + + for (const b of browsers) { + + describe(`Browser: ${b.name}`, () => { + + it("should populate the dataset list", async () => { + it("should populate the dataset list", async () => { + await mockGetDatasetList(page); + const datasetInput = page.locator("css=#dataset_query"); + const datasetTree = page.locator("css=#dataset_tree"); + expect(await datasetTree).toBeVisible(); + expect(await datasetTree.locator("css=.wb-row")).toHaveCount(3); // 3 categories + await datasetInput.fill("Hertzano"); + expect(await page.getByText("(Hertzano/Ament)")).toBeVisible(); + + }); + + }); + + describe("gene selection", () => { + + it("should append to the genes list when a gene is manually selected", async () => {}); + + it("should append to the genes list when a genecart is selected", async () => {}); + + it("should remove a gene from the genes list when the remove button is clicked", async () => {}); + + it("should remove all genes when Clear is clicked", async () => {}); + }); + + describe("plotting", () => { + + it("should plot a heatmap", async () => {}); + + it("should plot a matrixplot", async () => {}); + + it("should plot a dotplot", async () => {}); + + it("should plot a violin plot", async () => {}); + + it("should plot a stacked violin plot", async () => {}); + + it("should plot a volcano plot", async () => {}); + + it("should plot a quadrant plot", async () => {}); + + }); + + describe("options settings", () => { + + describe("common options", () => { + + }); + + describe("plot-specific options", () => { + + }); + + }); + + describe("saving", () => { + + }); + + + describe("logged in", () => { + + beforeEach("Logging in", async () => { + await login(page, gearUrl); + }); + + it('should login', async () => { + expect(await page.title()).toEqual("gEAR multigene viewer page"); + }); + + it("should prevent user from deleting a display owned by another user", async () => {}); + + it("should be able to delete a display owned by the user", async () => {}); + + it("Should be able to switch default displays", async () => {}); + + describe("saving", () => { + + it("should save a new display", async () => {}); + + it("should save a new display as a new default", async () => {}); + }); + + }) + + describe("not logged in", () => { + + it('should fail to login with incorrect password', async () => { + await loginFailure(page, gearUrl); + // Check that the error message is displayed + const incorrectPw = page.getByText("Incorrect password"); + await expect(incorrectPw).toBeVisible(); + expect(await page.title()).toEqual("gEAR multigene viewer page"); + }); + + it("should prevent user from selecting a default display", async () => {}) + + it("should prevent user from saving a display", async () => {}); + + it("should prevent user from deteting a display", async () => {}); + + }) + + }); + } +}); \ No newline at end of file