Skip to content

Commit 4dfe1f2

Browse files
committed
Initial commit
0 parents  commit 4dfe1f2

File tree

13 files changed

+460
-0
lines changed

13 files changed

+460
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
composer.phar
2+
composer.lock
3+
/vendor/

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6+
7+
## [Unreleased]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Netsells
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Laravel Hooks for Dredd API Testing Framework
2+
This package contains a PHP Dredd hook handler which provides a bridge between the [Dredd API Testing Framework](http://dredd.readthedocs.org/en/latest/)
3+
and PHP environment to ease implementation of testing hooks provided by [Dredd](http://dredd.readthedocs.org/en/latest/). Most of the heavy loading is provided by the [ddelnano/dredd-hooks-php](https://github.com/ddelnano/dredd-hooks-php) package.

bin/dredd-hooks-laravel

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
/*
5+
* This is mostly taken from ddelnano/dredd-hooks-php
6+
*/
7+
8+
use Dredd\Server;
9+
use Dredd\Hooks;
10+
11+
ini_set('implicit_flush', 'on');
12+
ini_set('output_buffering', 'off');
13+
14+
15+
$loaded = false;
16+
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
17+
if (file_exists($file)) {
18+
require $file;
19+
$loaded = true;
20+
break;
21+
}
22+
}
23+
if (!$loaded) {
24+
die(
25+
'You need to set up the project dependencies using the following commands:' . PHP_EOL .
26+
'wget http://getcomposer.org/composer.phar' . PHP_EOL .
27+
'php composer.phar install' . PHP_EOL
28+
);
29+
}
30+
31+
// Load Laravel
32+
$app = require $devPath . '/bootstrap/app.php';
33+
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
34+
35+
// Get options from the command line
36+
$options = getopt('', [
37+
'host:',
38+
'port:',
39+
'force',
40+
]);
41+
42+
// Second argument is the single kernel file
43+
$dreddKernel = $argv[1];
44+
$dreddKernelFile = file_get_contents($dreddKernel);
45+
46+
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7);
47+
48+
try {
49+
$stmts = $parser->parse($dreddKernelFile);
50+
// $stmts is an array of statement nodes
51+
} catch (PhpParser\Error $e) {
52+
echo 'Parse Error: ', $e->getMessage();
53+
}
54+
55+
$namespace = '';
56+
$class = '';
57+
58+
if ($stmts[0] instanceof PhpParser\Node\Stmt\Namespace_) {
59+
$namespace = implode('\\', $stmts[0]->name->parts);
60+
foreach ($stmts[0]->stmts as $statement) {
61+
if ($statement instanceof PhpParser\Node\Stmt\Class_) {
62+
$class = $statement->name;
63+
}
64+
}
65+
}
66+
67+
$kernelClass = $namespace . '\\' . $class;
68+
$kernel = new $kernelClass;
69+
70+
$kernel->handle(new \Netsells\Dredd\Hook());
71+
72+
$host = array_key_exists('host', $options)
73+
? $options['host']
74+
: '127.0.0.1';
75+
$port = array_key_exists('port', $options)
76+
? $options['port']
77+
: 61321;
78+
79+
$server = new Server($host, $port);
80+
81+
fprintf(STDOUT, "Starting server\n");
82+
flush();
83+
84+
$server->run(array_key_exists('force', $options));

composer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "netsells/dredd-hooks-laravel",
3+
"description": "Laravel hooks for the Dredd testing tool",
4+
"type": "package",
5+
"require": {
6+
"php": ">=7.1",
7+
"nikic/php-parser": "^3.1",
8+
"ddelnano/dredd-hooks-php": "^1.1"
9+
},
10+
"license": "MIT",
11+
"authors": [
12+
{
13+
"name": "Sam Jordan",
14+
"email": "sam@netsells.co.uk"
15+
}
16+
],
17+
"bin": ["bin/dredd-hooks-laravel"],
18+
"autoload": {
19+
"psr-4": {
20+
"Netsells\\Dredd\\": "src/"
21+
}
22+
},
23+
"extra": {
24+
"laravel": {
25+
"providers": [
26+
"Netsells\\Dredd\\DreddServiceProvider"
27+
]
28+
}
29+
},
30+
"minimum-stability": "stable"
31+
}

server.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
$basePath = __DIR__ . '/../../..';
4+
5+
// Composer won't autoload twice so this should have no performance hit
6+
require $basePath . '/vendor/autoload.php';
7+
8+
// Laravel will not overwrite existing environment variables, so we'll pull in custom ones here
9+
$dotenv = new Dotenv\Dotenv($basePath, '.env.dredd');
10+
$dotenv->load();
11+
12+
require_once $basePath . '/server.php';

src/Console/Serve.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace Netsells\Dredd\Console;
4+
5+
use Illuminate\Console\Command;
6+
use Symfony\Component\Process\ProcessUtils;
7+
use Symfony\Component\Console\Input\InputOption;
8+
use Symfony\Component\Process\PhpExecutableFinder;
9+
10+
class Serve extends Command
11+
{
12+
/**
13+
* The console command name.
14+
*
15+
* @var string
16+
*/
17+
protected $name = 'dredd:serve';
18+
19+
/**
20+
* The console command description.
21+
*
22+
* @var string
23+
*/
24+
protected $description = 'Serve the application for dredd testing';
25+
26+
/**
27+
* Execute the console command.
28+
*
29+
* @return void
30+
*
31+
* @throws \Exception
32+
*/
33+
public function fire()
34+
{
35+
chdir($this->laravel->publicPath());
36+
37+
$this->line("<info>Laravel development server started:</info> <http://{$this->host()}:{$this->port()}>");
38+
39+
passthru($this->serverCommand());
40+
}
41+
42+
/**
43+
* Get the full server command.
44+
*
45+
* @return string
46+
*/
47+
protected function serverCommand()
48+
{
49+
return sprintf('%s -S %s:%s %s/server.php',
50+
ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false)),
51+
$this->host(),
52+
$this->port(),
53+
ProcessUtils::escapeArgument(__DIR__ . '/../..')
54+
);
55+
}
56+
57+
/**
58+
* Get the host for the command.
59+
*
60+
* @return string
61+
*/
62+
protected function host()
63+
{
64+
return $this->input->getOption('host');
65+
}
66+
67+
/**
68+
* Get the port for the command.
69+
*
70+
* @return string
71+
*/
72+
protected function port()
73+
{
74+
return $this->input->getOption('port');
75+
}
76+
77+
/**
78+
* Get the console command options.
79+
*
80+
* @return array
81+
*/
82+
protected function getOptions()
83+
{
84+
return [
85+
['host', null, InputOption::VALUE_OPTIONAL, 'The host address to serve the application on.', '127.0.0.1'],
86+
87+
['port', null, InputOption::VALUE_OPTIONAL, 'The port to serve the application on.', 8000],
88+
];
89+
}
90+
}

src/DreddServiceProvider.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Netsells\Dredd;
4+
5+
use Illuminate\Support\ServiceProvider;
6+
7+
class DreddServiceProvider extends ServiceProvider
8+
{
9+
/**
10+
* Bootstrap the application services.
11+
*
12+
* @return void
13+
*/
14+
public function boot()
15+
{
16+
if ($this->app->runningInConsole()) {
17+
$this->commands([
18+
Console\Serve::class,
19+
]);
20+
}
21+
}
22+
23+
/**
24+
* Register bindings in the container.
25+
*
26+
* @return void
27+
*/
28+
public function register()
29+
{
30+
//
31+
}
32+
}

src/Hook.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Netsells\Dredd;
4+
5+
use Dredd\Hooks;
6+
7+
class Hook
8+
{
9+
use ResolvesArgumentTrait;
10+
11+
protected $group;
12+
protected $operation;
13+
protected $path;
14+
protected $status = 200;
15+
protected $response = 'application/json';
16+
17+
public function __call($method, $args)
18+
{
19+
if (in_array($method, ['group', 'path', 'operation', 'status', 'response'])) {
20+
$this->{$method} = $args[0];
21+
22+
if (isset($args[1])) {
23+
if ($callable = $this->resolveArgument($args[1])) {
24+
return $callable($this);
25+
}
26+
}
27+
28+
return $this;
29+
}
30+
31+
if (in_array($method, ['before'])) {
32+
$callable = $this->resolveArgument($args[0]);
33+
34+
Hooks::$method($this->buildTransactionName(), function (&$transaction) use ($callable) {
35+
$transactionObject = new Transaction($transaction);
36+
$callable($transactionObject);
37+
$transaction = $transactionObject->getTransaction();
38+
});
39+
}
40+
}
41+
42+
private function buildTransactionName()
43+
{
44+
return implode(' > ', [
45+
$this->group,
46+
$this->path,
47+
$this->operation,
48+
$this->status,
49+
$this->response,
50+
]);
51+
}
52+
}

0 commit comments

Comments
 (0)