|
|
|
|
@ -40,16 +40,16 @@ class EngineTest extends TestCase
|
|
|
|
|
};
|
|
|
|
|
$this->assertTrue($engine->getInitializedVar());
|
|
|
|
|
|
|
|
|
|
// we need to setup a dummy route
|
|
|
|
|
$engine->route('/someRoute', function () { });
|
|
|
|
|
$engine->request()->url = '/someRoute';
|
|
|
|
|
// we need to setup a dummy route
|
|
|
|
|
$engine->route('/someRoute', function () {});
|
|
|
|
|
$engine->request()->url = '/someRoute';
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($engine->router()->caseSensitive);
|
|
|
|
|
$this->assertTrue($engine->response()->content_length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testInitBeforeStartV2OutputBuffering(): void
|
|
|
|
|
public function testInitBeforeStartV2OutputBuffering(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new class extends Engine {
|
|
|
|
|
public function getInitializedVar(): bool
|
|
|
|
|
@ -57,12 +57,12 @@ class EngineTest extends TestCase
|
|
|
|
|
return $this->initialized;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
$engine->set('flight.v2.output_buffering', true);
|
|
|
|
|
$engine->set('flight.v2.output_buffering', true);
|
|
|
|
|
$this->assertTrue($engine->getInitializedVar());
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
// This is a necessary evil because of how the v2 output buffer works.
|
|
|
|
|
ob_end_clean();
|
|
|
|
|
// This is a necessary evil because of how the v2 output buffer works.
|
|
|
|
|
ob_end_clean();
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($engine->router()->caseSensitive);
|
|
|
|
|
$this->assertTrue($engine->response()->content_length);
|
|
|
|
|
@ -96,8 +96,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Cannot override an existing framework method.');
|
|
|
|
|
$engine->map('_start', function () {
|
|
|
|
|
});
|
|
|
|
|
$engine->map('_start', function () {});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testRegisterExistingMethod(): void
|
|
|
|
|
@ -111,7 +110,7 @@ class EngineTest extends TestCase
|
|
|
|
|
public function testSetArrayOfValues(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->set([ 'key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$engine->set(['key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$this->assertEquals('value1', $engine->get('key1'));
|
|
|
|
|
$this->assertEquals('value2', $engine->get('key2'));
|
|
|
|
|
}
|
|
|
|
|
@ -153,8 +152,8 @@ class EngineTest extends TestCase
|
|
|
|
|
$this->expectOutputString('<h1>404 Not Found</h1><h3>The page you have requested could not be found.</h3>');
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testStartWithRouteButReturnedValueThrows404V2OutputBuffering(): void
|
|
|
|
|
|
|
|
|
|
public function testStartWithRouteButReturnedValueThrows404V2OutputBuffering(): void
|
|
|
|
|
{
|
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/someRoute';
|
|
|
|
|
@ -165,7 +164,7 @@ class EngineTest extends TestCase
|
|
|
|
|
return $this->initialized;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
$engine->set('flight.v2.output_buffering', true);
|
|
|
|
|
$engine->set('flight.v2.output_buffering', true);
|
|
|
|
|
$engine->route('/someRoute', function () {
|
|
|
|
|
echo 'i ran';
|
|
|
|
|
return true;
|
|
|
|
|
@ -185,18 +184,18 @@ class EngineTest extends TestCase
|
|
|
|
|
return $this->initialized;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// First route that returns true (should continue routing)
|
|
|
|
|
$engine->route('/someRoute', function () {
|
|
|
|
|
echo 'first route ran, ';
|
|
|
|
|
return true;
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Second route that should be found and executed
|
|
|
|
|
$engine->route('/someRoute', function () {
|
|
|
|
|
echo 'second route executed!';
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('first route ran, second route executed!');
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
@ -211,13 +210,13 @@ class EngineTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
return $this->initialized;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getLoader()
|
|
|
|
|
{
|
|
|
|
|
return $this->loader;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Mock response to prevent actual headers
|
|
|
|
|
$engine->getLoader()->register('response', function () {
|
|
|
|
|
return new class extends Response {
|
|
|
|
|
@ -227,23 +226,23 @@ class EngineTest extends TestCase
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// First route that returns true and matches POST
|
|
|
|
|
$engine->route('POST /someRoute', function () {
|
|
|
|
|
echo 'first POST route ran, ';
|
|
|
|
|
return true;
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Second route that matches URL but wrong method (GET) - should be captured for 405
|
|
|
|
|
$engine->route('GET /someRoute', function () {
|
|
|
|
|
echo 'should not execute';
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Third route that matches POST and should execute
|
|
|
|
|
$engine->route('POST /someRoute', function () {
|
|
|
|
|
echo 'second POST route executed!';
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('first POST route ran, second POST route executed!');
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
@ -259,46 +258,46 @@ class EngineTest extends TestCase
|
|
|
|
|
return $this->initialized;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Route that returns true (continues iteration)
|
|
|
|
|
$engine->route('/someRoute', function () {
|
|
|
|
|
echo 'first route ran, ';
|
|
|
|
|
return true;
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Route with different URL that won't match
|
|
|
|
|
$engine->route('/differentRoute', function () {
|
|
|
|
|
echo 'should not execute';
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// No more matching routes - should reach end of iterator and return 404
|
|
|
|
|
$this->expectOutputString('<h1>404 Not Found</h1><h3>The page you have requested could not be found.</h3>');
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDoubleStart(): void
|
|
|
|
|
public function testDoubleStart(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->route('/someRoute', function () {
|
|
|
|
|
echo 'i ran';
|
|
|
|
|
}, true);
|
|
|
|
|
$engine->request()->url = '/someRoute';
|
|
|
|
|
$engine->start();
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->route('/someRoute', function () {
|
|
|
|
|
echo 'i ran';
|
|
|
|
|
}, true);
|
|
|
|
|
$engine->request()->url = '/someRoute';
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$request = $engine->request();
|
|
|
|
|
$response = $engine->response();
|
|
|
|
|
$request = $engine->request();
|
|
|
|
|
$response = $engine->response();
|
|
|
|
|
|
|
|
|
|
// This is pretending like this is embodied in a platform like swoole where
|
|
|
|
|
// another request comes in while still holding all the same state.
|
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/someRoute';
|
|
|
|
|
$engine->start();
|
|
|
|
|
// This is pretending like this is embodied in a platform like swoole where
|
|
|
|
|
// another request comes in while still holding all the same state.
|
|
|
|
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
|
|
|
|
$_SERVER['REQUEST_URI'] = '/someRoute';
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($request === $engine->request());
|
|
|
|
|
$this->assertFalse($response === $engine->response());
|
|
|
|
|
$this->assertFalse($request === $engine->request());
|
|
|
|
|
$this->assertFalse($response === $engine->response());
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('i rani ran');
|
|
|
|
|
}
|
|
|
|
|
$this->expectOutputString('i rani ran');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testStopWithCode(): void
|
|
|
|
|
{
|
|
|
|
|
@ -323,7 +322,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$this->assertEquals(500, $engine->response()->status());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testStopWithCodeV2OutputBuffering(): void
|
|
|
|
|
public function testStopWithCodeV2OutputBuffering(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new class extends Engine {
|
|
|
|
|
public function getLoader()
|
|
|
|
|
@ -340,13 +339,13 @@ class EngineTest extends TestCase
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
$engine->set('flight.v2.output_buffering', true);
|
|
|
|
|
$engine->route('/testRoute', function () use ($engine) {
|
|
|
|
|
echo 'I am a teapot';
|
|
|
|
|
$engine->stop(500);
|
|
|
|
|
});
|
|
|
|
|
$engine->request()->url = '/testRoute';
|
|
|
|
|
$engine->start();
|
|
|
|
|
$engine->set('flight.v2.output_buffering', true);
|
|
|
|
|
$engine->route('/testRoute', function () use ($engine) {
|
|
|
|
|
echo 'I am a teapot';
|
|
|
|
|
$engine->stop(500);
|
|
|
|
|
});
|
|
|
|
|
$engine->request()->url = '/testRoute';
|
|
|
|
|
$engine->start();
|
|
|
|
|
$this->expectOutputString('I am a teapot');
|
|
|
|
|
$this->assertEquals(500, $engine->response()->status());
|
|
|
|
|
}
|
|
|
|
|
@ -409,7 +408,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$this->expectOutputString('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testOptionsRoute(): void
|
|
|
|
|
public function testOptionsRoute(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->route('GET /someRoute', function () {
|
|
|
|
|
@ -421,7 +420,7 @@ class EngineTest extends TestCase
|
|
|
|
|
|
|
|
|
|
// No body should be sent
|
|
|
|
|
$this->expectOutputString('');
|
|
|
|
|
$this->assertEquals('GET, HEAD, OPTIONS', $engine->response()->headers()['Allow']);
|
|
|
|
|
$this->assertEquals('GET, HEAD, OPTIONS', $engine->response()->headers()['Allow']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testHalt(): void
|
|
|
|
|
@ -498,46 +497,46 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->json(['key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$this->assertEquals('application/json', $engine->response()->headers()['Content-Type']);
|
|
|
|
|
$this->assertEquals(200, $engine->response()->status());
|
|
|
|
|
$this->assertEquals('{"key1":"value1","key2":"value2"}', $engine->response()->getBody());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonWithDuplicateDefaultFlags()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$flags = JSON_HEX_TAG | JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
|
|
|
|
|
// utf8 emoji
|
|
|
|
|
$engine->json(['key1' => 'value1', 'key2' => 'value2', 'utf8_emoji' => '😀'], 201, true, '', $flags);
|
|
|
|
|
$this->assertEquals('application/json', $engine->response()->headers()['Content-Type']);
|
|
|
|
|
$this->assertEquals(201, $engine->response()->status());
|
|
|
|
|
$this->assertEquals('{"key1":"value1","key2":"value2","utf8_emoji":"😀"}', $engine->response()->getBody());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonThrowOnErrorByDefault(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Malformed UTF-8 characters, possibly incorrectly encoded');
|
|
|
|
|
$engine->json(['key1' => 'value1', 'key2' => 'value2', 'utf8_emoji' => "\xB1\x31"]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonV2OutputBuffering(): void
|
|
|
|
|
$this->assertEquals('{"key1":"value1","key2":"value2"}', $engine->response()->getBody());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonWithDuplicateDefaultFlags()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->response()->v2_output_buffering = true;
|
|
|
|
|
$flags = JSON_HEX_TAG | JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
|
|
|
|
|
// utf8 emoji
|
|
|
|
|
$engine->json(['key1' => 'value1', 'key2' => 'value2', 'utf8_emoji' => '😀'], 201, true, '', $flags);
|
|
|
|
|
$this->assertEquals('application/json', $engine->response()->headers()['Content-Type']);
|
|
|
|
|
$this->assertEquals(201, $engine->response()->status());
|
|
|
|
|
$this->assertEquals('{"key1":"value1","key2":"value2","utf8_emoji":"😀"}', $engine->response()->getBody());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonThrowOnErrorByDefault(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage('Malformed UTF-8 characters, possibly incorrectly encoded');
|
|
|
|
|
$engine->json(['key1' => 'value1', 'key2' => 'value2', 'utf8_emoji' => "\xB1\x31"]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonV2OutputBuffering(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->response()->v2_output_buffering = true;
|
|
|
|
|
$engine->json(['key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$this->expectOutputString('{"key1":"value1","key2":"value2"}');
|
|
|
|
|
$this->assertEquals('application/json', $engine->response()->headers()['Content-Type']);
|
|
|
|
|
$this->assertEquals(200, $engine->response()->status());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonHalt(): void
|
|
|
|
|
public function testJsonHalt(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$this->expectOutputString('{"key1":"value1","key2":"value2"}');
|
|
|
|
|
$this->expectOutputString('{"key1":"value1","key2":"value2"}');
|
|
|
|
|
$engine->jsonHalt(['key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$this->assertEquals('application/json', $engine->response()->headers()['Content-Type']);
|
|
|
|
|
$this->assertEquals(200, $engine->response()->status());
|
|
|
|
|
$this->assertEquals('{"key1":"value1","key2":"value2"}', $engine->response()->getBody());
|
|
|
|
|
$this->assertEquals('{"key1":"value1","key2":"value2"}', $engine->response()->getBody());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonP(): void
|
|
|
|
|
@ -547,13 +546,13 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->jsonp(['key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$this->assertEquals('application/javascript; charset=utf-8', $engine->response()->headers()['Content-Type']);
|
|
|
|
|
$this->assertEquals(200, $engine->response()->status());
|
|
|
|
|
$this->assertEquals('whatever({"key1":"value1","key2":"value2"});', $engine->response()->getBody());
|
|
|
|
|
$this->assertEquals('whatever({"key1":"value1","key2":"value2"});', $engine->response()->getBody());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonPV2OutputBuffering(): void
|
|
|
|
|
public function testJsonPV2OutputBuffering(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->response()->v2_output_buffering = true;
|
|
|
|
|
$engine->response()->v2_output_buffering = true;
|
|
|
|
|
$engine->request()->query['jsonp'] = 'whatever';
|
|
|
|
|
$engine->jsonp(['key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$this->expectOutputString('whatever({"key1":"value1","key2":"value2"});');
|
|
|
|
|
@ -570,10 +569,10 @@ class EngineTest extends TestCase
|
|
|
|
|
$this->assertEquals(200, $engine->response()->status());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testJsonpBadParamV2OutputBuffering(): void
|
|
|
|
|
public function testJsonpBadParamV2OutputBuffering(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->response()->v2_output_buffering = true;
|
|
|
|
|
$engine->response()->v2_output_buffering = true;
|
|
|
|
|
$engine->jsonp(['key1' => 'value1', 'key2' => 'value2']);
|
|
|
|
|
$this->expectOutputString('({"key1":"value1","key2":"value2"});');
|
|
|
|
|
$this->assertEquals('application/javascript; charset=utf-8', $engine->response()->headers()['Content-Type']);
|
|
|
|
|
@ -608,7 +607,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine = new Engine;
|
|
|
|
|
$_SERVER['HTTP_IF_MODIFIED_SINCE'] = 'Fri, 13 Feb 2009 23:31:30 GMT';
|
|
|
|
|
$engine->lastModified(1234567890);
|
|
|
|
|
$this->assertTrue(empty($engine->response()->headers()['Last-Modified']));
|
|
|
|
|
$this->assertTrue(empty($engine->response()->headers()['Last-Modified']));
|
|
|
|
|
$this->assertEquals(304, $engine->response()->status());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -618,7 +617,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->route('/path1/@param:[0-9]{3}', function () {
|
|
|
|
|
echo 'I win';
|
|
|
|
|
}, false, 'path1');
|
|
|
|
|
$url = $engine->getUrl('path1', [ 'param' => 123 ]);
|
|
|
|
|
$url = $engine->getUrl('path1', ['param' => 123]);
|
|
|
|
|
$this->assertEquals('/path1/123', $url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -628,7 +627,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->route('/item/@item_param:[a-z0-9]{16}/by-status/@token:[a-z0-9]{16}', function () {
|
|
|
|
|
echo 'I win';
|
|
|
|
|
}, false, 'path_item_1');
|
|
|
|
|
$url = $engine->getUrl('path_item_1', [ 'item_param' => 1234567890123456, 'token' => 6543210987654321 ]);
|
|
|
|
|
$url = $engine->getUrl('path_item_1', ['item_param' => 1234567890123456, 'token' => 6543210987654321]);
|
|
|
|
|
$this->assertEquals('/item/1234567890123456/by-status/6543210987654321', $url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -666,8 +665,7 @@ class EngineTest extends TestCase
|
|
|
|
|
|
|
|
|
|
public function testMiddlewareCallableFunctionReturnFalse(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new class extends Engine {
|
|
|
|
|
};
|
|
|
|
|
$engine = new class extends Engine {};
|
|
|
|
|
$engine->route('/path1/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
})
|
|
|
|
|
@ -742,7 +740,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$this->expectOutputString('OK123after123');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testMiddlewareClassStringNoContainer(): void
|
|
|
|
|
public function testMiddlewareClassStringNoContainer(): void
|
|
|
|
|
{
|
|
|
|
|
$middleware = new class {
|
|
|
|
|
public function after($params)
|
|
|
|
|
@ -761,10 +759,10 @@ class EngineTest extends TestCase
|
|
|
|
|
$this->expectOutputString('OK123after123');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testMiddlewareClassStringWithContainer(): void
|
|
|
|
|
public function testMiddlewareClassStringWithContainer(): void
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$dice = new \Dice\Dice();
|
|
|
|
|
$dice = $dice->addRule('*', [
|
|
|
|
|
'substitutions' => [
|
|
|
|
|
@ -774,7 +772,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
|
|
|
|
|
return $dice->create($class, $params);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$engine->route('/path1/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
@ -794,8 +792,7 @@ class EngineTest extends TestCase
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
$engine = new class extends Engine {
|
|
|
|
|
};
|
|
|
|
|
$engine = new class extends Engine {};
|
|
|
|
|
|
|
|
|
|
$engine->route('/path1/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
@ -850,7 +847,7 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->route('/path1/@id/subpath1/@another_id', function () {
|
|
|
|
|
echo 'OK';
|
|
|
|
|
})->addMiddleware([ $middleware, $middleware2 ]);
|
|
|
|
|
})->addMiddleware([$middleware, $middleware2]);
|
|
|
|
|
|
|
|
|
|
$engine->request()->url = '/path1/123/subpath1/456';
|
|
|
|
|
$engine->start();
|
|
|
|
|
@ -887,14 +884,15 @@ class EngineTest extends TestCase
|
|
|
|
|
$router->map('/@cool_id', function () {
|
|
|
|
|
echo 'OK';
|
|
|
|
|
});
|
|
|
|
|
}, [ $middleware, $middleware2 ]);
|
|
|
|
|
}, [$middleware, $middleware2]);
|
|
|
|
|
|
|
|
|
|
$engine->request()->url = '/path1/123/subpath1/456';
|
|
|
|
|
$engine->start();
|
|
|
|
|
$this->expectOutputString('before456before123OKafter123456after123');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerBadClass() {
|
|
|
|
|
public function testContainerBadClass()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
|
|
|
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
|
@ -902,47 +900,50 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->registerContainerHandler('BadClass');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerDice() {
|
|
|
|
|
public function testContainerDice()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$dice = new \Dice\Dice();
|
|
|
|
|
$dice = $dice->addRules([
|
|
|
|
|
PdoWrapper::class => [
|
|
|
|
|
'shared' => true,
|
|
|
|
|
'constructParams' => [ 'sqlite::memory:' ]
|
|
|
|
|
'constructParams' => ['sqlite::memory:']
|
|
|
|
|
]
|
|
|
|
|
]);
|
|
|
|
|
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
|
|
|
|
|
return $dice->create($class, $params);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class.'->testTheContainer');
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class . '->testTheContainer');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('yay! I injected a collection, and it has 1 items');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerDicePdoWrapperTest() {
|
|
|
|
|
public function testContainerDicePdoWrapperTest()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$dice = new \Dice\Dice();
|
|
|
|
|
$dice = $dice->addRules([
|
|
|
|
|
PdoWrapper::class => [
|
|
|
|
|
'shared' => true,
|
|
|
|
|
'constructParams' => [ 'sqlite::memory:' ]
|
|
|
|
|
'constructParams' => ['sqlite::memory:']
|
|
|
|
|
]
|
|
|
|
|
]);
|
|
|
|
|
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
|
|
|
|
|
return $dice->create($class, $params);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class.'->testThePdoWrapper');
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class . '->testThePdoWrapper');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('Yay! I injected a PdoWrapper, and it returned the number 5 from the database!');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerDiceFlightEngine() {
|
|
|
|
|
public function testContainerDiceFlightEngine()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$engine->set('test_me_out', 'You got it boss!');
|
|
|
|
|
$dice = new \Dice\Dice();
|
|
|
|
|
@ -954,44 +955,46 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
|
|
|
|
|
return $dice->create($class, $params);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', ContainerDefault::class.'->echoTheContainer');
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', ContainerDefault::class . '->echoTheContainer');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('You got it boss!');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerDiceBadClass() {
|
|
|
|
|
public function testContainerDiceBadClass()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$dice = new \Dice\Dice();
|
|
|
|
|
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
|
|
|
|
|
return $dice->create($class, $params);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', 'BadClass->testTheContainer');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage("Class 'BadClass' not found. Is it being correctly autoloaded with Flight::path()?");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerDiceBadMethod() {
|
|
|
|
|
public function testContainerDiceBadMethod()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$dice = new \Dice\Dice();
|
|
|
|
|
$dice = $dice->addRules([
|
|
|
|
|
PdoWrapper::class => [
|
|
|
|
|
'shared' => true,
|
|
|
|
|
'constructParams' => [ 'sqlite::memory:' ]
|
|
|
|
|
'constructParams' => ['sqlite::memory:']
|
|
|
|
|
]
|
|
|
|
|
]);
|
|
|
|
|
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
|
|
|
|
|
return $dice->create($class, $params);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class.'->badMethod');
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class . '->badMethod');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
@ -1000,46 +1003,49 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerPsr11(): void {
|
|
|
|
|
public function testContainerPsr11(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$container = new \League\Container\Container();
|
|
|
|
|
$container->add(Container::class)->addArgument(Collection::class)->addArgument(PdoWrapper::class);
|
|
|
|
|
$container->add(Collection::class);
|
|
|
|
|
$container->add(PdoWrapper::class)->addArgument('sqlite::memory:');
|
|
|
|
|
$engine->registerContainerHandler($container);
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class.'->testTheContainer');
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class . '->testTheContainer');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('yay! I injected a collection, and it has 1 items');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerPsr11ClassNotFound() {
|
|
|
|
|
public function testContainerPsr11ClassNotFound()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$container = new \League\Container\Container();
|
|
|
|
|
$container->add(Container::class)->addArgument(Collection::class);
|
|
|
|
|
$container->add(Collection::class);
|
|
|
|
|
$engine->registerContainerHandler($container);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', 'BadClass->testTheContainer');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage("Class 'BadClass' not found. Is it being correctly autoloaded with Flight::path()?");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testContainerPsr11MethodNotFound(): void {
|
|
|
|
|
public function testContainerPsr11MethodNotFound(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$container = new \League\Container\Container();
|
|
|
|
|
$container->add(Container::class)->addArgument(Collection::class)->addArgument(PdoWrapper::class);
|
|
|
|
|
$container->add(Collection::class);
|
|
|
|
|
$container->add(PdoWrapper::class)->addArgument('sqlite::memory:');
|
|
|
|
|
$engine->registerContainerHandler($container);
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class.'->badMethod');
|
|
|
|
|
|
|
|
|
|
$engine->route('/container', Container::class . '->badMethod');
|
|
|
|
|
$engine->request()->url = '/container';
|
|
|
|
|
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
@ -1048,7 +1054,8 @@ class EngineTest extends TestCase
|
|
|
|
|
$engine->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testRouteFoundButBadMethod(): void {
|
|
|
|
|
public function testRouteFoundButBadMethod(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new class extends Engine {
|
|
|
|
|
public function getLoader()
|
|
|
|
|
{
|
|
|
|
|
@ -1068,30 +1075,30 @@ class EngineTest extends TestCase
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->route('POST /path1/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
});
|
|
|
|
|
$engine->route('POST /path1/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->route('GET /path2/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
});
|
|
|
|
|
$engine->route('GET /path2/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->route('PATCH /path3/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
});
|
|
|
|
|
$engine->route('PATCH /path3/@id', function ($id) {
|
|
|
|
|
echo 'OK' . $id;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$engine->request()->url = '/path1/123';
|
|
|
|
|
$engine->request()->method = 'GET';
|
|
|
|
|
$engine->request()->url = '/path1/123';
|
|
|
|
|
$engine->request()->method = 'GET';
|
|
|
|
|
|
|
|
|
|
$engine->start();
|
|
|
|
|
|
|
|
|
|
$this->expectOutputString('Method Not Allowed. Allowed Methods are: POST, OPTIONS');
|
|
|
|
|
$this->expectOutputString('Method Not Allowed. Allowed Methods are: POST, OPTIONS');
|
|
|
|
|
$this->assertEquals(405, $engine->response()->status());
|
|
|
|
|
$this->assertEquals('Method Not Allowed. Allowed Methods are: POST, OPTIONS', $engine->response()->getBody());
|
|
|
|
|
$this->assertEquals('POST, OPTIONS', $engine->response()->headers()['Allow']);
|
|
|
|
|
}
|
|
|
|
|
$this->assertEquals('Method Not Allowed. Allowed Methods are: POST, OPTIONS', $engine->response()->getBody());
|
|
|
|
|
$this->assertEquals('POST, OPTIONS', $engine->response()->headers()['Allow']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDownload(): void
|
|
|
|
|
public function testDownload(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new class extends Engine {
|
|
|
|
|
public function getLoader()
|
|
|
|
|
@ -1102,26 +1109,26 @@ class EngineTest extends TestCase
|
|
|
|
|
// doing this so we can overwrite some parts of the response
|
|
|
|
|
$engine->getLoader()->register('response', function () {
|
|
|
|
|
return new class extends Response {
|
|
|
|
|
public $headersSent = [];
|
|
|
|
|
public $headersSent = [];
|
|
|
|
|
public function setRealHeader(
|
|
|
|
|
string $header_string,
|
|
|
|
|
bool $replace = true,
|
|
|
|
|
int $response_code = 0
|
|
|
|
|
): self {
|
|
|
|
|
$this->headersSent[] = $header_string;
|
|
|
|
|
$this->headersSent[] = $header_string;
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
$tmpfile = tmpfile();
|
|
|
|
|
fwrite($tmpfile, 'I am a teapot');
|
|
|
|
|
$streamPath = stream_get_meta_data($tmpfile)['uri'];
|
|
|
|
|
$this->expectOutputString('I am a teapot');
|
|
|
|
|
$tmpfile = tmpfile();
|
|
|
|
|
fwrite($tmpfile, 'I am a teapot');
|
|
|
|
|
$streamPath = stream_get_meta_data($tmpfile)['uri'];
|
|
|
|
|
$this->expectOutputString('I am a teapot');
|
|
|
|
|
$engine->download($streamPath);
|
|
|
|
|
$this->assertContains('Content-Disposition: attachment; filename="'.basename($streamPath).'"', $engine->response()->headersSent);
|
|
|
|
|
$this->assertContains('Content-Disposition: attachment; filename="' . basename($streamPath) . '"', $engine->response()->headersSent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDownloadWithDefaultFileName(): void
|
|
|
|
|
public function testDownloadWithDefaultFileName(): void
|
|
|
|
|
{
|
|
|
|
|
$engine = new class extends Engine {
|
|
|
|
|
public function getLoader()
|
|
|
|
|
@ -1132,30 +1139,30 @@ class EngineTest extends TestCase
|
|
|
|
|
// doing this so we can overwrite some parts of the response
|
|
|
|
|
$engine->getLoader()->register('response', function () {
|
|
|
|
|
return new class extends Response {
|
|
|
|
|
public $headersSent = [];
|
|
|
|
|
public $headersSent = [];
|
|
|
|
|
public function setRealHeader(
|
|
|
|
|
string $header_string,
|
|
|
|
|
bool $replace = true,
|
|
|
|
|
int $response_code = 0
|
|
|
|
|
): self {
|
|
|
|
|
$this->headersSent[] = $header_string;
|
|
|
|
|
$this->headersSent[] = $header_string;
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
$tmpfile = tmpfile();
|
|
|
|
|
fwrite($tmpfile, 'I am a teapot');
|
|
|
|
|
$streamPath = stream_get_meta_data($tmpfile)['uri'];
|
|
|
|
|
$this->expectOutputString('I am a teapot');
|
|
|
|
|
$tmpfile = tmpfile();
|
|
|
|
|
fwrite($tmpfile, 'I am a teapot');
|
|
|
|
|
$streamPath = stream_get_meta_data($tmpfile)['uri'];
|
|
|
|
|
$this->expectOutputString('I am a teapot');
|
|
|
|
|
$engine->download($streamPath, 'something.txt');
|
|
|
|
|
$this->assertContains('Content-Disposition: attachment; filename="something.txt"', $engine->response()->headersSent);
|
|
|
|
|
$this->assertContains('Content-Disposition: attachment; filename="something.txt"', $engine->response()->headersSent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDownloadBadPath() {
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage("/path/to/nowhere cannot be found.");
|
|
|
|
|
$engine->download('/path/to/nowhere');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDownloadBadPath()
|
|
|
|
|
{
|
|
|
|
|
$engine = new Engine();
|
|
|
|
|
$this->expectException(Exception::class);
|
|
|
|
|
$this->expectExceptionMessage("/path/to/nowhere cannot be found.");
|
|
|
|
|
$engine->download('/path/to/nowhere');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|