This section describes the recommended Developer Environment and how to set it up. You are welcome to use any other tools you prefer.
- JDK 15. This can also be either installed, or downloaded as a .zip. If you do not use the installer, be sure to set the
JAVA_HOME
environment variable to the location of the JDK. - git. While this is not required, it is highly recommended if you will be doing active development on ANET.
- Checkout the source code from GitHub.
git clone [email protected]:NCI-Agency/anet.git
- Install the recommended git hooks
cd anet git config core.hooksPath scripts/githooks
- You cannot access the source code repo. Solution: Get someone who does have admin access to add you as a collaborator. Ensure that you have the correct public key installed to GitHub. See Connecting to GitHub with SSH for more information on troubleshooting this step.
- The git clone command takes a long time, then fails. Solution: Some networks block ssh. Try using the
https
URL from GitHub to download the source code.
The frontend is run with yarn
. We recommend running the backend gradle
if you are only doing frontend development.
- Set up Gradle
- This step is not needed unless want to use other settings and passwords than the default ones (see
build.gradle
for the defaults). You can define custom settings in a local settings file as follows: - Open a command line in the
anet
directory that was retrieved from GitHub. - Create a new empty file at
localSettings.gradle
. (touch localSettings.gradle
on linux/mac). This will be a file for all of your local settings and passwords that should not be checked into GitHub.
- This step is not needed unless want to use other settings and passwords than the default ones (see
- Update the settings in
application.yml
for your environment. See the ANET Configuration documentation for more details on these configuration options.
Several of the components used by the back-end run as Docker containers. Make sure you have at least Docker Engine (a.k.a. Docker CE) installed. Check that you can manage Docker as a non-root user.
You may opt to manage containers using a GUI like Docker Desktop, Rancher Desktop or Podman Desktop. Be aware that several of these use their own Docker context, which you can see with:
docker context ls
Output can be something like:
NAME DESCRIPTION DOCKER ENDPOINT
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
desktop-linux Docker Desktop unix:///home/developer/.docker/desktop/docker.sock
rancher-desktop Rancher Desktop moby context unix:///home/developer/.rd/docker.sock
You can always switch contexts with:
docker context use NAME
e.g.
docker context use default
If your container management GUI uses a different endpoint, make sure that the Gradle build and your GUI agree.
You should add a small configuration section to your localSettings.gradle
and localTestSettings.gradle
:
docker {
url = 'unix:///home/developer/.docker/desktop/docker.sock' // Use Docker Desktop context
}
Copy the endpoint you want to use.
If you also want to be able to manage the containers from your IDE, make sure to configure the same there too. E.g. for IntelliJ this would be under Services, then Docker, then Connections From Contexts, then double-click on the context you want to connect to.
- Only PostgreSQL can be used for your database. You can run it entirely on your local machine and develop offline.
- PostgreSQL
- This is the default, so you don't need to do anything special
- If you want to change any of the default database settings (see
build.gradle
for the defaults), you can paste them as following in yourlocalSettings.gradle
file (do it for the ones you want to change and with the correct values):run.environment("ANET_DB_USERNAME","username") run.environment("ANET_DB_PASSWORD", "password") run.environment("ANET_DB_SERVER", "db server hostname") run.environment("ANET_DB_NAME","database name")
- PostgreSQL
- Create the DB Docker container and the initial database:
./gradlew dockerCreateDB
- Start the DB Docker container:
./gradlew dockerStartDB
- Run
./gradlew run
to download all dependencies (including client dependencies like nodejs and yarn), build the project, and start the server. When starting the server, database migrations are run automatically, and the initial data is loaded.- The database schema is stored in
src/main/resources/migrations.xml
. - The initial data is stored in
insertBaseData-psql.sql
. - If for some reason you want to re-load the initial data, run:
./gradlew dbLoad
.
- The database schema is stored in
Provided with the ANET source code is the file insertBaseData-psql.sql
. This file contains a series of raw SQL commands that insert some sample data into the database that is both required in order to pass all the unit tests, and also helpful for quickly developing and testing new features. The Base Data Set includes a set of fake users, organizations, locations, and reports. Here are some of the accounts that you can use to log in and test with:
User | username | organization | position | role |
---|---|---|---|---|
Erin Erinson | erin | EF2.2 | EF2.2 Advisor D | Regular person who can also approve their own reports |
Rebecca Beccabon | rebecca | EF2.2 | EF2.2 Final Reviewer | Superuser |
Arthur Dmin | arthur | ANET Admins | ANET Administrator | Administrator |
Jack Jackson | jack | EF2.1 | EF2.1 Advisor B | Regular person |
Henry Henderson | henry | EF2.1 | EF2.1 Superuser | Superuser |
Steve Steveson | - | MoD | Cost Adder | Regular person |
Ihave Noposition | nopos | - | - | Regular person |
To log in as one of the base data users, when prompted for a username and password, enter their username as both the username and the password. See Users defined locally in the realm for other possible users.
-
When starting the server, database migrations are run automatically. For background info on some of these Liquibase commands, see: https://www.dropwizard.io/en/latest/manual/migrations.html
- You may need to occasionally destroy, re-migrate, and re-seed your database if it has fallen too far out of sync; you can do this with
env ANET_DB_DROP=true ./gradlew run
-- BE CAREFUL, this will drop and re-populate your database unconditionally!
- You may need to occasionally destroy, re-migrate, and re-seed your database if it has fallen too far out of sync; you can do this with
-
Make sure the Keycloak authentication server is started (in a Docker container) in your local development environment:
./gradlew dockerConfigureKeycloak dockerStartKeycloak
-
Run
./gradlew run
to run the server via Gradle- If you have set smtp: disabled to true in
application.yml
, you're good to go; otherwise, you can start an SMTP server (in a Docker container) in your local development environment:./gradlew dockerCreateFakeSmtpServer dockerStartFakeSmtpServer
- The following output indicates that the server is ready:
INFO [2017-02-10 16:44:59,902] org.eclipse.jetty.server.Server: Started @4098ms > Building 75% > :run
- If you have set smtp: disabled to true in
-
Go to http://localhost:8080/ in your browser.
- When prompted for credentials:
- Username:
erin
- Password: same as username
- Username:
- You will get an error about a missing
index.ftl
file; this is expected and means the backend server is working. The error looks like:ERROR [2017-02-10 16:49:33,967] javax.ws.rs.ext.MessageBodyWriter: Template Error ! freemarker.template.TemplateNotFoundException: Template not found for name "/views/index.ftl".
The web page will say Template Error
- When prompted for credentials:
-
If you want to see the app running, continue to the React Frontend instructions.
First configure the database backend.
The following instructions initialize a database for testing purposes, within the database container.
Use the -PtestEnv
property to access the test environment settings in gradle
.
- Create the PostgreSQL Docker container and test database
./gradlew -PtestEnv dockerCreateDB
- Start the PostgreSQL Docker container:
./gradlew -PtestEnv dockerStartDB
- Run
./gradlew -PtestEnv build
to download all dependencies and build the project.
Override the default gradle settings if you want to run your tests on a different database:
- Open a command line in the
anet
directory that was retrieved from GitHub. - Create a new empty file at
localTestSettings.gradle
. (touch localTestSettings.gradle
on linux/mac). This will be a file for all of your local test settings and passwords that should not be checked into GitHub.
- The tests always start with a clean test-database
- Make sure the Keycloak authentication server is started (in a Docker container) in your local development environment:
./gradlew dockerConfigureKeycloak dockerStartKeycloak
- Start a test SMTP server (in a Docker container) in your local development environment:
./gradlew -PtestEnv dockerCreateFakeSmtpServer dockerStartFakeSmtpServer
- Run the server side tests with a clean build:
./gradlew -PtestEnv cleanTest test
Note that the server-side tests use the GraphQL Java Generator to generate Java test classes from the GraphQL schema. If you have changed the schema, you need to update it before you can run the tests (especially if you want to test your schema changes). Since the schema is derived from the GraphQL service endpoint, you need to take the following steps for updating it:
- Start the server:
./gradlew run
- Generate the schema:
./gradlew yarn_run_generate-graphql-schema
- Check the generated schema, e.g.:
git diff src/test/resources/anet.graphql
If you have updated the generated schema and need to update the generated Java classes, you can run:
./gradlew generateClientCode
to re-generate the Java sources./gradlew compileTestJava
to re-generate the Java sources and compile them into Java class files
Our tests use selenium to simulate interacting with the app like a user. To do this, we need to connect a browser to the JavaScript tests. We do that via a driver. This driver can either run the tests locally on your system, or remotely via BrowserStack.
The tests are reliant on the data looking pretty similar to what you'd get after a fresh run of insertBaseData-psql.sql
. If the tests crash and do not complete, they could leave the data set in a state which would cause future test runs to fail. Make sure you start with a clean test-database.
- The tests always start with a clean test-database
- Start a test SMTP server (in a Docker container) in your local development environment:
./gradlew -PtestEnv dockerCreateFakeSmtpServer dockerStartFakeSmtpServer
- In order to run the client-side tests you must start a server using the test-database:
./gradlew -PtestEnv run
- Optionally, make sure you have the proper Node.js and Yarn in your path (see the React Frontend instructions).
Run ./gradlew yarn_run_lint:fix
to automatically fix some kinds of lint errors.
Run ./gradlew yarn_run_prettier:format
to reformat the JavaScript code according to our style guide.
To run the tests locally, make sure you have the server using the test-database running as above.
- Run the client side E2E tests against the test database:
./gradlew yarn_run_test-e2e
- Run the client side wdio tests against the test database:
./gradlew yarn_run_test-wdio
- Run the client side jest tests against the test database:
./gradlew yarn_run_test-jest
- Or run all client side tests against the test database:
./gradlew yarn_run_test-all
To run the tests locally, by having chromedriver
as an npm dependency, we automatically have access to run in Chrome. To use Firefox instead, see geckodriver
.
When writing browser tests, remember that when you take an action, you need to give the browser time to update in response before you start making assertions. Use the driver.wait
method to do this.
If the tests are failing, and you don't know why, run them with env var DEBUG_LOG=true
:
DEBUG_LOG=true ./gradlew yarn_run_test-e2e
You can also insert the following into your code to make the browser pause, allowing you to investigate what is currently happening:
await t.context.waitForever()
In rare circumstances, when using Chrome, the tests will hang on the data:,
URL. I don't know why this is. If you re-run the test, you should not see the issue a second time.
To run the tests remotely, you need a username and access key for BrowserStack.
Look up your settings and put them in client/config/default.json
:
{
"browserstack_user": "myusername123",
"browserstack_key": "mYbRoWsErStAcKkEy"
}
If you want step-by-step screenshots from your tests (Visual Logs on BrowserStack) you can also add:
"browserstack_debug": "true"
to your default.json
.
Note that both the E2E and the wdio tests will automatically start (and stop) BrowserStackLocal during the tests.
When all is set up, run the remote tests:
- Configure scripts with
TEST_ENV
environment variable for remote testing:export TEST_ENV=remote
- Run;
- the client side E2E tests:
./gradlew yarn_run_test-e2e
- the client side wdio tests:
./gradlew yarn_run_test-wdio
- the client side wdio-ie tests:
About IE tests: Internet Explorer is not fully supported by ANET and all features are NOT guaranteed to work with IE. For that reason, a warning banner is displayed when IE detected.
./gradlew yarn_run_test-wdio-ie
test-wdio-ie
runs tests for this scenario and these tests run only on remote testing. When testing locally, they gracefully abort. - all client side tests:
./gradlew yarn_run_test-all
- the client side E2E tests:
- You can view the progress and results on BrowserStack.
ANET has a simulator that can exercise of the functions. It is located in 'client/test/sim'. It works by interfacing with ANET through GraphQL queries. The simulator executes stories
which are assigned to different user types and have different probabilities.
The simulator can be started by running './gradlew yarn_run_sim'.
All the frontend code is in the client/
directory.
- You can run all client-side scripts via Yarn through Gradle. Otherwise, make sure you have the proper Node.js and Yarn in your path; example:
Note: Node.js and Yarn versions might have changed in the meanwhile, check inside
export YARN_HOME=<anet_root_path>/.gradle/yarn/yarn-v1.22.15 export NODEJS_HOME=<anet_root_path>/.gradle/nodejs/node-v14.18.1-linux-x64 export PATH="$YARN_HOME/bin:$NODEJS_HOME/bin:$PATH" cd client/
<anet_root_path>/.gradle/nodejs/
and<anet_root_path>/.gradle/yarn/
for which versions are being used and change the path accordingly. - Run the server:
./gradlew yarn_run_start
- Go to http://localhost:3000/ in your browser.
- When prompted for credentials:
- Username:
erin
- Password: same as username
- Username:
- When prompted for credentials:
NB: You only need node.js and the npm dependencies for developing. When we deploy for production, everything is compiled to static files. No javascript dependencies are necessary on the server.
To simulate a "new user" in development mode, create a new user in the Keycloak realm, then log on to ANET as that user. This will start the new user workflow (onboarding). Note: if you enter an unknown username, ANET will reject you.