Skip to content

Commit

Permalink
Add tests, verify min/max/mean math (fix #35, fix #34)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcherny committed Nov 6, 2017
1 parent a3ec0c8 commit b1ddfa6
Show file tree
Hide file tree
Showing 8 changed files with 1,049 additions and 48 deletions.
21 changes: 21 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Contributing

## Install

```sh
# install git repo
git clone git@github.com:bayesimpact/tds-frontend.git
cd tds-frontend

# install dependencies
yarn

# recompile and re-run tests when anything changes
yarn run tdd
```

Then, open *https://localhost:8081* in your browser.

## Editor

I suggest editing this project using [VSCode](https://code.visualstudio.com/). VSCode will automatically suggest a small set of extensions that will surface type and lint errors directly in your editor. It will also auto-format files on save, reducing the need to manually fix lint errors.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ yarn build
yarn start
```

Then, open *https://localhost:9000* in your browser.
Then, open *https://localhost:8081* in your browser.

## Editor
## Tests

I suggest editing this project using [VSCode](https://code.visualstudio.com/).
```sh
yarn test
```

## License

Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"lint": "tslint src/**/*",
"pretest": "npm run build",
"start": "webpack-dev-server",
"tdd": "concurrently -k 'npm run start' 'npm run watch'",
"test": "echo 'no tests yet...' && exit 0",
"tdd": "concurrently -k 'jest dist/test.js --watch' 'npm run start' 'npm run watch'",
"test": "jest dist/test.js",
"watch": "webpack -w"
},
"dependencies": {
Expand All @@ -33,6 +33,7 @@
},
"devDependencies": {
"@types/chart.js": "^2.6.11",
"@types/jest": "^21.1.5",
"@types/lodash": "^4.14.79",
"@types/mapbox-gl": "^0.40.0",
"@types/material-ui": "^0.18.3",
Expand All @@ -46,7 +47,9 @@
"css-loader": "^0.28.7",
"dotenv-webpack": "^1.5.4",
"extract-text-webpack-plugin": "^3.0.1",
"glob": "^7.1.2",
"html-webpack-plugin": "^2.30.1",
"jest": "^21.2.1",
"postcss-cssnext": "^3.0.2",
"postcss-import": "^11.0.0",
"postcss-inline-svg": "^3.0.0",
Expand All @@ -59,4 +62,4 @@
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.3"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { filter, keyBy } from 'lodash'
import * as React from 'react'
import { withStore } from '../../../../services/store'
import { population } from '../../../../utils/analytics'
import { totalPopulation } from '../../../../utils/analytics'
import { representativePointsFromServiceAreas } from '../../../../utils/data'
import { StatsBox } from '../../../StatsBox/StatsBox'
import { AdequacyDoughnut } from './AdequacyDoughnut'
Expand All @@ -21,7 +21,7 @@ export let TotalAnalytics = withStore()(({ store }) => {
</tr>
<tr>
<td>{serviceAreas.length}</td>
<td>{population(representativePoints).toLocaleString()}</td>
<td>{totalPopulation(representativePoints).toLocaleString()}</td>
<td>{store.get('providers').length.toLocaleString()}</td>
</tr>
</StatsBox>
Expand Down
63 changes: 63 additions & 0 deletions src/utils/analytics.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { chain } from 'lodash'
import { averageDistance, averageTime, maxDistance, maxTime, minDistance, minTime, totalPopulation } from './analytics'

let adequacies1 = chain([
{ isAdequate: false, id: 0, distanceToClosestProvider: 10, timeToClosestProvider: 21, closestProviderByDistance: 63, closestProviderByTime: 63 },
{ isAdequate: false, id: 0, distanceToClosestProvider: 20, timeToClosestProvider: 31, closestProviderByDistance: 63, closestProviderByTime: 63 },
{ isAdequate: false, id: 0, distanceToClosestProvider: 30, timeToClosestProvider: 41, closestProviderByDistance: 63, closestProviderByTime: 63 },
{ isAdequate: false, id: 0, distanceToClosestProvider: 40, timeToClosestProvider: 51, closestProviderByDistance: 63, closestProviderByTime: 63 }
])

let adequacies2 = chain([
{ isAdequate: false, id: 0, distanceToClosestProvider: 0, timeToClosestProvider: 0, closestProviderByDistance: 63, closestProviderByTime: 63 },
{ isAdequate: false, id: 0, distanceToClosestProvider: 0, timeToClosestProvider: 0, closestProviderByDistance: 63, closestProviderByTime: 63 }
])

let representativePoints1 = chain([
{ county: 'Sonoma', id: 1, lat: 123.456, lng: 32.109, population: 100, serviceAreaId: 'Sonoma-90000', zip: '90000' },
{ county: 'Sonoma', id: 2, lat: 123.457, lng: 32.109, population: 101, serviceAreaId: 'Sonoma-90000', zip: '90001' },
{ county: 'Sonoma', id: 3, lat: 123.458, lng: 32.109, population: 200, serviceAreaId: 'Sonoma-90000', zip: '90002' },
{ county: 'Sonoma', id: 4, lat: 123.459, lng: 32.109, population: 102912, serviceAreaId: 'Sonoma-90000', zip: '90003' },
{ county: 'Sonoma', id: 5, lat: 123.460, lng: 32.109, population: 11, serviceAreaId: 'Sonoma-90000', zip: '90004' }
])

let representativePoints2 = chain([
{ county: 'Napa', id: 6, lat: 123.456, lng: 32.109, population: 0, serviceAreaId: 'Napa-90010', zip: '90010' },
{ county: 'Napa', id: 7, lat: 123.457, lng: 32.109, population: 0, serviceAreaId: 'Napa-90011', zip: '90011' },
{ county: 'Napa', id: 8, lat: 123.458, lng: 32.109, population: 0, serviceAreaId: 'Napa-90012', zip: '90012' }
])

test('averageDistance', () => {
expect(averageDistance(adequacies1)).toBe(25)
expect(averageDistance(adequacies2)).toBe(0)
})

test('maxDistance', () => {
expect(maxDistance(adequacies1)).toBe(40)
expect(maxDistance(adequacies2)).toBe(0)
})

test('minDistance', () => {
expect(minDistance(adequacies1)).toBe(10)
expect(minDistance(adequacies2)).toBe(0)
})

test('averageTime', () => {
expect(averageTime(adequacies1)).toBe(36)
expect(averageTime(adequacies2)).toBe(0)
})

test('maxTime', () => {
expect(maxTime(adequacies1)).toBe(51)
expect(maxTime(adequacies2)).toBe(0)
})

test('minTime', () => {
expect(minTime(adequacies1)).toBe(21)
expect(minTime(adequacies2)).toBe(0)
})

test('totalPoulation', () => {
expect(totalPopulation(representativePoints1)).toBe(103324)
expect(totalPopulation(representativePoints2)).toBe(0)
})
2 changes: 1 addition & 1 deletion src/utils/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ export let averageTime = mean<Adequacy>(_ => _.timeToClosestProvider)
export let maxTime = max<Adequacy>(_ => _.timeToClosestProvider)
export let minTime = min<Adequacy>(_ => _.timeToClosestProvider)

export let population = sum<RepresentativePoint>(_ => _.population)
export let totalPopulation = sum<RepresentativePoint>(_ => _.population)
10 changes: 8 additions & 2 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const Dotenv = require('dotenv-webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {
sync
} = require('glob')

module.exports = {
devtool: 'source-map',
Expand All @@ -11,9 +14,12 @@ module.exports = {
https: false,
port: 8081
},
entry: './src/index.tsx',
entry: {
bundle: './src/index.tsx',
test: sync('./src/**/*.test.ts')
},
output: {
filename: 'bundle.js',
filename: '[name].js',
path: __dirname + '/dist'
},
resolve: {
Expand Down
Loading

0 comments on commit b1ddfa6

Please sign in to comment.