Skip to content

Commit

Permalink
Merge pull request #4 from agl0809/develop
Browse files Browse the repository at this point in the history
Data source settings extended
  • Loading branch information
agl0809 committed Feb 3, 2018
2 parents e76adf4 + 315d173 commit 7fcca7c
Show file tree
Hide file tree
Showing 17 changed files with 325 additions and 276 deletions.
74 changes: 51 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,65 @@
[![Build Status](https://travis-ci.org/agl0809/location-history-player.svg?branch=master)](https://travis-ci.org/agl0809/location-history-player)

# Location History Player
Using ES6 and Test-driven development (TDD) to display a heat map through the location history provided by Google Maps Timeline.

## Table of Contents

- [Available Scripts](#available-scripts)
- [Installation](#installation)
- [Settings](#settings)
- [Available scripts](#available-scripts)
- [npm start](#npm-start)
- [npm test](#npm-test)
- [npm run build](#npm-run-build)
- [npm run eject](#npm-run-eject)
- [Dependencies](#scaffolding)
- [Scaffolding](#scaffolding)


## Installation
```bash
git clone https://github.com/agl0809/location-history-player/
cd location-history-player
npm install
```

## Settings
There are two different ways to setting up the data provided in **constants.js**<br>

[Firebase service](https://api-project-923029851043.firebaseio.com/locations.json)<br>
By default Firebase service example will be used.
```javascript
export const JSON_FILE_URL = 'https://api-project-923029851043.firebaseio.com/locations.json';
```

## Available Scripts
[Google Takeout](https://takeout.google.com/settings/takeout)<br>
Use a specific data file downloading the location history JSON file. Then move it to `/public` project folder .<br>
```javascript
export const JSON_FILE_URL = '/YOUR_FILE_NAME.json';
```

## Available scripts
In the project directory, you can run:

### `npm start`
**npm start**<br>
Runs the app in the development mode.

Open [http://localhost:3000](http://localhost:3000) to view it in the browser.<br>
The page will reload if you make edits.You will also see any lint errors in the console.

**npm test**<br>
Launches the test runner in the interactive watch mode.

**npm run build**<br>
Builds the app for production to the `build` folder.

It correctly bundles React in production mode and optimizes the build for the best performance.<br>
The build is minified and the filenames include the hashes.

## Dependencies
[leaflet](https://github.com/Leaflet/Leaflet)
[leaflet.heat](https://github.com/Leaflet/Leaflet.heat)

Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
## Scaffolding
[create-react-app](https://github.com/facebook/create-react-app)

The page will reload if you make edits.<br>
You will also see any lint errors in the console.

### `npm test`

Launches the test runner in the interactive watch mode.<br>
See the section about [running tests](#running-tests) for more information.

### `npm run build`

Builds the app for production to the `build` folder.<br>
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!

See the section about [deployment](#deployment) for more information.
40 changes: 20 additions & 20 deletions __tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@ import * as locationHistoryController from 'js/locationHistoryController';
import * as MapController from 'js/mapController';

describe('running up the app', () => {
it('spec name', () => {
const coordsResponse = [['any coordinates pair']];
const expectedMapOptions = {
containerId: HEATMAP_CONTAINER_ID,
coordinates: coordsResponse,
mapOptions: LEAFLET_OPTIONS,
heatLayerOptions: HEAT_OPTIONS
};
it('spec name', () => {
const coordsResponse = [['any coordinates pair']];
const expectedMapOptions = {
containerId: HEATMAP_CONTAINER_ID,
coordinates: coordsResponse,
mapOptions: LEAFLET_OPTIONS,
heatLayerOptions: HEAT_OPTIONS
};

locationHistoryController.getCoordinates = jest.fn(() =>
new Promise((resolve) => {
process.nextTick(
() => resolve(coordsResponse)
);
})
locationHistoryController.getCoordinates = jest.fn(() =>
new Promise((resolve) => {
process.nextTick(
() => resolve(coordsResponse)
);
})
);

MapController.renderHeatMap = jest.fn();
MapController.renderHeatMap = jest.fn();

start();
start();

expect(locationHistoryController.getCoordinates).toBeCalledWith(JSON_FILE_URL);
return locationHistoryController.getCoordinates(JSON_FILE_URL).then(() => {
expect(MapController.renderHeatMap).toBeCalledWith(expectedMapOptions);
});
expect(locationHistoryController.getCoordinates).toBeCalledWith(JSON_FILE_URL);
return locationHistoryController.getCoordinates(JSON_FILE_URL).then(() => {
expect(MapController.renderHeatMap).toBeCalledWith(expectedMapOptions);
});
});
});
33 changes: 33 additions & 0 deletions __tests__/locationHistoryParser.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {locationHistoryParser} from 'js/locationHistoryParser';

describe('parsing a service response', () => {

describe('retrieving a valid string containing an array of objects', function () {
it('should return an array of coordinates parsed properly', () => {
const SCALAR_E7 = 0.0000001;
const latOne = 1;
const lonOne = 1;
const fileContent = '[{"latitudeE7": ' + latOne + ',"longitudeE7": ' + lonOne + '}]';
const expectedObject = [[latOne * SCALAR_E7, lonOne * SCALAR_E7]];

const response = locationHistoryParser(fileContent);

expect(response).toEqual(expectedObject);
});
});

describe('retrieving a valid string containing an object with locations key', function () {
it('should return an array of coordinates parsed properly', () => {
const SCALAR_E7 = 0.0000001;
const latOne = 1;
const lonOne = 1;
const fileContent = '{"locations": [{"latitudeE7": ' + latOne + ',' +
'"longitudeE7": ' + lonOne + '}]}';
const expectedObject = [[latOne * SCALAR_E7, lonOne * SCALAR_E7]];

const response = locationHistoryParser(fileContent, SCALAR_E7);

expect(response).toEqual(expectedObject);
});
});
});
41 changes: 20 additions & 21 deletions __tests__/locationhistoryController.test.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import {getCoordinates} from 'js/locationHistoryController';
import * as serviceDep from 'js/service';
import * as parserDep from 'js/timeLineParser'
import * as parserDep from 'js/locationHistoryParser'
import {SCALAR_E7} from 'helpers/constants';

describe('locationHistoryController', () => {
it('should read the file content', function () {
const fileContent = 'any file content';
const JSONFileUrl = 'anyURL';
const expectedCoords = [['any coordinates pair']];
let promise;

it('should read the file content', function () {
const fileContent = 'any file content';
const JSONFileUrl = 'anyURL';
const expectedCoords = [['any coordinates pair']];
let controller, timeLineParser, promise;

serviceDep.service = jest.fn(() => {
return new Promise((resolve, reject) => {
process.nextTick(
() => resolve(fileContent)
);
});
});
serviceDep.service = jest.fn(() => {
return new Promise((resolve, reject) => {
process.nextTick(
() => resolve(fileContent)
);
});
});

parserDep.timeLineParser = jest.fn(() => expectedCoords);
parserDep.locationHistoryParser = jest.fn(() => expectedCoords);

promise = getCoordinates(JSONFileUrl);
promise = getCoordinates(JSONFileUrl);

expect.assertions(2);
expect.assertions(2);

return promise.then((data) => {
expect(serviceDep.service).toBeCalledWith(JSONFileUrl);
expect(parserDep.timeLineParser).toBeCalledWith(fileContent, SCALAR_E7);
});
return promise.then((data) => {
expect(serviceDep.service).toBeCalledWith(JSONFileUrl);
expect(parserDep.locationHistoryParser).toBeCalledWith(fileContent, SCALAR_E7);
});
});
})
102 changes: 51 additions & 51 deletions __tests__/map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,55 @@ import LeafMap from "leaflet";
import * as Map from 'js/map';

describe('drawing a map', () => {
it('should create a map', () => {
const HEATMAP_CONTAINER_ID = 'any id';
const CENTER_COORDS = 'any coords';
const ZOOM_LEVEL = 'any zoom';
const TILE_LAYER_OPTIONS = {
attribution: 'any attribution',
maxZoom: 'any max zoom',
minZoom: 'any min zoom'
};
const URL_TEMPLATE = 'any urlTemplate';
const mapOptions = {
CENTER_COORDS,
ZOOM_LEVEL,
URL_TEMPLATE,
TILE_LAYER_OPTIONS
};

const MockSetView = {setView: jest.fn()};
const MockAddTo = {addTo: jest.fn()};
LeafMap.map = jest.fn(() => MockSetView);
LeafMap.tileLayer = jest.fn(() => MockAddTo);

Map.createMap(HEATMAP_CONTAINER_ID, mapOptions);

expect(LeafMap.map).toBeCalledWith(HEATMAP_CONTAINER_ID);
expect(MockSetView.setView).toBeCalledWith(CENTER_COORDS, ZOOM_LEVEL);
expect(LeafMap.tileLayer).toBeCalledWith(URL_TEMPLATE, TILE_LAYER_OPTIONS);
});

it('should create a heat layer on the map using the coordenates received', () => {
const heatOptions = {
tileOpacity: 'any tileOpacity',
heatOpacity: 'any heatOpacity',
radius: 'any radius',
blur: 'any blur'
};
const coords = ['any lat', 'any lon'];
const mapInstance = {};

const MockAddTo = {addTo: jest.fn()};
LeafMap.heatLayer = jest.fn(() => MockAddTo);

const MockHeatMap = {redraw: jest.fn()};
MockAddTo.addTo.mockReturnValue(MockHeatMap);

Map.createHeatMap(mapInstance, coords, heatOptions);

expect(LeafMap.heatLayer).toBeCalledWith(coords, heatOptions);
expect(MockAddTo.addTo).toBeCalledWith(mapInstance);
expect(MockHeatMap.redraw).toBeCalled();
});
it('should create a map', () => {
const HEATMAP_CONTAINER_ID = 'any id';
const CENTER_COORDS = 'any coords';
const ZOOM_LEVEL = 'any zoom';
const TILE_LAYER_OPTIONS = {
attribution: 'any attribution',
maxZoom: 'any max zoom',
minZoom: 'any min zoom'
};
const URL_TEMPLATE = 'any urlTemplate';
const mapOptions = {
CENTER_COORDS,
ZOOM_LEVEL,
URL_TEMPLATE,
TILE_LAYER_OPTIONS
};

const MockSetView = {setView: jest.fn()};
const MockAddTo = {addTo: jest.fn()};
LeafMap.map = jest.fn(() => MockSetView);
LeafMap.tileLayer = jest.fn(() => MockAddTo);

Map.createMap(HEATMAP_CONTAINER_ID, mapOptions);

expect(LeafMap.map).toBeCalledWith(HEATMAP_CONTAINER_ID);
expect(MockSetView.setView).toBeCalledWith(CENTER_COORDS, ZOOM_LEVEL);
expect(LeafMap.tileLayer).toBeCalledWith(URL_TEMPLATE, TILE_LAYER_OPTIONS);
});

it('should create a heat layer on the map using the coordenates received', () => {
const heatOptions = {
tileOpacity: 'any tileOpacity',
heatOpacity: 'any heatOpacity',
radius: 'any radius',
blur: 'any blur'
};
const coords = ['any lat', 'any lon'];
const mapInstance = {};

const MockAddTo = {addTo: jest.fn()};
LeafMap.heatLayer = jest.fn(() => MockAddTo);

const MockHeatMap = {redraw: jest.fn()};
MockAddTo.addTo.mockReturnValue(MockHeatMap);

Map.createHeatMap(mapInstance, coords, heatOptions);

expect(LeafMap.heatLayer).toBeCalledWith(coords, heatOptions);
expect(MockAddTo.addTo).toBeCalledWith(mapInstance);
expect(MockHeatMap.redraw).toBeCalled();
});
});
Loading

0 comments on commit 7fcca7c

Please sign in to comment.