Some Error handling and acceptance tests
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ Homestead.yaml
|
||||
.env
|
||||
|
||||
tests/_output/*
|
||||
/public/docs/
|
||||
/build/
|
||||
|
||||
8
apidoc.json
Executable file
8
apidoc.json
Executable file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Trip Builder",
|
||||
"version": "0.1.0",
|
||||
"description": "API for Trip Builder",
|
||||
"title": "... API v1",
|
||||
"url" : "http://localhost:8080",
|
||||
"sampleUrl" : "http://localhost:8080"
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Libraries\IotaCodes\Airport;
|
||||
use App\Libraries\IotaCodes\AirportTransformer;
|
||||
use App\Libraries\IotaCodes\Client;
|
||||
use App\Libraries\IotaCodes\Client as IotaClient;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
@@ -18,33 +18,27 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
class AirportController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch list of airports
|
||||
*
|
||||
* @api {get} /airports
|
||||
* @api {get} /airports list airports
|
||||
* @apiName List Airports
|
||||
* @apiGroup Airports
|
||||
* @apiDescription Fetch list of airports
|
||||
*
|
||||
* @apiParam (pagination) {number} [page] page number to display
|
||||
* @apiParam (pagination) {number} [per_page] number of items to display on the page
|
||||
* @apiParam (query param) {number} [page=1] page number to display
|
||||
* @apiParam (query param) {number} [per_page=10] number of items to display on the page
|
||||
*
|
||||
* @apiParam (autocomplete) {string} [autocomplete] string to try and autocomplete
|
||||
* @apiParam (query param) {string} [autocomplete] string to try and autocomplete
|
||||
*
|
||||
* @apiExample {curl} example
|
||||
* curl -i http://localhost:8080/airports?page=1&per_page=10&autocomplete=aar
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function resourceList(Request $request)
|
||||
{
|
||||
$client = Client::create();
|
||||
$client = IotaClient::create();
|
||||
$collection = $client->listAirports($request->input('autocomplete'));
|
||||
|
||||
//add pagination
|
||||
@@ -64,12 +58,15 @@ class AirportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Get details of an airport by it's code
|
||||
* @api {get} /airports/:code get airport
|
||||
* @apiName Get Airport
|
||||
* @apiGroup Airports
|
||||
* @apiDescription Get details of an airport by it's code
|
||||
*
|
||||
* @api {get} /airports/:code
|
||||
* @apiName Get Airport from code
|
||||
* @apiParam (query param) {string} code 3 letter airport code
|
||||
*
|
||||
* @apiParam {string} code 3 letter airport code
|
||||
* @apiExample {curl} example
|
||||
* curl -i http://localhost:8080/airports/YUL
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param $code
|
||||
@@ -77,27 +74,15 @@ class AirportController extends Controller
|
||||
*/
|
||||
public function getAirport(Request $request, $code)
|
||||
{
|
||||
$client = Client::create();
|
||||
$client = IotaClient::create();
|
||||
|
||||
$result = $client->getAirport($code);
|
||||
$result = new Item($result, new AirportTransformer(), 'airports');
|
||||
$airport = $client->getAirport($code);
|
||||
if (is_null($airport)) {
|
||||
return $this->returnErrorMessage('not a valid airport code', 400);
|
||||
}
|
||||
|
||||
$result = new Item($airport, new AirportTransformer(), 'airports');
|
||||
|
||||
return $this->JsonApiResponse($result, 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the response to Json
|
||||
*
|
||||
* @param \League\Fractal\Resource\Item $resource
|
||||
* @param $statusCode
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function JsonApiResponse(ResourceInterface $resource, $statusCode)
|
||||
{
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new JsonApiSerializer('http://docker.dev:8080'));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray(), $statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,40 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Laravel\Lumen\Routing\Controller as BaseController;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\ResourceInterface;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
//
|
||||
/**
|
||||
* Convert the response to Json
|
||||
*
|
||||
* @param \League\Fractal\Resource\Item $resource
|
||||
* @param int $statusCode
|
||||
* @param string $includes
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function JsonApiResponse(ResourceInterface $resource, $statusCode, $includes = '')
|
||||
{
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new JsonApiSerializer('http://docker.dev:8080'));
|
||||
$manager->parseIncludes($includes);
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray(), $statusCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* format an error message
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $statusCode
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function returnErrorMessage($message, $statusCode = 400)
|
||||
{
|
||||
return response()->json([
|
||||
'error_message' => $message
|
||||
], $statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ use App\Libraries\Trips\Models\Flights;
|
||||
use App\Libraries\Trips\Models\Trips;
|
||||
use App\Libraries\Trips\TripTransformer;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\ResourceInterface;
|
||||
@@ -16,62 +18,90 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
class FlightController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
* @api {get} /flights list flights
|
||||
* @apiName List Flights
|
||||
* @apiGroup Flights
|
||||
* @apiDescription List all defined flights
|
||||
*
|
||||
* @return void
|
||||
* @apiParam (query params) {number} [page=1] page to fetch
|
||||
* @apiParam (query param) {number} [per_page=10] number of results to fetch per page
|
||||
*
|
||||
* @apiExample {curl} example
|
||||
* curl -i http://localhost:8080/flights?page=1&per_page=10
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function listFlights(Request $request)
|
||||
{
|
||||
$flightCollection = Flights::all();
|
||||
//TODO: add pagination
|
||||
|
||||
//add pagination
|
||||
$per_page = $request->input('per_page', 10);
|
||||
$page = $request->input('page', 1);
|
||||
$paginator = new LengthAwarePaginator(
|
||||
$flightCollection->forPage($page, $per_page),
|
||||
$flightCollection->count(),
|
||||
$per_page,
|
||||
$page
|
||||
);
|
||||
|
||||
$result = (new Collection($paginator, new TripTransformer(), 'trips'))
|
||||
->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
$result = new Collection($flightCollection, new FlightTransform(), 'flights');
|
||||
|
||||
return $this->JsonApiResponse($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} /flights/:id get flight
|
||||
* @apiName Get Flight
|
||||
* @apiGroup Flights
|
||||
* @apiDescription get details of a specific flight
|
||||
*
|
||||
* @apiParam (url) {number} id the id of the flight to fetch
|
||||
*
|
||||
* @apiExample {curl} example
|
||||
* curl -i http://localhost:8080/flights/1
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getFlight(Request $request, $id)
|
||||
{
|
||||
$flight = Flights::find($id);
|
||||
|
||||
$result = new Item($flight, new FlightTransform(), 'flights');
|
||||
if (! $flight) {
|
||||
return $this->returnErrorMessage("flight id $id not found", 400);
|
||||
}
|
||||
|
||||
return $this->JsonApiResponse($result, 200);
|
||||
}
|
||||
|
||||
public function removeFlight(Request $request, $id)
|
||||
{
|
||||
/** @var \App\Libraries\Trips\Models\Flights $flight */
|
||||
$flight = Flights::find($id);
|
||||
$deleted = $flight->delete();
|
||||
|
||||
// $result = new Item($flight, [
|
||||
// 'id' => $id,
|
||||
// 'message' => 'flight removed'
|
||||
// ], 'message');
|
||||
$result = new Item($flight, new FlightTransform(), 'flights');
|
||||
|
||||
return $this->JsonApiResponse($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the response to Json
|
||||
* @api {delete} /flights/:id delete a flight
|
||||
* @apiName Delete a Flight
|
||||
* @apiGroup Flights
|
||||
* @apiDescription delete a flight and remove it from any trips
|
||||
*
|
||||
* @param \League\Fractal\Resource\Item $resource
|
||||
* @param $statusCode
|
||||
* @apiParam (url) {number} id the id of the flight to fetch
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function JsonApiResponse(ResourceInterface $resource, $statusCode)
|
||||
public function removeFlight(Request $request, $id)
|
||||
{
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new JsonApiSerializer('http://docker.dev:8080'));
|
||||
$manager->parseIncludes('flights');
|
||||
/** @var \App\Libraries\Trips\Models\Flights $flight */
|
||||
$flight = Flights::find($id);
|
||||
$deleted = $flight->delete();
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray(), $statusCode);
|
||||
$result = new Item($flight, new FlightTransform(), 'flights');
|
||||
|
||||
return $this->JsonApiResponse($result, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Libraries\IotaCodes\Client as IotaClient;
|
||||
use App\Libraries\Trips\Models\Flights;
|
||||
use App\Libraries\Trips\Models\Trips;
|
||||
use App\Libraries\Trips\TripTransformer;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\ResourceInterface;
|
||||
@@ -25,6 +27,21 @@ class TripController extends Controller
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} /trips list trips
|
||||
* @apiName list trips
|
||||
* @apiGroup Trips
|
||||
* @apiDescription This api returns a paginated list of trips found
|
||||
*
|
||||
* @apiParam (query params) {number} [page=1] page to fetch
|
||||
* @apiParam (query param) {number} [per_page=10] number of results to fetch per page
|
||||
*
|
||||
* @apiExample {curl} example
|
||||
* curl -i http://localhost:8080/trips?page=1&per_page=10
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function listTrips(Request $request)
|
||||
{
|
||||
$tripsCollection = Trips::all();
|
||||
@@ -45,6 +62,21 @@ class TripController extends Controller
|
||||
return $this->JsonApiResponse($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} /trips/:id get trip
|
||||
* @apiName get trip
|
||||
* @apiGroup Trips
|
||||
* @apiDescription Fetch details of a specific trip
|
||||
*
|
||||
* @apiParam (url) {number} id the id of the trip to fetch
|
||||
*
|
||||
* @apiExample {curl} example
|
||||
* curl -i http://localhost:8080/trips/1
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getTrip(Request $request, $id)
|
||||
{
|
||||
$trip = Trips::find($id);
|
||||
@@ -58,6 +90,22 @@ class TripController extends Controller
|
||||
return $this->JsonApiResponse($result, 200, 'flights');
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /trips/:id/flights add flight
|
||||
* @apiName add flight
|
||||
* @apiGroup Trips
|
||||
* @apiDescription send a destination to this endpoint to add a flight to the trip
|
||||
*
|
||||
* @apiParam (form data) {string} destination the destination of the new flight
|
||||
* @apiParam (url) {number} id the id of the trip to fetch
|
||||
*
|
||||
* @apiExample {curl} example
|
||||
* curl -i http://localhost:8080/trips/1/flights
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function addFlight(Request $request, $id)
|
||||
{
|
||||
$trip = Trips::find($id);
|
||||
@@ -67,6 +115,12 @@ class TripController extends Controller
|
||||
return $this->returnErrorMessage('destination not set', 400);
|
||||
}
|
||||
|
||||
$client = IotaClient::create();
|
||||
$airport = $client->getAirport($destination);
|
||||
if (is_null($airport)) {
|
||||
return $this->returnErrorMessage('destination not a valid airport code', 400);
|
||||
}
|
||||
|
||||
$flight = new Flights(['destination' => $destination]);
|
||||
$flight->save();
|
||||
$trip->flights()->attach($flight->id);
|
||||
@@ -74,27 +128,4 @@ class TripController extends Controller
|
||||
$result = new Item($trip, new TripTransformer(), 'trips');
|
||||
return $this->JsonApiResponse($result, 201, 'flights');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the response to Json
|
||||
*
|
||||
* @param \League\Fractal\Resource\Item $resource
|
||||
* @param $statusCode
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function JsonApiResponse(ResourceInterface $resource, $statusCode, $includes = '')
|
||||
{
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new JsonApiSerializer('http://docker.dev:8080'));
|
||||
$manager->parseIncludes($includes);
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray(), $statusCode);
|
||||
}
|
||||
|
||||
protected function returnErrorMessage($message, $statusCode = 400)
|
||||
{
|
||||
return response()->json([
|
||||
'error_message' => $message
|
||||
], $statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +63,15 @@ class Client
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $code
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAirport($code)
|
||||
{
|
||||
$uri = '/api/v6/airports';
|
||||
$cacheKey = 'airport.'.$code;
|
||||
$cacheMinutes = 60;
|
||||
$cacheMinutes = 1;
|
||||
|
||||
$response = app('cache')->get($cacheKey, function () use ($cacheKey, $cacheMinutes, $uri, $code) {
|
||||
try {
|
||||
@@ -81,7 +85,7 @@ class Client
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
//todo handle error
|
||||
return new Collection();
|
||||
}
|
||||
|
||||
$result = $response->getBody()->getContents();
|
||||
|
||||
@@ -7,6 +7,15 @@ use League\Fractal\TransformerAbstract;
|
||||
|
||||
class FlightTransform extends TransformerAbstract
|
||||
{
|
||||
/**
|
||||
* List of resources possible to include
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'trips'
|
||||
];
|
||||
|
||||
/**
|
||||
* Turn this item object into a generic array
|
||||
*
|
||||
@@ -17,10 +26,23 @@ class FlightTransform extends TransformerAbstract
|
||||
return [
|
||||
'id' => $flight->id,
|
||||
'name' => $flight->destination,
|
||||
'trips' => $flight->trips()->get(),
|
||||
'links' => [
|
||||
'rel' => 'self',
|
||||
'uri' => '/flights/'.$flight->id,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Include Trips
|
||||
*
|
||||
* @return \League\Fractal\Resource\ResourceAbstract
|
||||
*/
|
||||
public function includeTrips(Flights $flight)
|
||||
{
|
||||
$flights = $flight->trips()->get();
|
||||
|
||||
return $this->collection($flights, new TripTransformer());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,15 @@ class Trips extends Model
|
||||
{
|
||||
return $this->belongsToMany(Flights::class, 'trip_flights');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class TripTransformer extends TransformerAbstract
|
||||
}
|
||||
|
||||
/**
|
||||
* Include Author
|
||||
* Include Flights
|
||||
*
|
||||
* @return \League\Fractal\Resource\ResourceAbstract
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,7 @@ services:
|
||||
- app
|
||||
links:
|
||||
- app
|
||||
- apidocs
|
||||
volumes:
|
||||
- ./docker/docker-vhost.conf:/etc/nginx/sites-enabled/vhost.conf
|
||||
|
||||
@@ -52,3 +53,17 @@ services:
|
||||
entrypoint:
|
||||
- composer
|
||||
- install
|
||||
|
||||
# generate api documentation, then exits
|
||||
apidocs:
|
||||
image: apidocs:latest
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/Dockerfile-apidocs
|
||||
volumes:
|
||||
- .:/src
|
||||
environment:
|
||||
- DOCS_DIR=public/docs
|
||||
- APP_DIR=./app
|
||||
- FILE_FILTER="[Http\/Controllers\/|routes\/].*php"
|
||||
|
||||
|
||||
21
docker/Dockerfile-apidocs
Normal file
21
docker/Dockerfile-apidocs
Normal file
@@ -0,0 +1,21 @@
|
||||
# Using alpine linux for small image
|
||||
# - http://gliderlabs.viewdocs.io/docker-alpine/
|
||||
FROM alpine:3.4
|
||||
MAINTAINER Richard Morgan <r_morgan@sympatico.ca>
|
||||
LABEL version=1.0 \
|
||||
"usage"="docker run --rm --name apidocker -v <source dir>:/src -it apidocker" \
|
||||
"env"="DOCS_DIR, APP_DIR, FILE_FILTER"
|
||||
|
||||
ENV DOCS_DIR="build/docs/" \
|
||||
APP_DIR="app/" \
|
||||
FILE_FILTER=".[php]$"
|
||||
|
||||
ADD ./docker/entrypoint-apidocs.sh /scripts/entrypoint.sh
|
||||
|
||||
# install system packages
|
||||
RUN apk --no-cache add \
|
||||
nodejs \
|
||||
&& npm install apidoc -g \
|
||||
&& chmod +x -R /scripts
|
||||
|
||||
ENTRYPOINT /scripts/entrypoint.sh
|
||||
@@ -1,11 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# start required services
|
||||
#service ssh start
|
||||
#service php5-fpm start
|
||||
|
||||
# keep the container running
|
||||
#tail -f /dev/null
|
||||
#tail -f /var/www/storage/logs/lumen.log
|
||||
/usr/sbin/php-fpm7.0 -F
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ server {
|
||||
try_files $uri /index.php?$args;
|
||||
}
|
||||
|
||||
location /docs {
|
||||
try_files $uri /docs/index.html;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass app:9000;
|
||||
|
||||
6
docker/entrypoint-apidocs.sh
Normal file
6
docker/entrypoint-apidocs.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
cd /src/
|
||||
echo ${APP_DIR} : ${DOCS_DIR} : ${FILE_FILTER}
|
||||
rm -rf ${DOCS_DIR} && mkdir -p ${DOCS_DIR}
|
||||
apidoc -i ${APP_DIR} -o ${DOCS_DIR} -f ${FILE_FILTER}
|
||||
1
docker/entrypoint-seeder.sh
Normal file
1
docker/entrypoint-seeder.sh
Normal file
@@ -0,0 +1 @@
|
||||
#!/usr/bin/env bash
|
||||
34
readme.md
34
readme.md
@@ -1,21 +1,29 @@
|
||||
# Lumen PHP Framework
|
||||
# Trip Builder
|
||||
- Richard Morgan <r_morgan@sympatico.ca>
|
||||
|
||||
[](https://travis-ci.org/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
Test application based on Laravel Lumen 5.4, running on docker containers.
|
||||
|
||||
Laravel Lumen is a stunningly fast PHP micro-framework for building web applications with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Lumen attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as routing, database abstraction, queueing, and caching.
|
||||
## Launch Environment
|
||||
The dev environment is docker based. To run the php app, nginx, postgres database, and redis cache containers, simply run docker-compose up
|
||||
|
||||
## Official Documentation
|
||||
|
||||
Documentation for the framework can be found on the [Lumen website](http://lumen.laravel.com/docs).
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
## Security Vulnerabilities
|
||||
This will download the required base images, then build the additional tools into new images, and then launch new containers.
|
||||
A container also runs briefly to generate the api docs.
|
||||
|
||||
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell at taylor@laravel.com. All security vulnerabilities will be promptly addressed.
|
||||
## Setup database
|
||||
Database migrations and seeds are provided for testing the app. These can be run in docker with the following command:
|
||||
|
||||
## License
|
||||
```bash
|
||||
docker-compose exec app php artisan migrate:refresh --seed
|
||||
```
|
||||
|
||||
The Lumen framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
||||
|
||||
## Api Documentation
|
||||
The docker containers expose the api documentation on [http://localhost:8080/docs/](http://localhost:8080/docs/)
|
||||
|
||||
|
||||
##
|
||||
|
||||
@@ -8,5 +8,9 @@ class_name: AcceptanceTester
|
||||
modules:
|
||||
enabled:
|
||||
- PhpBrowser:
|
||||
url: http://localhost/myapp
|
||||
url: http://localhost
|
||||
- REST:
|
||||
depends: PhpBrowser
|
||||
url: 'http://nginx'
|
||||
- Asserts
|
||||
- \Helper\Acceptance
|
||||
18
tests/acceptance/AirportsCest.php
Executable file
18
tests/acceptance/AirportsCest.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
|
||||
class AirportsCest
|
||||
{
|
||||
public function _before(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
|
||||
public function _after(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
|
||||
// tests
|
||||
public function tryToTest(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
}
|
||||
18
tests/acceptance/FlightsCest.php
Executable file
18
tests/acceptance/FlightsCest.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
|
||||
class FlightsCest
|
||||
{
|
||||
public function _before(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
|
||||
public function _after(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
|
||||
// tests
|
||||
public function tryToTest(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
}
|
||||
117
tests/acceptance/TripsCest.php
Executable file
117
tests/acceptance/TripsCest.php
Executable file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
|
||||
class TripsCest
|
||||
{
|
||||
protected $uri = '/trips';
|
||||
|
||||
public function _before(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
|
||||
public function _after(AcceptanceTester $I)
|
||||
{
|
||||
}
|
||||
|
||||
// tests
|
||||
public function listTripsReturnsJson(AcceptanceTester $I)
|
||||
{
|
||||
$params = [];
|
||||
|
||||
$I->sendGET($this->uri, $params);
|
||||
$r = $I->grabResponse();
|
||||
|
||||
$I->seeResponseCodeIs(200, $r);
|
||||
$I->seeResponseIsJson();
|
||||
}
|
||||
|
||||
public function listTripReturns1ItemWhenPerPageIs1(AcceptanceTester $I)
|
||||
{
|
||||
$params = [
|
||||
'page' => 1,
|
||||
'per_page' => 1
|
||||
];
|
||||
|
||||
$I->sendGET($this->uri, $params);
|
||||
$r = $I->grabResponse();
|
||||
|
||||
$I->seeResponseCodeIs(200, $r);
|
||||
$I->seeResponseIsJson();
|
||||
|
||||
$data = json_decode($r);
|
||||
$I->assertCount(1, $data->data, $data);
|
||||
}
|
||||
|
||||
public function listTripReturns2ItemWhenPerPageIs2(AcceptanceTester $I)
|
||||
{
|
||||
$params = [
|
||||
'page' => 1,
|
||||
'per_page' => 2
|
||||
];
|
||||
|
||||
$I->sendGET($this->uri, $params);
|
||||
$r = $I->grabResponse();
|
||||
|
||||
$I->seeResponseCodeIs(200, $r);
|
||||
$I->seeResponseIsJson();
|
||||
|
||||
$data = json_decode($r);
|
||||
$I->assertCount(2, $data->data, $data);
|
||||
}
|
||||
|
||||
public function getTripReturnsTripJson(AcceptanceTester $I)
|
||||
{
|
||||
$I->sendGET($this->uri, []);
|
||||
$r = $I->grabResponse();
|
||||
$data = json_decode($r, true);
|
||||
$tripId = $data['data'][0]['id'];
|
||||
|
||||
$params = [];
|
||||
$uri = $this->uri . '/' . $tripId;
|
||||
|
||||
$I->sendGET($uri, $params);
|
||||
$r = $I->grabResponse();
|
||||
|
||||
$I->seeResponseCodeIs(200, $r);
|
||||
$I->seeResponseIsJson();
|
||||
|
||||
$data = json_decode($r, true);
|
||||
$I->assertEquals('trips', $data['data']['type']);
|
||||
$I->assertEquals($tripId, $data['data']['id']);
|
||||
}
|
||||
|
||||
public function getTripReturns400IfTripIdNotFound(AcceptanceTester $I)
|
||||
{
|
||||
$params = [];
|
||||
$uri = $this->uri . '/999999';
|
||||
|
||||
$I->sendGET($uri, $params);
|
||||
$r = $I->grabResponse();
|
||||
|
||||
$I->seeResponseCodeIs(400, $r);
|
||||
$I->seeResponseIsJson();
|
||||
}
|
||||
|
||||
public function addFlightAttachesNewFlightOnTrip(AcceptanceTester $I)
|
||||
{
|
||||
$I->sendGET($this->uri, []);
|
||||
$r = $I->grabResponse();
|
||||
$data = json_decode($r, true);
|
||||
$tripId = $data['data'][0]['id'];
|
||||
$nbFlights = count($data['data'][0]['attributes']['flights']);
|
||||
|
||||
$params = [
|
||||
'destination' => 'YUL'
|
||||
];
|
||||
$uri = $this->uri . '/' . $tripId .'/flights';
|
||||
|
||||
$I->sendPost($uri, $params);
|
||||
$r = $I->grabResponse();
|
||||
|
||||
$I->seeResponseCodeIs(201, $r);
|
||||
$I->seeResponseIsJson();
|
||||
|
||||
$data = json_decode($r, true);
|
||||
$I->assertCount($nbFlights+1, $data['data']['attributes']['flights']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user