Some Error handling and acceptance tests

This commit is contained in:
Richard Morgan
2017-05-15 08:56:10 -04:00
parent 42dc785735
commit 2c8c692890
21 changed files with 457 additions and 126 deletions

4
.gitignore vendored
View File

@@ -4,4 +4,6 @@ Homestead.json
Homestead.yaml Homestead.yaml
.env .env
tests/_output/* tests/_output/*
/public/docs/
/build/

8
apidoc.json Executable file
View 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"
}

View File

@@ -4,7 +4,7 @@ namespace App\Http\Controllers;
use App\Libraries\IotaCodes\Airport; use App\Libraries\IotaCodes\Airport;
use App\Libraries\IotaCodes\AirportTransformer; use App\Libraries\IotaCodes\AirportTransformer;
use App\Libraries\IotaCodes\Client; use App\Libraries\IotaCodes\Client as IotaClient;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Manager; use League\Fractal\Manager;
@@ -18,33 +18,27 @@ use League\Fractal\Serializer\JsonApiSerializer;
class AirportController extends Controller class AirportController extends Controller
{ {
/** /**
* Create a new controller instance. * @api {get} /airports list airports
*
* @return void
*/
public function __construct()
{
//
}
/**
* Fetch list of airports
*
* @api {get} /airports
* @apiName List Airports * @apiName List Airports
* @apiGroup Airports
* @apiDescription Fetch list of airports
* *
* @apiParam (pagination) {number} [page] page number to display * @apiParam (query param) {number} [page=1] page number to display
* @apiParam (pagination) {number} [per_page] number of items to display on the page * @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 * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function resourceList(Request $request) public function resourceList(Request $request)
{ {
$client = Client::create(); $client = IotaClient::create();
$collection = $client->listAirports($request->input('autocomplete')); $collection = $client->listAirports($request->input('autocomplete'));
//add pagination //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 * @apiParam (query param) {string} code 3 letter airport code
* @apiName Get Airport from code
* *
* @apiParam {string} code 3 letter airport code * @apiExample {curl} example
* curl -i http://localhost:8080/airports/YUL
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param $code * @param $code
@@ -77,27 +74,15 @@ class AirportController extends Controller
*/ */
public function getAirport(Request $request, $code) public function getAirport(Request $request, $code)
{ {
$client = Client::create(); $client = IotaClient::create();
$airport = $client->getAirport($code);
if (is_null($airport)) {
return $this->returnErrorMessage('not a valid airport code', 400);
}
$result = $client->getAirport($code); $result = new Item($airport, new AirportTransformer(), 'airports');
$result = new Item($result, new AirportTransformer(), 'airports');
return $this->JsonApiResponse($result, 200); 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);
}
} }

View File

@@ -3,8 +3,40 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Laravel\Lumen\Routing\Controller as BaseController; 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 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);
}
} }

View File

@@ -7,7 +7,9 @@ use App\Libraries\Trips\Models\Flights;
use App\Libraries\Trips\Models\Trips; use App\Libraries\Trips\Models\Trips;
use App\Libraries\Trips\TripTransformer; use App\Libraries\Trips\TripTransformer;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Manager; use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection; use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
use League\Fractal\Resource\ResourceInterface; use League\Fractal\Resource\ResourceInterface;
@@ -16,62 +18,90 @@ use League\Fractal\Serializer\JsonApiSerializer;
class FlightController extends Controller 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) public function listFlights(Request $request)
{ {
$flightCollection = Flights::all(); $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'); $result = new Collection($flightCollection, new FlightTransform(), 'flights');
return $this->JsonApiResponse($result, 200); 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) public function getFlight(Request $request, $id)
{ {
$flight = Flights::find($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'); $result = new Item($flight, new FlightTransform(), 'flights');
return $this->JsonApiResponse($result, 200); 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 * @apiParam (url) {number} id the id of the flight to fetch
* @param $statusCode *
* @param \Illuminate\Http\Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
protected function JsonApiResponse(ResourceInterface $resource, $statusCode) public function removeFlight(Request $request, $id)
{ {
$manager = new Manager(); /** @var \App\Libraries\Trips\Models\Flights $flight */
$manager->setSerializer(new JsonApiSerializer('http://docker.dev:8080')); $flight = Flights::find($id);
$manager->parseIncludes('flights'); $deleted = $flight->delete();
$result = new Item($flight, new FlightTransform(), 'flights');
return response()->json($manager->createData($resource)->toArray(), $statusCode); return $this->JsonApiResponse($result, 200);
} }
} }

View File

@@ -2,12 +2,14 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Libraries\IotaCodes\Client as IotaClient;
use App\Libraries\Trips\Models\Flights; use App\Libraries\Trips\Models\Flights;
use App\Libraries\Trips\Models\Trips; use App\Libraries\Trips\Models\Trips;
use App\Libraries\Trips\TripTransformer; use App\Libraries\Trips\TripTransformer;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Manager; use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection; use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
use League\Fractal\Resource\ResourceInterface; use League\Fractal\Resource\ResourceInterface;
@@ -24,7 +26,22 @@ 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) public function listTrips(Request $request)
{ {
$tripsCollection = Trips::all(); $tripsCollection = Trips::all();
@@ -41,10 +58,25 @@ class TripController extends Controller
$result = (new Collection($paginator, new TripTransformer(), 'trips')) $result = (new Collection($paginator, new TripTransformer(), 'trips'))
->setPaginator(new IlluminatePaginatorAdapter($paginator)); ->setPaginator(new IlluminatePaginatorAdapter($paginator));
return $this->JsonApiResponse($result, 200); 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) public function getTrip(Request $request, $id)
{ {
$trip = Trips::find($id); $trip = Trips::find($id);
@@ -58,14 +90,36 @@ class TripController extends Controller
return $this->JsonApiResponse($result, 200, 'flights'); 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) public function addFlight(Request $request, $id)
{ {
$trip = Trips::find($id); $trip = Trips::find($id);
$destination = $request->input('destination'); $destination = $request->input('destination');
if (! $destination) { if (! $destination) {
return $this->returnErrorMessage('destination not set', 400); 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 = new Flights(['destination' => $destination]);
$flight->save(); $flight->save();
@@ -74,27 +128,4 @@ class TripController extends Controller
$result = new Item($trip, new TripTransformer(), 'trips'); $result = new Item($trip, new TripTransformer(), 'trips');
return $this->JsonApiResponse($result, 201, 'flights'); 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);
}
} }

View File

@@ -63,11 +63,15 @@ class Client
return $result; return $result;
} }
/**
* @param $code
* @return Collection
*/
public function getAirport($code) public function getAirport($code)
{ {
$uri = '/api/v6/airports'; $uri = '/api/v6/airports';
$cacheKey = 'airport.'.$code; $cacheKey = 'airport.'.$code;
$cacheMinutes = 60; $cacheMinutes = 1;
$response = app('cache')->get($cacheKey, function () use ($cacheKey, $cacheMinutes, $uri, $code) { $response = app('cache')->get($cacheKey, function () use ($cacheKey, $cacheMinutes, $uri, $code) {
try { try {
@@ -81,7 +85,7 @@ class Client
]); ]);
} catch (\Exception $e) { } catch (\Exception $e) {
//todo handle error return new Collection();
} }
$result = $response->getBody()->getContents(); $result = $response->getBody()->getContents();

View File

@@ -7,6 +7,15 @@ use League\Fractal\TransformerAbstract;
class FlightTransform extends TransformerAbstract class FlightTransform extends TransformerAbstract
{ {
/**
* List of resources possible to include
*
* @var array
*/
protected $availableIncludes = [
'trips'
];
/** /**
* Turn this item object into a generic array * Turn this item object into a generic array
* *
@@ -17,10 +26,23 @@ class FlightTransform extends TransformerAbstract
return [ return [
'id' => $flight->id, 'id' => $flight->id,
'name' => $flight->destination, 'name' => $flight->destination,
'trips' => $flight->trips()->get(),
'links' => [ 'links' => [
'rel' => 'self', 'rel' => 'self',
'uri' => '/flights/'.$flight->id, '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());
}
} }

View File

@@ -16,4 +16,15 @@ class Trips extends Model
{ {
return $this->belongsToMany(Flights::class, 'trip_flights'); return $this->belongsToMany(Flights::class, 'trip_flights');
} }
/**
* @return array
*/
public function toArray()
{
return [
'id' => $this->id,
'name' => $this->name,
];
}
} }

View File

@@ -36,7 +36,7 @@ class TripTransformer extends TransformerAbstract
} }
/** /**
* Include Author * Include Flights
* *
* @return \League\Fractal\Resource\ResourceAbstract * @return \League\Fractal\Resource\ResourceAbstract
*/ */

View File

@@ -27,6 +27,7 @@ services:
- app - app
links: links:
- app - app
- apidocs
volumes: volumes:
- ./docker/docker-vhost.conf:/etc/nginx/sites-enabled/vhost.conf - ./docker/docker-vhost.conf:/etc/nginx/sites-enabled/vhost.conf
@@ -52,3 +53,17 @@ services:
entrypoint: entrypoint:
- composer - composer
- install - 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
View 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

View File

@@ -1,11 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# start required services
#service ssh start
#service php5-fpm start
# keep the container running # keep the container running
#tail -f /dev/null
#tail -f /var/www/storage/logs/lumen.log
/usr/sbin/php-fpm7.0 -F /usr/sbin/php-fpm7.0 -F

View File

@@ -9,6 +9,10 @@ server {
try_files $uri /index.php?$args; try_files $uri /index.php?$args;
} }
location /docs {
try_files $uri /docs/index.html;
}
location ~ \.php$ { location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000; fastcgi_pass app:9000;

View 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}

View File

@@ -0,0 +1 @@
#!/usr/bin/env bash

View File

@@ -1,21 +1,29 @@
# Lumen PHP Framework # Trip Builder
- Richard Morgan <r_morgan@sympatico.ca>
[![Build Status](https://travis-ci.org/laravel/lumen-framework.svg)](https://travis-ci.org/laravel/lumen-framework) Test application based on Laravel Lumen 5.4, running on docker containers.
[![Total Downloads](https://poser.pugx.org/laravel/lumen-framework/d/total.svg)](https://packagist.org/packages/laravel/lumen-framework)
[![Latest Stable Version](https://poser.pugx.org/laravel/lumen-framework/v/stable.svg)](https://packagist.org/packages/laravel/lumen-framework)
[![Latest Unstable Version](https://poser.pugx.org/laravel/lumen-framework/v/unstable.svg)](https://packagist.org/packages/laravel/lumen-framework)
[![License](https://poser.pugx.org/laravel/lumen-framework/license.svg)](https://packagist.org/packages/laravel/lumen-framework)
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/)
##

View File

@@ -8,5 +8,9 @@ class_name: AcceptanceTester
modules: modules:
enabled: enabled:
- PhpBrowser: - PhpBrowser:
url: http://localhost/myapp url: http://localhost
- \Helper\Acceptance - REST:
depends: PhpBrowser
url: 'http://nginx'
- Asserts
- \Helper\Acceptance

View File

@@ -0,0 +1,18 @@
<?php
class AirportsCest
{
public function _before(AcceptanceTester $I)
{
}
public function _after(AcceptanceTester $I)
{
}
// tests
public function tryToTest(AcceptanceTester $I)
{
}
}

View 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
View 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']);
}
}