Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9909e41
Rebase development onto branch
nickbeaird Aug 19, 2020
a984d06
Move files the backend dir for jest setup
nickbeaird Jul 9, 2020
e90091f
Rebase changes on development
nickbeaird Aug 19, 2020
c23bf91
Get backend working with slack
nickbeaird Aug 19, 2020
f2c8d06
Get a working client and backend script
nickbeaird Aug 19, 2020
a09962b
Add backend jest environment
nickbeaird Aug 19, 2020
9b8f069
Get working unit tests with jest
nickbeaird Aug 19, 2020
2d6b731
Do not commit test db or db config file
nickbeaird Aug 19, 2020
688a752
Getting a simple api test
nickbeaird Aug 20, 2020
5ea1dea
Refactor server and app for testability
nickbeaird Aug 21, 2020
23ecc0b
Disable slack app to enable testing
nickbeaird Aug 21, 2020
94f7179
Add working proxy settings for front and backend
nickbeaird Aug 21, 2020
03b2b5e
Get some example test cases
nickbeaird Aug 21, 2020
343369d
Fix typo in server file
nickbeaird Aug 21, 2020
5fafaf2
Rename test files
nickbeaird Aug 21, 2020
34c418f
Fix Answer model and add unit test
nickbeaird Aug 21, 2020
8b68a37
Fix Answer model and add unit test
nickbeaird Aug 21, 2020
243c286
Add Checkin model unit test
nickbeaird Aug 21, 2020
2d0f073
Add Events unit test
nickbeaird Aug 21, 2020
d0e117d
Get working Project unit test
nickbeaird Aug 21, 2020
32d087a
Add unit tests for projectTeamMember model
nickbeaird Aug 21, 2020
da88bdd
Return formatting to preserve inline comments
nickbeaird Aug 21, 2020
46449a3
Add unit tests for Question Model
nickbeaird Aug 21, 2020
fdf28a2
Add recurringEvent unit test
nickbeaird Aug 21, 2020
e19a469
Add user unit test
nickbeaird Aug 21, 2020
234c114
Resolve import statements
nickbeaird Aug 21, 2020
ef62493
Update README for setting up the project
nickbeaird Aug 21, 2020
c09cf46
Add api test for Event creation
nickbeaird Aug 22, 2020
7c36425
Add documentation for the tests
nickbeaird Aug 22, 2020
afc8514
Make a workaround to get the tests working
nickbeaird Aug 22, 2020
57b8906
Reinstate Slack server
nickbeaird Aug 22, 2020
eb49661
Add in Cypress test framework
nickbeaird Aug 23, 2020
b735b24
Get a working test
nickbeaird Aug 25, 2020
26ed64f
Move from npm to yarn
nickbeaird Aug 25, 2020
1ccac6c
Downgrade package versions to work with react reqs
nickbeaird Aug 25, 2020
43b71d2
Add a working frontend unit test
nickbeaird Aug 25, 2020
42f766d
Get a working Cypress test
nickbeaird Aug 25, 2020
7ff41ec
Update the cypress test naming
nickbeaird Aug 25, 2020
07dde5a
Make all of the tests executable
nickbeaird Aug 25, 2020
afe32ae
Remove all hard coded env variables
nickbeaird Aug 27, 2020
dcaa1ad
Merge remote-tracking branch 'upstream/development' into add_frontend…
nickbeaird Aug 27, 2020
f82b003
Fix merge conflicts with npm vs yarn
nickbeaird Aug 27, 2020
e33cece
Add changes for better README
nickbeaird Aug 27, 2020
7f9815f
Add changes for review
nickbeaird Aug 28, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/node_modules

node_modules/
npm-debug.log
.DS_Store
/*.env
client/.env
.env
/.idea
test.db
globalConfig.json
videos/
screenshots/
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"workbench.colorCustomizations": {
"editorRuler.foreground": "#ff4081",
"activityBar.background": "#322F03",
"titleBar.activeBackground": "#464204",
"titleBar.activeForeground": "#FDFBE1"
}
}
59 changes: 43 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ VRMS is a tool used for the engagement, support, and retention of a network of v

This is an ambitious project to create a system that will help us measure our human capital development, reduce repetitive tasks and processes for leadership, and improve outcomes for both volunteers and the projects they contribute to.

### Project Context
## Project Context

We are currently in the initial planning phase after delivering a prototype to the organization's leadership. Our priorities are laying out a feature roadmap for beta and beyond, and recruiting a team of dedicated members to build the product. Time is of the essence, as each Hack Night is a new opportunity to garner valuable data which, in return, supports the organization and it's members.

### Technologies
## Technologies

This is a Full Stack web app, built with:
- [React](https://reactjs.org/docs/getting-started.html)
- Node/[Express](https://expressjs.com/en/starter/installing.html)
- [Node](https://nodejs.org/en/) / [Express](https://expressjs.com/en/starter/installing.html)
- [MongoDB](https://docs.mongodb.com/manual/tutorial/getting-started/)
- [Heroku](https://devcenter.heroku.com/categories/reference)

Expand Down Expand Up @@ -108,7 +108,7 @@ Star (`*`) indicates which branch you're on
git branch
```

By default you should start on the `master` branch.
By default you should start on the `develop` branch.

This command will (create and) change to a new branch:

Expand Down Expand Up @@ -140,28 +140,55 @@ git reset --hard vrms/master

## Get up and running

Do you have (Node)[https://nodejs.org/en/download/] and NPM installed?
1. Have [Node](https://nodejs.org/en/download/) and NPM installed locally:
- Verify with `node -v` and `npm -v` respectively.

Verify with `node -v` and `npm -v` respectively.
1. Install [Yarn](https://classic.yarnpkg.com/en/docs/install/#mac-stable): an improved package manager
- Verify with `yarn --version`

If you completed the Git steps above, you should be ready with your local fork loaded in your code editor of choice. Check your remotes again with `git remote -v` to make sure you're good to go.
1. Verify that you have the git remote repositories configured:
- Verify that the output of `git remote -v` shows your local repo as origin and the upstream vrms repo.

From the app root `vrms/`, run `npm install` to setup the `package.json` for the Node server, then `cd client/` and run `npm install` again to setup the `package.json` for the React front end. This might take a minute or two.
1. Install the node packages needed in each directory:
- `cd vrms/` and run `yarn install`
- `cd client` and run `yarn install`
- `cd ../backend` and run `yarn install`

Create `.env` files:
* in the project root folder `vrms/` for back-end.
* in the `vrms/client/` folder for front-end.
1. Add your required environment variables for the frontend and backend directories:
- `touch vrms/backend/.env`
- `touch vrms/client/.env`
- Then paste the content from the [document](https://docs.google.com/document/d/1yDF6UmyO-MPNrl3y_Mw0mkm_WaixlSkXzWbudCzHXDY/edit?usp=sharing). It is accessible for the project team members only.
- *Please note that the `ports` for the frontend and backend are set in this location*

Then paste the content from the [document](https://docs.google.com/document/d/1yDF6UmyO-MPNrl3y_Mw0mkm_WaixlSkXzWbudCzHXDY/edit?usp=sharing). It is accessible for the project team members only.
1. Take a second to review the `app.js` and `server.js` files in the `vrms/backend` folder. These two files are a blueprint for the back end, so please familiarize yourself with it. You'll see folders for the database collection models, routes for the API, and a config file which loads the necessary environment variables.

1. Start the local development servers (frontend & backend).
- Navigate to the root of the application `vrms/` and run `npm run dev`

Take a second to review the `server.js` file in the `vrms/` folder. It is a blueprint for the back end, so please familiarize yourself with it. You'll see folders for the database collection models, routes for the API, and a config file which loads the necessary environment variables.
You should now have a live app. Happy hacking.

Make sure you're at the app root, and run:
## Running Tests

`npm run dev-start`
The VRMS application has a variety of tests written for the application. Review the `package.json` file in any directory
and look for any variation of `test` scripts.

You should now have a live app. Happy hacking.
To run all of the tests run `npm run test:all` from the root folder.

## Configure your database

The application uses MongoDB and the team has a few databases for differing environments. Below are instructions on how to connect to the different databases used for development.

1. Staging test database: This database is maintained by the team. Post in the #vrms-dev channel to see who has access if you have any issues. This db has data useful for developming
1. Navigate to the [Get up and running](#get-up-and-running) section and find the credentials link.
1. Add the mongoDB credential listed in the `DATABASE_URL` variable to your `backend/.env` file.

1. Localhost test database: Create your own database on your laptop and connect to it. This database will be empty and you will need to add your own data. follow this [tutorial](https://zellwk.com/blog/local-mongodb/) for an in depth look on how to setup a local copy of mongodb.
1. Download mongoDB.
1. Setup a local mongoDB cluster.
1. Get the connection string.
1. Add your localhost connection string to the `DATABASE_URL` variable to your `backend/.env` file.

1. Test case in-memory-MongoDB: The unit tests and integration tests create and remove an in memory database on each test run. You should not need to connect to these test databases. See the `backend/README.md` for more information.


### Licensing *WIP*
Expand Down
55 changes: 55 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Backend

## Running Tests

To maintain consistency across the front end and back end development, we are using Jest
as a test runner.

### Execute Tests

You will need to be in the backend directory for this to work.

1. Run all tests: `npm test`
1. Run a single test: `npm test <testFileName>`

### Writing Tests

To maintain idempotent tests, we have opted to use in memory test databases. Jest, like
most test runners, has hooks or methods for you to call before or after tests. We can
call the `beforeAll` and `afterAll` methods setup and tear down our database before each
test.

```js
// You will need to require the db-handler file.
const dbHandler = require("./db-handler");

// Call the dbHanlder methods in your beforeAll and afterAll methods.
beforeAll(async () => await dbHandler.connect());
afterAll(async () => await dbHandler.closeDatabase());
```

In addition to hooks to call after the file is completed, Jest also has hooks/methods to
call before and after each test case. **At this time, the `dbHandler` method for clearing
the database does not work, so you can remove each collection manually if needed.

```js
// You will need to require the db-handler file.
const dbHandler = require("./db-handler");

// You will need to get the Model.
const Event = require("../models/event.model.js");

// Then you can delete the Collection in the db beforeAll or afterAll.
afterEach(async () => await Event.remove({}));
```

### Unit Tests

Unit tests are tests to write around a single unit. These can be tests around validation
of a Model, or testing the boundaries on a class.

### Integration Tests

Integration Tests are tests that verify that differing components work together. A common
example of an integration test is to verify that data is saved correctly in the database
based on the use of the API.
71 changes: 7 additions & 64 deletions server.js → backend/app.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
// server.js - Entry point for our application
// app.js - Entry point for our application

// Load in all of our node modules. Their uses are explained below as they are called.
const express = require("express");
require("dotenv").config();
const mongoose = require("mongoose");
const morgan = require("morgan");
const bodyParser = require("body-parser");
// const helmet = require('helmet');
// const cors = require('cors');
const path = require("path");
const cron = require("node-cron");
const fetch = require("node-fetch");
const morgan = require("morgan");
const path = require("path");

require("dotenv").config();

// Create a new application using the Express framework
const app = express();

// Load config variables
const { DATABASE_URL, PORT } = require("./config/database");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We refactored server.js into app.js and server.js. (see comments from above)


// Required to view Request Body (req.body) in JSON
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
Expand All @@ -31,9 +26,6 @@ app.use(morgan("dev"));
// Cross-Origin-Resource-Sharing
// app.use(cors());

// Let mongoose access Promises
mongoose.Promise = global.Promise;

// WORKERS
// const runOpenCheckinWorker = require("./workers/openCheckins")(cron, fetch);
// const runCloseCheckinWorker = require("./workers/closeCheckins")(cron, fetch);
Expand Down Expand Up @@ -64,7 +56,7 @@ app.use("/api/projects", projectsRouter);
app.use("/api/recurringevents", recurringEventsRouter);
app.use("/api/projectteammembers", projectTeamMembersRouter);
app.use("/api/slack", slackRouter);
const CLIENT_BUILD_PATH = path.join(__dirname, "./client/build");
const CLIENT_BUILD_PATH = path.join(__dirname, "../client/build");

// Serve static files from the React frontend app
app.use(express.static(path.join(CLIENT_BUILD_PATH)));
Expand All @@ -76,53 +68,4 @@ app.get("*", (req, res) => {
res.sendFile(index);
});

// Make the server functions available to testing
let server;

async function runServer(databaseUrl, port = PORT) {
await mongoose
.connect(databaseUrl, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: false,
})
.catch((err) => err);

server = app
.listen(port, () => {
console.log(
`Mongoose connected from runServer() and is listening on ${port}`
);
})
.on("error", (err) => {
mongoose.disconnect();
return err;
});
}

async function closeServer() {
await mongoose.disconnect().then(() => {
return new Promise((resolve, reject) => {
console.log("Closing Mongoose connection. Bye");

server.close((err) => {
if (err) {
return reject(err);
}

resolve();
});
});
});
}

if (require.main === module) {
runServer(DATABASE_URL).catch((err) => console.error(err));
}

// app.listen(process.env.PORT || PORT, () => {
// console.log(`Server is listening on port: ${process.env.PORT || PORT}`);
// });

module.exports = { app, runServer, closeServer };
module.exports = app;
2 changes: 2 additions & 0 deletions backend/config/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exports.PORT = process.env.BACKEND_PORT;
exports.DATABASE_URL = process.env.DATABASE_URL;
12 changes: 12 additions & 0 deletions backend/jest-mongodb-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
mongodbMemoryServerOptions: {
binary: {
version: "4.0.3",
skipMD5: true,
},
instance: {
dbName: "jest",
},
autoStart: false,
},
};
4 changes: 4 additions & 0 deletions backend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
testEnvironment: "node",
preset: "@shelf/jest-mongodb",
};
34 changes: 34 additions & 0 deletions backend/models/answer.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const mongoose = require("mongoose");

mongoose.Promise = global.Promise;

const answerSchema = mongoose.Schema({
question: {
questionId: { type: String },
htmlName: { type: String },
},
user: {
userId: { type: String },
},
selectedAnswer: { type: String },
createdDate: { type: Date, default: Date.now },
});

answerSchema.methods.serialize = function () {
return {
id: this._id,
question: {
questionID: this.question.questionId,
htmlName: this.question.htmlName,
},
user: {
userId: this.user.userId,
},
selectedAnswer: this.selectedAnswer,
createdDate: this.createdDate,
};
};

const Answer = mongoose.model("Answer", answerSchema);

module.exports = Answer;
24 changes: 24 additions & 0 deletions backend/models/checkIn.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const mongoose = require("mongoose");

mongoose.Promise = global.Promise;

const checkInSchema = mongoose.Schema({
userId: { type: String },
eventId: { type: String },
checkedIn: { type: Boolean, default: true },
createdDate: { type: Date, default: Date.now },
});

checkInSchema.methods.serialize = function () {
return {
id: this._id,
userId: this.userId,
eventId: this.eventId,
checkedIn: this.checkedIn,
createdDate: this.createdDate,
};
};

const CheckIn = mongoose.model("CheckIn", checkInSchema);

module.exports = CheckIn;
2 changes: 1 addition & 1 deletion models/event.model.js → backend/models/event.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ eventSchema.methods.serialize = function() {

const Event = mongoose.model('Event', eventSchema);

module.exports = { Event };
module.exports = Event;



Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ projectSchema.methods.serialize = function() {

const Project = mongoose.model('Project', projectSchema);

module.exports = { Project };
module.exports = Project
Loading