Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add deployed url #1

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
30 changes: 26 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Motherbrain API

Galvanize staff, student, and cohort API aggregator. Uses:
Galvanize staff, student, and cohort API aggregator.

Deployed URL: http://galvanize-motherbrain.herokuapp.com/

Uses:

## Technologies

Expand All @@ -13,32 +17,50 @@ Galvanize staff, student, and cohort API aggregator. Uses:

## Setup

1. `yarn` or `npm install
1. `yarn` or `npm install`
1. Copy `.env.example` to `.env` and replace the values
1. `createdb motherbrain`
1. `npm run migrate && npm run seed` to populate the database
1. `npm start` to run production build
1. `npm run dev` to run locally

## Testing
Testing can be setup using:

1. `createdb motherbrain-test`
1. `createdb learn`
1. `npm run migrate:test && npm run seed:test`
1. `npm run migrate:dev && npm run seed:dev`

## Testing

* Mocha/Chai and Sinon for unit and integration testing
* Supertest for acceptance testing
1. `npm test` to run all tests
1. `npm run [test-level]` to run individual test levels, where [level] is `unit`|`integration`|`acceptance`
1. `npm run find-test || [search-term]` to grep for specific tests
1. `npm run find-test [search-term]` to grep for specific tests

## Endpoints

### Business Units

Business Units are programs: Denver WDI (1), Boulder WDI (2), etc.

* `/api/v1/business-units`
* `/api/v1/business-units/:business_unit_id`
* `/api/v1/business-units/:business_unit_id/cohorts`
* `/api/v1/business-units/:business_unit_id/cohorts/:cohort_id`

### Cohorts

* `/api/v1/cohorts/:cohort_id`

### Students

* `/api/v1/students`
* `/api/v1/students/:student_id`
* `/api/v1/business-units/:business_unit_id/cohorts/:cohort_id/students`
* `/api/v1/cohorts/:cohort_id/students`

### Standards

* `/api/v1/standards`
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/students.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@ module.exports = {
single: function(request, response){
Student.getOne(request.params.student_id)
.then(respond.bind(null, request, response));
},
byCohort: function(request, response){
Student.getByCohort(request.params.cohort_id)
.then(respond.bind(null, request, response));
}
}
6 changes: 5 additions & 1 deletion app/models/Cohort.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
var LearnCohort = require("./LearnCohort");
var LocalCohort = require("./LocalCohort");
var Student = require("./Student");
var {Model} = require("objection");
var {find, map} = require("lodash");
var deserializeLearnCohort = require("./deserializers/learn-cohort");

class Cohort extends Model {
static getOne(id){
return LocalCohort.getOne(id)
return LocalCohort.getOneByLearnId(id)
.then(localCohort => {
return LearnCohort.getOne(localCohort.learn_id)
.then(deserializeLearnCohort)
Expand All @@ -29,6 +30,9 @@ class Cohort extends Model {
.then(this.getSome.bind(this))
.catch(console.error);
}
static getStudents(id) {
return Student.getByCohort(id);
}
}

function combineCohorts(localCohorts, learnCohorts){
Expand Down
32 changes: 32 additions & 0 deletions app/models/Enrollment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var {Model} = require("objection");

class Enrollment extends Model {
static get tableName(){
return "enrollments";
}
static get columns(){
return [
"id",
"user_id",
"cohort_id"
];
}
static getAll(){
return this.query()
.select(this.columns);
}
static getOne(id){
return this.query()
.select(this.columns)
.where("id", id)
.first();
}
static byCohort(id) {
return this.query()
.pluck("user_id")
.where("cohort_id", id);
}
}
Enrollment.knex(require("../../database/learn_connection"));

module.exports = Enrollment;
6 changes: 6 additions & 0 deletions app/models/LocalCohort.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ class LocalCohort extends Model {
.where("id", id)
.first();
}
static getOneByLearnId(id){
return this.query()
.select(this.columns)
.where("learn_id", id)
.first();
}
static getSome(ids){
return this.query()
.select(this.columns)
Expand Down
12 changes: 12 additions & 0 deletions app/models/Student.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var {Model} = require("objection");

var Enrollment = require("./Enrollment");

class Student extends Model {
static get tableName(){
return "users";
Expand Down Expand Up @@ -28,6 +30,16 @@ class Student extends Model {
.where("id", id)
.first();
}
static getSome(ids){
return this.query()
.select(this.columns)
.whereIn("id", ids);
}
static getByCohort(id) {
return Enrollment.byCohort(id)
.then(studentIds => this.getSome(studentIds))
.catch(console.error);
}
}
Student.knex(require("../../database/learn_connection"));

Expand Down
4 changes: 4 additions & 0 deletions app/routes/business-units.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ var express = require("express");
var router = express.Router();
var businessUnitController = require("../controllers/business-units");
var cohortController = require("../controllers/cohorts");
var studentController = require("../controllers/students");

router.get("/", businessUnitController.multiple);
router.get("/:business_unit_id", businessUnitController.single);
router.get("/:business_unit_id/cohorts", cohortController.byBusinessUnit);
router.get("/:business_unit_id/cohorts/:cohort_id", cohortController.single);
router.get("/:business_unit_id/cohorts/:cohort_id/students", studentController.byCohort);

module.exports = router;
5 changes: 4 additions & 1 deletion app/routes/cohorts.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
var express = require("express");
var router = express.Router();
var cohortController = require("../controllers/cohorts");
var studentController = require("../controllers/students");

router.get("/:cohort_id", require("../controllers/cohorts").single);
router.get("/:cohort_id", cohortController.single);
router.get("/:cohort_id/students", studentController.byCohort);

module.exports = router;
14 changes: 14 additions & 0 deletions database/learn_migrations/20170818155845_enrollments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

exports.up = function(knex, Promise) {
return knex.schema.createTable("enrollments", function(table){
table.increments();
table.integer("user_id").references("id").inTable("users");
table.integer("cohort_id").references("id").inTable("cohorts");
table.timestamp("created_at");
table.timestamp("updated_at");
});
};

exports.down = function(knex, Promise) {
return knex.schema.dropTableIfExists("enrollments");
};
21 changes: 21 additions & 0 deletions database/learn_seeds/06-enrollments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
exports.seed = function(knex, Promise){
return knex.schema.raw("TRUNCATE TABLE \"enrollments\" RESTART IDENTITY CASCADE")
.then(function(){
return knex("enrollments").insert([{
created_at: "2017-01-01 01:01:01.111111",
updated_at: "2017-01-01 01:01:01.111111",
user_id: 1,
cohort_id: 1
},{
created_at: "2017-01-01 01:01:01.111111",
updated_at: "2017-01-01 01:01:01.111111",
user_id: 1,
cohort_id: 2
},{
created_at: "2017-01-01 01:01:01.111111",
updated_at: "2017-01-01 01:01:01.111111",
user_id: 2,
cohort_id: 1
}]);
});
};
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
"integration": "./node_modules/mocha/bin/mocha -wG --recursive --no-exit tests/integration",
"acceptance": "./node_modules/mocha/bin/mocha -wG --recursive --no-exit tests/acceptance",
"migrate": "./node_modules/knex/bin/cli.js migrate:latest",
"migrate:test": "./node_modules/knex/bin/cli.js migrate:latest --env test",
"migrate:dev": "./node_modules/knex/bin/cli.js migrate:latest --env learn_development",
"seed": "./node_modules/knex/bin/cli.js seed:run",
"seed:test": "./node_modules/knex/bin/cli.js seed:run --env test",
"seed:dev": "./node_modules/knex/bin/cli.js seed:run --env learn_development",
"reset-test-data": "knex seed:run --env test && knex seed:run --env learn_development"
},
"dependencies": {
Expand Down
13 changes: 13 additions & 0 deletions tests/acceptance/business-units.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const request = require("supertest");
const execute = require("child_process").exec;

const businessUnitFixtures = require("../fixtures/business-units");
const studentsFixture = require("../fixtures/students");

process.env.NODE_ENV = "test";
const VERSION = "/api/v1";
Expand Down Expand Up @@ -37,4 +38,16 @@ describe("acceptance - /business-units", function(){
}).catch(done);
});
});

describe("#GET /business-units/:id/cohorts/:cohort_id/students", function(){
it("displays a list of cohorts' students", done => {
request(app)
.get(`${VERSION}/business-units/1/cohorts/1/students`)
.expect(200)
.then(response => {
assert.deepEqual(response.body.data, studentsFixture.JSONAPI.cohort1Students.data);
done();
}).catch(done);
});
});
});
12 changes: 12 additions & 0 deletions tests/acceptance/cohorts.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ process.env.NODE_ENV = "test";
const VERSION = "/api/v1";

const app = require("../../app/index");
const studentsFixture = require("../fixtures/students");

describe("acceptance - /cohorts", function(){
before(done => {
Expand Down Expand Up @@ -142,4 +143,15 @@ describe("acceptance - /cohorts", function(){
}).catch(done);
});
});
describe("#GET /cohorts/:id/students", function(){
it("displays a list of cohorts' students", done => {
request(app)
.get(`${VERSION}/cohorts/1/students`)
.expect(200)
.then(response => {
assert.deepEqual(response.body.data, studentsFixture.JSONAPI.cohort1Students.data);
done();
}).catch(done);
});
});
});
42 changes: 42 additions & 0 deletions tests/fixtures/students.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module.exports = {
raw: [

],
JSONAPI: {
// Ex: /cohorts/1/students
cohort1Students: {
data: [
{
"type": "students",
"id": "1",
"attributes": {
"first-name": "Kyle",
"last-name": "Coberly",
"email": "[email protected]",
"phone": "777-777-7777",
"twitter": "kylecoberly",
"github": "kylecoberly",
"linkedin": "kylecoberly",
"galvanize-id": 1,
"avatar": "https://www.google.com"
}
},
{
"type": "students",
"id": "2",
"attributes": {
"first-name": "Danny",
"last-name": "Fritz",
"email": "[email protected]",
"phone": "777-777-7777",
"twitter": "dannyfritz",
"github": "dannyfritz",
"linkedin": "dannyfritz",
"galvanize-id": 2,
"avatar": "https://www.google.com"
}
}
]
}
}
}