This commit is contained in:
2025-09-03 15:57:56 +02:00
parent a3f5b5a0cf
commit bd32f43c9e
441 changed files with 54487 additions and 256 deletions

View File

@ -0,0 +1,42 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Tests\Psr7\Factory;
use Interop\Http\Factory\RequestFactoryTestCase;
use InvalidArgumentException;
use Psr\Http\Message\UriInterface;
use Slim\Psr7\Factory\RequestFactory;
use Slim\Psr7\Factory\UriFactory;
use stdClass;
class RequestFactoryTest extends RequestFactoryTestCase
{
protected function createRequestFactory(): RequestFactory
{
return new RequestFactory();
}
protected function createUri($uri): UriInterface
{
return (new UriFactory())->createUri($uri);
}
public function testCreateRequestThrowsExceptionWithInvalidUri()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Parameter 2 of RequestFactory::createRequest() must be a string' .
' or a compatible UriInterface.');
$factory = $this->createRequestFactory();
$factory->createRequest('GET', new stdClass());
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Tests\Psr7\Factory;
use Interop\Http\Factory\ResponseFactoryTestCase;
use Psr\Http\Message\ResponseInterface;
use Slim\Psr7\Factory\ResponseFactory;
class ResponseFactoryTest extends ResponseFactoryTestCase
{
protected function createResponseFactory(): ResponseFactory
{
return new ResponseFactory();
}
protected function assertResponseCodeAndReasonPhrase(ResponseInterface $response, int $code, string $reasonPhrase)
{
$this->assertInstanceOf(ResponseInterface::class, $response);
$this->assertSame($code, $response->getStatusCode());
$this->assertSame($reasonPhrase, $response->getReasonPhrase());
}
/**
* @dataProvider dataCodes
*
* @param int $code
*/
public function testCreateResponseWithReasonPhrase(int $code)
{
$response = $this->factory->createResponse($code, 'Reason');
$this->assertResponse($response, $code);
$this->assertResponseCodeAndReasonPhrase($response, $code, 'Reason');
}
}

View File

@ -0,0 +1,208 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Tests\Psr7\Factory;
use Interop\Http\Factory\ServerRequestFactoryTestCase;
use InvalidArgumentException;
use Psr\Http\Message\UriInterface;
use ReflectionClass;
use Slim\Psr7\Environment;
use Slim\Psr7\Factory\ServerRequestFactory;
use Slim\Psr7\Factory\UriFactory;
use Slim\Psr7\UploadedFile;
use stdClass;
use function microtime;
use function time;
class ServerRequestFactoryTest extends ServerRequestFactoryTestCase
{
protected function createServerRequestFactory(): ServerRequestFactory
{
return new ServerRequestFactory();
}
protected function createUri($uri): UriInterface
{
return (new UriFactory())->createUri($uri);
}
public function testGetProtocolVersion()
{
$env = Environment::mock(['SERVER_PROTOCOL' => 'HTTP/1.0']);
$request = $this->createServerRequestFactory()->createServerRequest('GET', '', $env);
$this->assertEquals('1.0', $request->getProtocolVersion());
}
public function testCreateFromGlobals()
{
$GLOBALS['getallheaders_return'] = [
'ACCEPT' => 'application/json',
'ACCEPT-CHARSET' => 'utf-8',
'ACCEPT-LANGUAGE' => 'en-US',
'CONTENT-TYPE' => 'multipart/form-data',
'HOST' => 'example.com',
'USER-AGENT' => 'Slim Framework',
];
$_SERVER = Environment::mock([
'HTTP_HOST' => 'example.com',
'PHP_AUTH_PW' => 'sekrit',
'PHP_AUTH_USER' => 'josh',
'QUERY_STRING' => 'abc=123',
'REMOTE_ADDR' => '127.0.0.1',
'REQUEST_METHOD' => 'GET',
'REQUEST_TIME' => time(),
'REQUEST_TIME_FLOAT' => microtime(true),
'REQUEST_URI' => '/foo/bar',
'SCRIPT_NAME' => '/index.php',
'SERVER_NAME' => 'localhost',
'SERVER_PORT' => 8080,
'SERVER_PROTOCOL' => 'HTTP/1.1',
]);
$request = ServerRequestFactory::createFromGlobals();
unset($GLOBALS['getallheaders_return']);
$this->assertEquals('GET', $request->getMethod());
$this->assertEquals('1.1', $request->getProtocolVersion());
$this->assertEquals('application/json', $request->getHeaderLine('Accept'));
$this->assertEquals('utf-8', $request->getHeaderLine('Accept-Charset'));
$this->assertEquals('en-US', $request->getHeaderLine('Accept-Language'));
$this->assertEquals('multipart/form-data', $request->getHeaderLine('Content-Type'));
$uri = $request->getUri();
$this->assertEquals('josh:sekrit', $uri->getUserInfo());
$this->assertEquals('example.com', $uri->getHost());
$this->assertEquals('8080', $uri->getPort());
$this->assertEquals('/foo/bar', $uri->getPath());
$this->assertEquals('abc=123', $uri->getQuery());
$this->assertEquals('', $uri->getFragment());
}
public function testCreateFromGlobalsWithParsedBody()
{
$_SERVER = Environment::mock([
'HTTP_CONTENT_TYPE' => 'multipart/form-data',
'REQUEST_METHOD' => 'POST',
]);
$_POST = [
'def' => '456',
];
$request = ServerRequestFactory::createFromGlobals();
// $_POST should be placed into the parsed body
$this->assertEquals($_POST, $request->getParsedBody());
}
public function testCreateFromGlobalsBodyPointsToPhpInput()
{
$request = ServerRequestFactory::createFromGlobals();
$this->assertEquals('php://input', $request->getBody()->getMetadata('uri'));
}
public function testCreateFromGlobalsSetsACache()
{
$request = ServerRequestFactory::createFromGlobals();
// ensure that the Stream's $cache property has been set for this php://input stream
$stream = $request->getBody();
$class = new ReflectionClass($stream);
$property = $class->getProperty('cache');
$property->setAccessible(true);
$cacheStreamValue = $property->getValue($stream);
$this->assertNotNull($cacheStreamValue);
}
public function testCreateFromGlobalsWithUploadedFiles()
{
$_SERVER = Environment::mock([
'HTTP_CONTENT_TYPE' => 'multipart/form-data',
'REQUEST_METHOD' => 'POST',
]);
$_FILES = [
'uploaded_file' => [
'name' => [
0 => 'foo.jpg',
1 => 'bar.jpg',
],
'type' => [
0 => 'image/jpeg',
1 => 'image/jpeg',
],
'tmp_name' => [
0 => '/tmp/phpUA3XUw',
1 => '/tmp/phpXUFS0x',
],
'error' => [
0 => 0,
1 => 0,
],
'size' => [
0 => 358708,
1 => 236162,
],
]
];
$request = ServerRequestFactory::createFromGlobals();
// $_FILES should be mapped to an array of UploadedFile objects
$uploadedFiles = $request->getUploadedFiles();
$this->assertCount(1, $uploadedFiles);
$this->assertArrayHasKey('uploaded_file', $uploadedFiles);
$this->assertInstanceOf(UploadedFile::class, $uploadedFiles['uploaded_file'][0]);
$this->assertInstanceOf(UploadedFile::class, $uploadedFiles['uploaded_file'][1]);
}
public function testCreateFromGlobalsParsesBodyWithFragmentedContentType()
{
$_SERVER = Environment::mock([
'HTTP_CONTENT_TYPE' => 'application/x-www-form-urlencoded;charset=utf-8',
'REQUEST_METHOD' => 'POST',
]);
$_POST = [
'def' => '456',
];
$request = ServerRequestFactory::createFromGlobals();
$this->assertEquals($_POST, $request->getParsedBody());
}
public function testCreateServerRequestWithNullAsUri()
{
$this->expectException(InvalidArgumentException::class);
$env = Environment::mock();
$this->createServerRequestFactory()->createServerRequest('GET', null, $env);
}
public function testCreateServerRequestWithInvalidUriObject()
{
$this->expectException(InvalidArgumentException::class);
$env = Environment::mock();
$this->createServerRequestFactory()->createServerRequest('GET', new stdClass(), $env);
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Tests\Psr7\Factory;
use Interop\Http\Factory\StreamFactoryTestCase;
use InvalidArgumentException;
use RuntimeException;
use Slim\Psr7\Factory\StreamFactory;
class StreamFactoryTest extends StreamFactoryTestCase
{
public function tearDown(): void
{
if (isset($GLOBALS['fopen_return'])) {
unset($GLOBALS['fopen_return']);
}
}
protected function createStreamFactory(): StreamFactory
{
return new StreamFactory();
}
public function testCreateStreamThrowsRuntimeException()
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('StreamFactory::createStream() could not open temporary file stream.');
$GLOBALS['fopen_return'] = false;
$factory = $this->createStreamFactory();
$factory->createStream();
}
public function testCreateStreamFromFileThrowsRuntimeException()
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('StreamFactory::createStreamFromFile() could not create resource'
. ' from file `non-readable`');
$GLOBALS['fopen_return'] = false;
$factory = $this->createStreamFactory();
$factory->createStreamFromFile('non-readable');
}
public function testCreateStreamFromResourceThrowsRuntimeException()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Parameter 1 of StreamFactory::createStreamFromResource() must be a resource.');
$factory = $this->createStreamFactory();
$factory->createStreamFromResource('not-resource');
}
}

View File

@ -0,0 +1,114 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Tests\Psr7\Factory;
use Interop\Http\Factory\UploadedFileFactoryTestCase;
use InvalidArgumentException;
use Prophecy\PhpUnit\ProphecyTrait;
use Psr\Http\Message\StreamInterface;
use Slim\Psr7\Factory\StreamFactory;
use Slim\Psr7\Factory\UploadedFileFactory;
use function fopen;
use function fwrite;
use function rewind;
use function sys_get_temp_dir;
use function tempnam;
class UploadedFileFactoryTest extends UploadedFileFactoryTestCase
{
use ProphecyTrait;
protected function createUploadedFileFactory(): UploadedFileFactory
{
return new UploadedFileFactory();
}
protected function createStream($content): StreamInterface
{
$file = tempnam(sys_get_temp_dir(), 'Slim_Http_UploadedFileTest_');
$resource = fopen($file, 'r+');
fwrite($resource, $content);
rewind($resource);
return (new StreamFactory())->createStreamFromResource($resource);
}
/**
* Prophesize a `\Psr\Http\Message\StreamInterface` with a `getMetadata` method prophecy.
*
* @param string $argKey Argument for the method prophecy.
* @param mixed $returnValue Return value of the `getMetadata` method.
*
* @return StreamInterface
*/
protected function prophesizeStreamInterfaceWithGetMetadataMethod(string $argKey, $returnValue): StreamInterface
{
$streamProphecy = $this->prophesize(StreamInterface::class);
/** @noinspection PhpUndefinedMethodInspection */
$streamProphecy
->getMetadata($argKey)
->willReturn($returnValue)
->shouldBeCalled();
/** @var StreamInterface $stream */
$stream = $streamProphecy->reveal();
return $stream;
}
public function testCreateUploadedFileWithInvalidUri()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('File is not readable.');
// Prophesize a `\Psr\Http\Message\StreamInterface` with a `getMetadata` method prophecy.
$streamProphecy = $this->prophesize(StreamInterface::class);
/** @noinspection PhpUndefinedMethodInspection */
$streamProphecy
->getMetadata('uri')
->willReturn(null)
->shouldBeCalled();
/** @var StreamInterface $stream */
$stream = $streamProphecy->reveal();
$this->factory->createUploadedFile($stream);
}
public function testCreateUploadedFileWithNonReadableFile()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('File is not readable.');
// Prophesize a `\Psr\Http\Message\StreamInterface` with a `getMetadata` and `isReadable` method prophecies.
$streamProphecy = $this->prophesize(StreamInterface::class);
/** @noinspection PhpUndefinedMethodInspection */
$streamProphecy
->getMetadata('uri')
->willReturn('non-readable')
->shouldBeCalled();
/** @noinspection PhpUndefinedMethodInspection */
$streamProphecy
->isReadable()
->willReturn(false)
->shouldBeCalled();
/** @var StreamInterface $stream */
$stream = $streamProphecy->reveal();
$this->factory->createUploadedFile($stream);
}
}

View File

@ -0,0 +1,243 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Tests\Psr7\Factory;
use Interop\Http\Factory\UriFactoryTestCase;
use Slim\Psr7\Environment;
use Slim\Psr7\Factory\UriFactory;
class UriFactoryTest extends UriFactoryTestCase
{
protected function createUriFactory(): UriFactory
{
return new UriFactory();
}
public function testGetAuthorityWithUsername()
{
$uri = $this->createUriFactory()->createUri('https://josh@example.com/foo/bar?abc=123#section3');
$this->assertEquals('josh@example.com', $uri->getAuthority());
}
public function testGetAuthority()
{
$uri = $this->createUriFactory()->createUri('https://example.com/foo/bar?abc=123#section3');
$this->assertEquals('example.com', $uri->getAuthority());
}
public function testGetAuthorityWithNonStandardPort()
{
$uri = $this->createUriFactory()->createUri('https://example.com:400/foo/bar?abc=123#section3');
$this->assertEquals('example.com:400', $uri->getAuthority());
}
public function testGetUserInfoWithUsernameAndPassword()
{
$uri = $this->createUriFactory()->createUri('https://josh:sekrit@example.com:443/foo/bar?abc=123#section3');
$this->assertEquals('josh:sekrit', $uri->getUserInfo());
}
public function testGetUserInfoWithUsernameAndPasswordEncodesCorrectly()
{
$uri = $this
->createUriFactory()
->createUri('https://bob@example.com:pass:word@example.com:443/foo/bar?abc=123#section3');
$this->assertEquals('bob%40example.com:pass%3Aword', $uri->getUserInfo());
}
public function testGetUserInfoWithUsername()
{
$uri = $this->createUriFactory()->createUri('http://josh@example.com/foo/bar?abc=123#section3');
$this->assertEquals('josh', $uri->getUserInfo());
}
public function testGetUserInfoNone()
{
$uri = $this->createUriFactory()->createUri('https://example.com/foo/bar?abc=123#section3');
$this->assertEquals('', $uri->getUserInfo());
}
public function testCreateFromString()
{
$uri = $this->createUriFactory()->createUri('https://example.com:8080/foo/bar?abc=123');
$this->assertEquals('https', $uri->getScheme());
$this->assertEquals('example.com', $uri->getHost());
$this->assertEquals('8080', $uri->getPort());
$this->assertEquals('/foo/bar', $uri->getPath());
$this->assertEquals('abc=123', $uri->getQuery());
}
public function testCreateFromGlobals()
{
$globals = Environment::mock([
'SCRIPT_NAME' => '/index.php',
'REQUEST_URI' => '/foo/bar?baz=1',
'PHP_AUTH_USER' => 'josh',
'PHP_AUTH_PW' => 'sekrit',
'QUERY_STRING' => 'abc=123',
'HTTP_HOST' => 'example.com:8080',
'SERVER_PORT' => 8080,
]);
$uri = $this->createUriFactory()->createFromGlobals($globals);
$this->assertEquals('josh:sekrit', $uri->getUserInfo());
$this->assertEquals('example.com', $uri->getHost());
$this->assertEquals('8080', $uri->getPort());
$this->assertEquals('/foo/bar', $uri->getPath());
$this->assertEquals('abc=123', $uri->getQuery());
$this->assertEquals('', $uri->getFragment());
}
public function testCreateFromGlobalsWithHttps()
{
$globals = Environment::mock(
[
'HTTPS' => 'on',
'HTTP_HOST' => 'example.com'
]
);
// Make the 'SERVER_PORT' empty as we want to test if the default server port gets set correctly.
$globals['SERVER_PORT'] = '';
$uri = $this->createUriFactory()->createFromGlobals($globals);
$this->assertEquals('https', $uri->getScheme());
$this->assertEquals('example.com', $uri->getHost());
// The port is expected to be NULL as the server port is the default standard (443 in case of https).
$this->assertNull($uri->getPort());
}
public function testCreateFromGlobalsUsesServerNameAsHostIfHostHeaderIsNotPresent()
{
$globals = Environment::mock([
'SERVER_NAME' => 'example.com',
]);
$uri = $this->createUriFactory()->createFromGlobals($globals);
$this->assertEquals('example.com', $uri->getHost());
}
public function testCreateFromGlobalWithIPv6HostNoPort()
{
$environment = Environment::mock([
'SCRIPT_NAME' => '/index.php',
'REQUEST_URI' => '/foo/bar',
'PHP_AUTH_USER' => 'josh',
'PHP_AUTH_PW' => 'sekrit',
'QUERY_STRING' => 'abc=123',
'HTTP_HOST' => '[2001:db8::1]',
'REMOTE_ADDR' => '2001:db8::1',
'SERVER_PORT' => 8080,
]);
$uri = $this->createUriFactory()->createFromGlobals($environment);
$this->assertEquals('josh:sekrit', $uri->getUserInfo());
$this->assertEquals('[2001:db8::1]', $uri->getHost());
$this->assertEquals('8080', $uri->getPort());
$this->assertEquals('/foo/bar', $uri->getPath());
$this->assertEquals('abc=123', $uri->getQuery());
$this->assertEquals('', $uri->getFragment());
}
public function testCreateFromGlobalsWithIPv6HostWithPort()
{
$globals = Environment::mock([
'SCRIPT_NAME' => '/index.php',
'REQUEST_URI' => '/foo/bar',
'PHP_AUTH_USER' => 'josh',
'PHP_AUTH_PW' => 'sekrit',
'QUERY_STRING' => 'abc=123',
'HTTP_HOST' => '[2001:db8::1]:8080',
'REMOTE_ADDR' => '2001:db8::1',
'SERVER_PORT' => 8080,
]);
$uri = $this->createUriFactory()->createFromGlobals($globals);
$this->assertEquals('josh:sekrit', $uri->getUserInfo());
$this->assertEquals('[2001:db8::1]', $uri->getHost());
$this->assertEquals('8080', $uri->getPort());
$this->assertEquals('/foo/bar', $uri->getPath());
$this->assertEquals('abc=123', $uri->getQuery());
$this->assertEquals('', $uri->getFragment());
}
public function testCreateFromGlobalsWithBasePathContainingSpace()
{
$globals = Environment::mock([
'SCRIPT_NAME' => "/f'oo bar/index.php",
'REQUEST_URI' => "/f%27oo%20bar/baz",
]);
$uri = $this->createUriFactory()->createFromGlobals($globals);
$this->assertEquals('/f%27oo%20bar/baz', $uri->getPath());
}
public function testWithPathWhenBaseRootIsEmpty()
{
$globals = Environment::mock([
'SCRIPT_NAME' => '/index.php',
'REQUEST_URI' => '/bar',
]);
$uri = $this->createUriFactory()->createFromGlobals($globals);
$this->assertEquals('http://localhost/test', (string) $uri->withPath('test'));
}
/**
* When the URL is /foo/index.php/bar/baz, we need the baseURL to be
* /foo/index.php so that routing works correctly.
*
* @ticket 1639 as a fix to 1590 broke this.
*/
public function testRequestURIContainsIndexDotPhp()
{
$uri = $this->createUriFactory()->createFromGlobals(
Environment::mock(
[
'SCRIPT_NAME' => '/foo/index.php',
'REQUEST_URI' => '/foo/index.php/bar/baz',
]
)
);
$this->assertSame('/foo/index.php/bar/baz', $uri->getPath());
}
public function testRequestURICanContainParams()
{
$uri = $this->createUriFactory()->createFromGlobals(
Environment::mock(
[
'REQUEST_URI' => '/foo?abc=123',
]
)
);
$this->assertEquals('abc=123', $uri->getQuery());
}
public function testUriDistinguishZeroFromEmptyString()
{
$expected = 'https://0:0@0:1/0?0#0';
$this->assertSame($expected, (string) $this->createUriFactory()->createUri($expected));
}
}