From 6c173cdc89b34dbde68ee6200826ff781c30a758 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Sun, 28 Sep 2014 09:47:54 -0400 Subject: [PATCH] Working on tests for the Resource class. Got a bunch more validation rules to port over. --- src/Resource.php | 61 +++++++------- tests/ResourceTest.php | 185 ++++++++++++++++++++++++++++------------- tests/RouterTest.php | 35 ++++++-- tests/ValidateTest.php | 78 ----------------- 4 files changed, 188 insertions(+), 171 deletions(-) diff --git a/src/Resource.php b/src/Resource.php index fde36ff..b2c2e64 100644 --- a/src/Resource.php +++ b/src/Resource.php @@ -87,13 +87,11 @@ class Resource extends Object try { // Determines if we need to serve over HTTP or HTTPS - if ($this->https === true + if (($this->https === true || (isset($this->https[$method]) && $this->https[$method])) + && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == false)) { - if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == false) - { - throw new \Exception('SSL is required.', 400); - } + throw new \Exception('HTTPS is required.', 400); } // Check auth if flag is explicitly true or is true for the method @@ -201,37 +199,35 @@ class Resource extends Object { $rule = explode(':', $rule); - switch (strtolower($rule[0])) + switch ($rule[0]) { // {{{ Checks using filter_var() case 'filter': - if (count($rule) < 2) + if (!isset($rule[1])) { - throw new \Exception('Invalid validation rule, expected: "validate:boolean|email|float|int|ip|url".'); + $rule[1] = false; } - else + + switch ($rule[1]) { - switch (strtolower($rule[1])) - { - case 'boolean': - case 'email': - case 'float': - case 'int': - case 'ip': - case 'url': - $filter = constant('FILTER_VALIDATE_' . strtoupper($rule[1])); - break; + case 'boolean': + case 'email': + case 'float': + case 'int': + case 'ip': + case 'url': + $filter = constant('FILTER_VALIDATE_' . strtoupper($rule[1])); + break; - default: - throw new \Exception('Invalid filter, expecting boolean, email, float, int, ip or url.'); - break; - } + default: + throw new \Exception('Invalid filter, expecting boolean, email, float, int, ip or url.'); + break; + } - if (!filter_var($value, $filter)) - { - $this->errors[$variable][] = $message; - } + if (!filter_var($value, $filter)) + { + $this->errors[$variable][] = $message; } break; @@ -374,7 +370,16 @@ class Resource extends Object } catch (\Exception $e) { - throw $e; + $code = $e->getCode(); + + // Anything below 200 is probably a PHP error + if ($code < 200) + { + $code = 500; + } + + $this->status = $code; + $this->message = $e->getMessage(); } } diff --git a/tests/ResourceTest.php b/tests/ResourceTest.php index 6fa429e..6131d82 100644 --- a/tests/ResourceTest.php +++ b/tests/ResourceTest.php @@ -1,69 +1,138 @@ [ - 'length:<:10' => 'Too short', - 'length:>:50' => 'Too long', - ], - ]; -} - -class MockChildResource extends MockParentResource -{ - public $method = ['POST', 'GET']; -} - -class ResourceTest extends PHPUnit_Framework_TestCase -{ - public function testAutoRun() + class resource extends \Pickles\Resource { - $this->assertInstanceOf('Pickles\\Resource', new Pickles\Resource(true)); - } + public $https = [ + 'POST' => true, + ]; - public function testAutoRunParentError() - { - $this->expectOutputString(''); - $model = new MockChildResource(true); - } + public $auth = [ + 'DELETE' => true, + ]; - public function testSetGetReturn() - { - $module = new Pickles\Resource(); - $module->foo = 'bar'; - $this->assertEquals('bar', $module->foo); - } + public $filter = [ + 'GET' => [ + 'foo' => 'trim', + 'bar' => 'password_hash', + ], + ]; - public function testGetMissing() - { - $module = new Pickles\Resource(); - $this->assertFalse($module->missing); - } + public $validate = [ + 'GET' => [ + 'missing', + 'isBoolean' => ['filter:boolean' => 'Error'], + 'isNotBoolean' => ['filter:boolean' => 'Error'], + 'isEmail' => ['filter:email' => 'Error'], + 'isNotEmail' => ['filter:email' => 'Error'], + 'isFloat' => ['filter:float' => 'Error'], + 'isNotFloat' => ['filter:float' => 'Error'], + 'isInt' => ['filter:int' => 'Error'], + 'isNotInt' => ['filter:int' => 'Error'], + 'isIP' => ['filter:ip' => 'Error'], + 'isNotIP' => ['filter:ip' => 'Error'], + 'isURL' => ['filter:url' => 'Error'], + 'isNotURL' => ['filter:url' => 'Error'], + 'invalidRule' => ['filter' => 'Error'], + ], + ]; - public function testValidateGet() - { - $module = new MockParentResource(); - $module->method = 'GET'; - $this->assertEquals(['The field1 field is required.', 'Too long'], $module->__validate()); - } - - public function testValidatePost() - { - $module = new MockParentResource(); - $this->assertEquals(['The field1 field is required.', 'Too long'], $module->__validate()); - } - - public function testValidateRequest() - { - $module = new MockParentResource(); - $module->method = null; - $this->assertEquals(['The field1 field is required.', 'Too long'], $module->__validate()); + public function GET() + { + return ['foo' => 'bar']; + } + } +} + +namespace +{ + class ResourceTest extends PHPUnit_Framework_TestCase + { + public function testFilterAndValidate() + { + $response = json_encode([ + 'meta' => [ + 'status' => 500, + 'message' => 'Invalid filter, expecting boolean, email, float, int, ip or url.', + 'errors' => [ + 'missing' => ['The missing parameter is required.'], + 'isNotBoolean' => ['Error'], + 'isNotEmail' => ['Error'], + 'isNotFloat' => ['Error'], + 'isNotInt' => ['Error'], + 'isNotIP' => ['Error'], + 'isNotURL' => ['Error'], + ], + ], + ]); + + $this->expectOutputString($response); + + $_SERVER['REQUEST_METHOD'] = 'GET'; + $_REQUEST['request'] = 'v1/resource/1'; + $_GET = [ + 'foo' => ' bar ', + 'bar' => 'unencrypted', + 'isBoolean' => true, + 'isNotBoolean' => 'invalid', + 'isEmail' => 'foo@bar.com', + 'isNotEmail' => 'nope', + 'isFloat' => 1.234567890, + 'isNotFloat' => 'five', + 'isInt' => 22381, + 'isNotInt' => 'pretzel', + 'isIP' => '127.0.0.1', + 'isNotIP' => 'home', + 'isURL' => 'http://joshtronic.com', + 'isNotURL' => 'doubleUdoubleUdoubleUdot', + 'invalidRule' => 'invalid', + ]; + + new Pickles\Router(); + + $this->assertEquals('bar', $_GET['foo']); + $this->assertFalse('unencrypted' == $_GET['bar']); + } + + public function testHTTPS() + { + $response = json_encode([ + 'meta' => [ + 'status' => 400, + 'message' => 'HTTPS is required.', + ], + ]); + + $this->expectOutputString($response); + + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_REQUEST['request'] = 'v1/resource/1'; + + new Pickles\Router(); + } + + public function testAuthMisconfigured() + { + $response = json_encode([ + 'meta' => [ + 'status' => 401, + 'message' => 'Authentication is not configured properly.', + ], + ]); + + $this->expectOutputString($response); + + $_SERVER['REQUEST_METHOD'] = 'DELETE'; + $_REQUEST['request'] = 'v1/resource/1'; + + new Pickles\Router(); + } + + public function testValidation() + { + + } } } diff --git a/tests/RouterTest.php b/tests/RouterTest.php index e4c7902..46346f2 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -2,7 +2,7 @@ namespace Resources\v1 { - class resource extends \Pickles\Resource + class router extends \Pickles\Resource { } @@ -14,7 +14,14 @@ namespace { public function testServerError() { - $this->expectOutputRegex('/{"status":500,"message":"Undefined index: request"}/'); + $response = json_encode([ + 'meta' => [ + 'status' => 500, + 'message' => 'Undefined index: request', + ], + ]); + + $this->expectOutputString($response); $_SERVER['REQUEST_METHOD'] = 'GET'; @@ -23,22 +30,36 @@ namespace public function testNotFound() { - $this->expectOutputRegex('/{"status":404,"message":"Not Found."}/'); + $response = json_encode([ + 'meta' => [ + 'status' => 404, + 'message' => 'Not Found.', + ], + ]); + + $this->expectOutputString($response); $_SERVER['REQUEST_METHOD'] = 'GET'; - $_REQUEST['request'] = 'v1/test'; + $_REQUEST['request'] = 'v1/doesnotexist'; new Pickles\Router(); } // We're just testing that the class can be loaded, not that it will // work. That logic is off in ResourceTest - public function testFound() + public function testFoundWithUID() { - $this->expectOutputRegex('/{"status":405,"message":"Method not allowed."}/'); + $response = json_encode([ + 'meta' => [ + 'status' => 405, + 'message' => 'Method not allowed.', + ], + ]); + + $this->expectOutputString($response); $_SERVER['REQUEST_METHOD'] = 'GET'; - $_REQUEST['request'] = 'v1/resource/1'; + $_REQUEST['request'] = 'v1/router/1'; new Pickles\Router(); } diff --git a/tests/ValidateTest.php b/tests/ValidateTest.php index 8a2cf11..6bec4a6 100644 --- a/tests/ValidateTest.php +++ b/tests/ValidateTest.php @@ -2,84 +2,6 @@ // class ValidateTest extends PHPUnit_Framework_TestCase // { -// public function testFilterBoolean() -// { -// $this->assertTrue(Validate::isValid(true, ['filter:boolean' => 'error'])); -// } -// -// public function testFilterBooleanError() -// { -// $this->assertEquals(['error'], Validate::isValid(false, ['filter:boolean' => 'error'])); -// } -// -// public function testFilterEmail() -// { -// $this->assertTrue(Validate::isValid('foo@bar.com', ['filter:email' => 'error'])); -// } -// -// public function testFilterEmailError() -// { -// $this->assertEquals(['error'], Validate::isValid('invalid', ['filter:email' => 'error'])); -// } -// -// public function testFilterFloat() -// { -// $this->assertTrue(Validate::isValid(2.231981, ['filter:float' => 'error'])); -// } -// -// public function testFilterFloatError() -// { -// $this->assertEquals(['error'], Validate::isValid('invalid', ['filter:float' => 'error'])); -// } -// -// public function testFilterInt() -// { -// $this->assertTrue(Validate::isValid(2231981, ['filter:int' => 'error'])); -// } -// -// public function testFilterIntError() -// { -// $this->assertEquals(['error'], Validate::isValid('invalid', ['filter:int' => 'error'])); -// } -// -// public function testFilterIP() -// { -// $this->assertTrue(Validate::isValid('2.23.19.81', ['filter:ip' => 'error'])); -// } -// -// public function testFilterIPError() -// { -// $this->assertEquals(['error'], Validate::isValid('invalid', ['filter:ip' => 'error'])); -// } -// -// public function testFilterURL() -// { -// $this->assertTrue(Validate::isValid('http://foo.com/bar?stuff', ['filter:url' => 'error'])); -// } -// -// public function testFilterURLError() -// { -// $this->assertEquals(['error'], Validate::isValid('invalid', ['filter:url' => 'error'])); -// } -// -// /** -// * @expectedException Exception -// * @expectedExceptionMessage Invalid validation rule, expected: "validate:boolean|email|float|int|ip|url". -// */ -// public function testFilterVarInvalidRule() -// { -// Validate::isValid('value', ['filter' => 'foo']); -// } -// -// /** -// * @expectedException Exception -// * @expectedExceptionMessage Invalid filter, expecting boolean, email, float, int, ip or url. -// */ -// public function testFilterVarInvalidFilter() -// { -// Validate::isValid('value', ['filter:foo' => 'bar']); -// } -// // public function testLengthLessThan() // { // $this->assertTrue(Validate::isValid('value', ['length:<:10' => 'error']));