Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 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
cc9c59f
Merge branch 'development' into add_jest_from_develop
nickbeaird Aug 27, 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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/node_modules

node_modules/
npm-debug.log
.DS_Store
/*.env
client/.env
.env
/.idea
test.db
globalConfig.json
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"
}
}
46 changes: 31 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ 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)
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,44 @@ 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/] installed locally:
- Verify with `node -v` and `npm -v` respectively.

Verify with `node -v` and `npm -v` respectively.
1. Verify that you have the git remote repositories configured:
- Verify that the output of `git remote -v` shows your local repo and the upstream vrms repo.

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. Install the node packages needed in each directory:
- `cd vrms/` and run `npm install`
- `cd client` and run `npm install`
- `cd ../backend` and run `npm install`

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. Create `.env` files in both 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.

Create `.env` files:
* in the project root folder `vrms/` for back-end.
* in the `vrms/client/` folder for front-end.
1. Take a second to review the `server.js` file in the `vrms/backend` 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.

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. Start the local development servers (frontend & backend).
- Navigate to the root of the application `vrms/` and run `npm run dev-start`

You should now have a live app. Happy hacking.

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.
## Configure your database

Make sure you're at the app root, and run:
The application uses MongoDB and the team has a few databases dependent on the environment. Below are instructions on how to connect to the different databases used for development.

`npm run dev-start`
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.

You should now have a live app. Happy hacking.
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");

// 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;
File renamed without changes.
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,10 @@ Idea for the future: numberGithubContributions (pull this from github?)
*/

const projectTeamMemberSchema = mongoose.Schema({
userId: { // id of the user
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
projectId: { // id of the project
type: mongoose.Schema.Types.ObjectId,
ref: 'Project'
},
teamMemberStatus: { type: String, default: "Active" }, // Active or Inactive
vrmsProjectAdmin: { type: Boolean, default: false }, // does this team member have admin rights to the project in VRMS?
userId: { type: String }, // id of the user
projectId: { type: String }, // id of the project
teamMemberStatus: { type: String }, // Active or Inactive
vrmsProjectAdmin: { type: Boolean }, // does this team member have admin rights to the project in VRMS?
roleOnProject: { type: String }, // Developer, Project Manager, UX, Data Science
joinedDate: { type: Date, default: Date.now }, // date/time joined project
leftDate: { type: Date }, // only if Status = Inactive, date/time went inactive
Expand All @@ -33,7 +27,6 @@ const projectTeamMemberSchema = mongoose.Schema({
onProjectGithub: { type: Boolean, default: false }, // added to the project team on github? pull from github api?
onProjectGoogleDrive: { type: Boolean, default: false} // added to the project team's google drive folder?
});

projectTeamMemberSchema.methods.serialize = function() {
return {
id: this._id,
Expand All @@ -53,4 +46,4 @@ projectTeamMemberSchema.methods.serialize = function() {

const ProjectTeamMember = mongoose.model('ProjectTeamMember', projectTeamMemberSchema);

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