Skip to content

Latest commit

 

History

History
236 lines (171 loc) · 6.2 KB

File metadata and controls

236 lines (171 loc) · 6.2 KB

Project to demonstrate a small REST-based service to retrieve weather information in different cities using the following technologies:

Main project structure:

.
├── app
│   ├── Dockerfile
│   ├── configs
│   ├── controllers
│   ├── lib
│   ├── resources
│   ├── routes
│   ├── services
│   ├── tests
│   │   └── unit
│   └── validations
├── docker-compose.yml
└── integration
    ├── Dockerfile
    └── features

Install

git clone https://github.com/isena/demo-node-docker-test.git

In app directory:

npm install

Set environment variables

.env

cp .env.example .env

API Key

The weather endpoint uses data from [openweathermap.org]. Go to [openweathermap.org/api], subscribe (for free) and get an API Key to replace <<<API_KEY_VALUE_HERE>>> in the following command:

export APP_WEATHER_API_KEY="<<<API_KEY_VALUE_HERE>>>"

Start

npm start

To monitor changes and restart automatically:

npm run start:watch

And you are ready! Visit some city to check, e.g., http://localhost:5000/cities/2873891

Test

Unit

In app directory:

npm test

To monitor changes and restart automatically:

npm run test:watch

Integration

Install

In integration directory:

npm install

Set environment variable

When running locally, set APP_HOST:

export APP_HOST="localhost"

Run

With the service running, run the following command:

npm test

To monitor changes and restart automatically:

npm run test:watch

Docker Compose

This may be the simplest way to run the project. After setting the environment variables, just run the following command:

docker-compose up

and the service will be started and the integration tests will be executed.

Docker (without compose)

In app directory:

  • Build:
docker build -t demo-weather:0.0.1 .
  • Run
export APP_WEATHER_API_KEY="<<<API_KEY_VALUE_HERE>>>"
export APP_HOST="demo-weather-api"

docker run \
  --env APP_WEATHER_API_KEY=$APP_WEATHER_API_KEY \
  -p 5000:5000 \
  --name $APP_HOST \
  -ti --rm  demo-weather:0.0.1

Integration tests

In integration directory:

  • Build:
docker build -t demo-weather-integration-tests:0.0.1 .
  • Run
export APP_HOST="demo-weather-api"

docker run \
  --env APP_HOST=$APP_HOST \
  --name integration \
  --link $APP_HOST:integration \
  -ti  --rm  demo-weather-integration-tests:0.0.1

Routes

GET /cities?lat={latitude}&lng={longitude}

  • HTTP 200 Ok with body:
➜  ~ curl http://localhost:5000/cities\?lat\=49.48\&lng\=8.46
[{"id":2864869,"name":"Neuhofen","country":"DE","coord":{"lon":8.42472,"lat":49.42778}},...]
  • HTTP 400 Bad Request if parameters are missing:
➜  ~ curl http://localhost:5000/cities\?lat\=\&lng\=
{"status":"error","message":"lat/lng required","code":"BadRequestError"}

GET /cities/{city_id}

  • HTTP 200 Ok with body:
➜  ~ curl http://localhost:5000/cities/2873891
{"id":2873891,"name":"Mannheim","country":"DE","coord":{"lon":8.46472,"lat":49.488331}}
  • HTTP 404 Not Found if the city_id was not found:
➜  ~ curl http://localhost:5000/cities/99999999
{"status":"error","message":"not found","code":"NotFoundError"}

GET /cities/{city_id}/weather

  • HTTP 200 Ok with body:
➜  ~ curl http://localhost:5000/cities/2867310/weather
{"coord":{"lon":8.36,"lat":49.44},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":288.15,"pressure":1017,"humidity":87,"temp_min":285.93,"temp_max":290.37},"visibility":10000,"wind":{"speed":3.6,"deg":210},"clouds":{"all":0},"dt":1565567145,"sys":{"type":1,"id":1265,"message":0.0076,"country":"DE","sunrise":1565583171,"sunset":1565635839},"timezone":7200,"id":2867310,"name":"Mutterstadt","cod":200}
  • HTTP 404 Not Found if the city_id was not found:
➜  ~ curl http://localhost:5000/cities/99999999/weather
{"status":"error","message":"not found","code":"NotFoundError"}

ToDo

Main dependencies

  • restify: web service framework for building RESTful web services;
  • winston: logging library;
  • joi: Object schema validation;
  • standard: JavaScript style guide, linter, and formatter;
  • dotenv: module that loads environment variables from a .env file into process.env;
  • cucumber: tool for running automated tests written in plain language. We use here for integration tests;
  • jest: JavaScript testing framework. Used here for unit testing;
  • geolib: Library to provide basic geospatial operations. Although the formula used to measure the distance between two geospatial coordinates is not complex (see Haversine formula: https://en.wikipedia.org/wiki/Haversine_formula), this robust library already abstract the calculations. "Why would we reinvent the wheel?".

License

ISC