diff --git a/.github/workflows/push_tests.yml b/.github/workflows/push_tests.yml index 0e84a43b..0ccbde78 100644 --- a/.github/workflows/push_tests.yml +++ b/.github/workflows/push_tests.yml @@ -4,7 +4,7 @@ on: push: branches: master pull_request: - branches: '*' + branches: "*" env: JEST_ENV: prod @@ -32,7 +32,7 @@ jobs: run: | pip install flake8 cd client - npm i "eslint" "eslint-config-airbnb" "eslint-config-prettier" "eslint-loader" "eslint-plugin-filenames" "eslint-plugin-import" "eslint-plugin-jest" "eslint-plugin-jsx-a11y" "eslint-plugin-react" "eslint-plugin-react-hooks" "eslint-plugin-prettier" + npm install - name: Lint with flake8 run: | make lint-server @@ -41,7 +41,6 @@ jobs: run: | make lint - unit-test: runs-on: ubuntu-latest steps: diff --git a/.gitignore b/.gitignore index 4f93ac98..cb29f839 100644 --- a/.gitignore +++ b/.gitignore @@ -19,11 +19,7 @@ venv/ cellxgene/ # client build -server/common/web/static/css/ -server/common/web/static/img/ -server/common/web/static/media/ -server/common/web/static/fonts/ -server/common/web/static/js/ +server/common/web/static/* server/common/web/templates/ server/common/web/csp-hashes.json @@ -53,3 +49,6 @@ docs/_site/ docs/Gemfile.lock client/.eslintcache + +# E2E Testing +ignoreE2E* diff --git a/client/Makefile b/client/Makefile index 3a9acb5b..5033053f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -7,6 +7,7 @@ ANNOTATIONS_FILENAME := $(shell basename $(ANNOTATIONS)) .PHONY: clean clean: rm -rf node_modules + rm -f __tests__/screenshots/*.png .PHONY: ci ci: @@ -21,39 +22,20 @@ WEBPACK_CONFIG ?= configuration/webpack/webpack.config.prod.js build: npm run build $(WEBPACK_CONFIG) -# Formatting code - -.PHONY: lint -lint: - npx eslint ./src/ - # Development convenience methods .PHONY: start-frontend start-frontend: node server/development.js -.PHONY: e2e -e2e: - node node_modules/jest/bin/jest.js \ - --verbose false \ - --config __tests__/e2e/e2eJestConfig.json \ - e2e/e2e.test.js - -.PHONY: e2e-annotations -e2e-annotations: - node node_modules/jest/bin/jest.js \ - --verbose false \ - --config __tests__/e2e/e2eJestConfig.json \ - e2e/e2eAnnotations.test.js - +# start an instance of cellxgene and run the end-to-end tests .PHONY: smoke-test smoke-test: start_server_and_test \ 'CXG_OPTIONS="--disable-annotations" $(MAKE) start-server' \ $(CXG_SERVER_PORT) \ - '$(MAKE) e2e' - + 'CXG_URL_BASE="http://localhost:$(CXG_SERVER_PORT)" npm run e2e -- --verbose false' +# start an instance of cellxgene and run the end-to-end annotations tests .PHONY: smoke-test-annotations smoke-test-annotations: $(eval TMP_DIR := $(shell mktemp -d /tmp/cellxgene_XXXXXX)) @@ -61,13 +43,12 @@ smoke-test-annotations: start_server_and_test \ 'CXG_OPTIONS="--annotations-file $(TMP_DIR)/$(ANNOTATIONS_FILENAME)" $(MAKE) start-server' \ $(CXG_SERVER_PORT) \ - '$(MAKE) e2e-annotations' + 'CXG_URL_BASE="http://localhost:$(CXG_SERVER_PORT)" npm run e2e-annotations -- --verbose false' rm -rf $(TMP_DIR) .PHONY: unit-test unit-test: - node node_modules/jest/bin/jest.js \ - --testPathIgnorePatterns e2e + node node_modules/jest/bin/jest.js --testPathIgnorePatterns e2e # pass remaining commands through to npm run %: diff --git a/client/__tests__/e2e/__snapshots__/e2e.test.js.snap b/client/__tests__/e2e/__snapshots__/e2e.test.js.snap index 6c411b0f..a81872c6 100644 --- a/client/__tests__/e2e/__snapshots__/e2e.test.js.snap +++ b/client/__tests__/e2e/__snapshots__/e2e.test.js.snap @@ -2,4 +2,4 @@ exports[`did launch page launched 1`] = `"pbmc3kc3k"`; -exports[`metadata loads categories and values from dataset appear 1`] = `"
Name your annotations collection:
Create annotations collection
diff --git a/client/src/components/categorical/annoSelect.js b/client/src/components/categorical/annoSelect.js
index a78a5331..f2d3cd84 100644
--- a/client/src/components/categorical/annoSelect.js
+++ b/client/src/components/categorical/annoSelect.js
@@ -27,7 +27,14 @@ class DuplicateCategorySelect extends React.PureComponent {
}
filterable={false}
itemRenderer={(d, { handleClick }) => {
- return ;
+ return (
+
+ );
}}
noResults={}
onItemSelect={(d) => {
@@ -36,6 +43,7 @@ class DuplicateCategorySelect extends React.PureComponent {
>
{/* children become the popover target; render value here */}
diff --git a/client/src/components/categorical/category/index.js b/client/src/components/categorical/category/index.js
index 6f50eea6..cd0976ad 100644
--- a/client/src/components/categorical/category/index.js
+++ b/client/src/components/categorical/category/index.js
@@ -258,6 +258,7 @@ class Category extends React.Component {
{
if (e.key === "Enter") {
diff --git a/client/src/components/graph/drawPointsRegl.js b/client/src/components/graph/drawPointsRegl.js
index 082d9520..47c665a3 100644
--- a/client/src/components/graph/drawPointsRegl.js
+++ b/client/src/components/graph/drawPointsRegl.js
@@ -1,6 +1,6 @@
import { glPointFlags, glPointSize } from "../../util/glHelpers";
-export default function (regl) {
+export default function drawPointsRegl(regl) {
return regl({
vert: `
precision mediump float;
diff --git a/client/src/components/scatterplot/drawPointsRegl.js b/client/src/components/scatterplot/drawPointsRegl.js
index a9e8a40a..4f70e9ed 100644
--- a/client/src/components/scatterplot/drawPointsRegl.js
+++ b/client/src/components/scatterplot/drawPointsRegl.js
@@ -1,6 +1,6 @@
import { glPointFlags, glPointSize } from "../../util/glHelpers";
-export default function (regl) {
+export default function drawPointsRegl(regl) {
return regl({
vert: `
precision mediump float;
diff --git a/client/src/globals.js b/client/src/globals.js
index e53eef49..a39d7846 100644
--- a/client/src/globals.js
+++ b/client/src/globals.js
@@ -1,5 +1,6 @@
import { Colors } from "@blueprintjs/core";
import { dispatchNetworkErrorMessageToUser } from "./util/actionHelpers";
+import * as ENV_DEFAULT from "../../environment.default.json";
/* if a categorical metadata field has more options than this, truncate */
export const maxCategoricalOptionsToDisplay = 200;
@@ -82,21 +83,25 @@ export const maxGenes = 100;
export const tooltipHoverOpenDelay = 1000; /* ms delay before a tooltip displays */
export const tooltipHoverOpenDelayQuick = 500;
+const CXG_SERVER_PORT =
+ process.env.CXG_SERVER_PORT || ENV_DEFAULT.CXG_SERVER_PORT;
+
let _API;
if (window.CELLXGENE && window.CELLXGENE.API) {
_API = window.CELLXGENE.API;
} else {
- if (process.env.CXG_SERVER_PORT === undefined) {
+ if (CXG_SERVER_PORT === undefined) {
const errorMessage = "Please set the CXG_SERVER_PORT environment variable.";
dispatchNetworkErrorMessageToUser(errorMessage);
throw new Error(errorMessage);
}
+
_API = {
// prefix: "http://api.clustering.czi.technology/api/",
// prefix: "http://tabulamuris.cxg.czi.technology/api/",
// prefix: "http://api-staging.clustering.czi.technology/api/",
- prefix: `http://localhost:${process.env.CXG_SERVER_PORT}/api/`,
+ prefix: `http://localhost:${CXG_SERVER_PORT}/api/`,
version: "v0.2/",
};
}
diff --git a/common.mk b/common.mk
index dc1d3bd2..01a11476 100644
--- a/common.mk
+++ b/common.mk
@@ -3,11 +3,12 @@ PATH := $(PATH):$(PROJECT_ROOT)/scripts
SHELL := env PATH='$(PATH)' /bin/bash
-# get_or_else_dev_env_default
-# - If a variable is defined, return its value
-# - Else return the default value from environment.dev
-define get_or_else_dev_env_default
-$(if $($(1)),$($(1)),$(shell VAR=$$(sed -n 's/$(1)=\(.*\)/\1/p' $(PROJECT_ROOT)/environment.default); eval "echo \"$$VAR\""))
+ifeq ($(shell which jq),)
+$(error Please install jq using "apt-get install jq" or "brew install jq")
+endif
+
+define GetValueFromJson
+$(shell jq -r '.$(1)' "$(PROJECT_ROOT)/environment.default.json")
endef
# https://stackoverflow.com/a/14777895/9587410
@@ -16,11 +17,11 @@ ifeq ($(shell uname),Darwin) # is Windows_NT on XP, 2000, 7, Vista, 10...
endif
export CELLXGENE_COMMIT := $(shell git rev-parse --short HEAD)
-export CXG_SERVER_PORT := $(call get_or_else_dev_env_default,CXG_SERVER_PORT)
-export CXG_CLIENT_PORT := $(call get_or_else_dev_env_default,CXG_CLIENT_PORT)
-export JEST_ENV := $(call get_or_else_dev_env_default,JEST_ENV)
-export DATASET := $(call get_or_else_dev_env_default,DATASET)
-export CXG_OPTIONS := $(call get_or_else_dev_env_default,CXG_OPTIONS)
+export CXG_SERVER_PORT := $(call GetValueFromJson,CXG_SERVER_PORT)
+export CXG_CLIENT_PORT := $(call GetValueFromJson,CXG_CLIENT_PORT)
+export JEST_ENV := $(call GetValueFromJson,JEST_ENV)
+export DATASET := $(call GetValueFromJson,DATASET)
+export CXG_OPTIONS := $(call GetValueFromJson,CXG_OPTIONS)
.PHONY: start-server
start-server:
diff --git a/dev_docs/developer_guidelines.md b/dev_docs/developer_guidelines.md
index 93c03d63..409d34ed 100644
--- a/dev_docs/developer_guidelines.md
+++ b/dev_docs/developer_guidelines.md
@@ -1,6 +1,7 @@
# Developer guidelines
-### Requirements
+## Requirements
+
- npm
- Python 3.6+
- Chrome
@@ -11,20 +12,24 @@
### Environment
-For all `make` commands, `common.mk` automatically checks whether required environment variables are set and, if they are not set, assigns them default values from `environment.default`.
+For all `make` commands, `common.mk` automatically checks whether required environment variables are set and, if they are not set, assigns them default values from `environment.default.json`.
-You can set these environment variables manually with the `export` shell command, as in `export JEST_ENV=debug`.
+You can set these environment variables manually with the `export` shell command, as in `export JEST_ENV=debug`, or you can just pass the variables as part of the command. E.g., `HEADFUL=true make e2e` or `JEST_ENV=debug npm run e2e`
## Running test suite
-Client and server tests run on Travis CI for every push, PR, and commit to master on github. End to end tests run nightly on master only.
+
+Client and server tests run on Travis CI for every push, PR, and commit to master on github. End to end tests run nightly on master only.
### Unit tests
+
Steps to run the all unit tests:
+
1. Start in the project root directory
1. `make dev-env`
1. `make unit-test`
To run unit tests for the `client` code only:
+
1. Start in the project root directory
1. `cd client`
1. `make unit-test`
@@ -33,37 +38,58 @@ To run unit tests for the `client` code only:
To run E2E tests, run `cd client` and `make smoke-test`
-The `JEST_ENV` environment variable enables the following E2E test options:
-* `dev` - opens chromimum, runs tests with minimal slowdown, close on exit.
-* `debug` - opens chromium, runs tests with 100ms slowdown, dev tools open, chrome stays open on exit.
-* `prod` - run headless with no slowdown, chromium will not open.
+#### Flags
-Run end to end tests interactively during development
-1. cellxgene should be installed as [specified in client dev](#install-1)
-1. Follow [launch](#launch-1) instructions for client dev with dataset `example-dataset/pbmc3k`
-1. Run `npm run e2e` or `make e2e` from the `client` directory
-1. To debug a failing test `export JEST_ENV='debug'` and re-run.
+1. `JEST_ENV`: This enables the following E2E test options. You can find their corresponding configs in [`jest-puppeteer.config.js`](../client/jest-puppeteer.config.js):
-To run end to end tests _exactly_ as they will be run on CI use the following command:
-```
+ - `dev` - opens window, runs tests with minimal slowdown, close on exit.
+ - `debug` - opens window, runs tests with 100ms slowdown, dev tools open, chrome stays open on exit.
+ - `prod`[default] - run headless with no slowdown, window will not open.
+
+2. `HEADFUL`: Default is `false`. When set to `true`, it will launch the Chrome window for visual inspection. E.g., `HEADFUL=true npm run e2e`
+
+3. `HEADLESS`: Default is `true`. When set to `false`, it will launch the Chrome window for visual inspection. E.g., `HEADLESS=false npm run e2e`
+
+#### Run end to end tests interactively during development
+
+1. cellxgene should be installed as [specified in client dev](#install)
+
+1. Follow [launch](#launch) instructions for client dev with dataset `example-dataset/pbmc3k`
+
+1. Run `npm run e2e` from the `client` directory
+
+1. To debug a failing test, add `debugger` in any line of JS code as breakpoint, and launch the test again with [`ndb`](https://github.com/GoogleChromeLabs/ndb). E.g., `ndb make e2e` or `ndb npm run e2e`.
+
+ 1. Please make sure to install `ndb` via `npm install -g ndb`
+
+ 1. Check out [Debugging Tips](e2e_tests.md#debugging-tips) for more ideas!
+
+#### To run end to end tests _exactly_ as they will be run on CI use the following command
+
+```shell
JEST_ENV=prod make pydist install-dist dev-env smoke-test
```
## Server dev
+
### Install
To install from the source tree
-* Build the client and put static files in place: `make build-for-server-dev`
-* Install from local files: `make install-dev`
+
+- Build the client and put static files in place: `make build-for-server-dev`
+- Install from local files: `make install-dev`
To install from a candidate python distribution
-* Make the distribution: `make pydist`
-* Install it: `make install-dist`
+
+- Make the distribution: `make pydist`
+- Install it: `make install-dist`
### Launch
-* `cellxgene launch [options]