Clean up MessageTest and documentation for Message classes

This commit is contained in:
PJ Dietz 2018-06-22 13:43:44 -04:00
parent b82ebf6d95
commit 72d5df244d
3 changed files with 109 additions and 98 deletions

View File

@ -15,20 +15,19 @@ abstract class Message implements MessageInterface
/** @var StreamInterface */
protected $body;
/** @var string */
protected $protocolVersion = "1.1";
protected $protocolVersion = '1.1';
/**
* Create a new Message, optionally with headers and a body.
*
* If provided, $headers MUST by an associative array with header field
* names as (string) keys and lists of header field values (string[])
* as values.
* $headers is an optional associative array with header field names as
* (string) keys and lists of header field values (string[]) as values.
*
* If no StreamInterface is provided for $body, the instance will create
* a NullStream instance for the message body.
*
* @param array $headers Associative array of headers fields with header
* field names as keys and list arrays of field values as values
* @param array $headers Associative array with header field names as
* (string) keys and lists of header field values (string[]) as values.
* @param StreamInterface $body A stream representation of the message
* entity body
*/
@ -61,8 +60,6 @@ abstract class Message implements MessageInterface
/**
* Retrieves the HTTP protocol version as a string.
*
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
*
* @return string HTTP protocol version.
*/
public function getProtocolVersion()
@ -73,9 +70,6 @@ abstract class Message implements MessageInterface
/**
* Create a new instance with the specified HTTP protocol version.
*
* The version string MUST contain only the HTTP version number (e.g.,
* "1.1", "1.0").
*
* @param string $version HTTP protocol version
* @return static
*/
@ -94,7 +88,7 @@ abstract class Message implements MessageInterface
*
* // Represent the headers as a string
* foreach ($message->getHeaders() as $name => $values) {
* echo $name . ": " . implode(", ", $values);
* echo $name . ': ' . implode(', ', $values);
* }
*
* // Emit headers iteratively:
@ -177,9 +171,9 @@ abstract class Message implements MessageInterface
public function getHeaderLine($name)
{
if (isset($this->headers[$name])) {
return join(", ", $this->headers[$name]);
return join(', ', $this->headers[$name]);
} else {
return "";
return '';
}
}
@ -278,7 +272,7 @@ abstract class Message implements MessageInterface
};
if (!is_string($name)) {
throw new \InvalidArgumentException("Header name must be a string");
throw new \InvalidArgumentException('Header name must be a string');
}
if ($is_allowed($value)) {
@ -286,7 +280,7 @@ abstract class Message implements MessageInterface
} elseif (is_array($value) && count($value) === count(array_filter($value, $is_allowed))) {
return $value;
} else {
throw new \InvalidArgumentException("Header values must be a string or string[]");
throw new \InvalidArgumentException('Header values must be a string or string[]');
}
}
}

View File

@ -2,32 +2,45 @@
namespace WellRESTed\Test\Unit\Message;
use WellRESTed\Message\Message;
use WellRESTed\Message\Response;
use WellRESTed\Message\Stream;
use WellRESTed\Test\TestCase;
class MessageTest extends TestCase
{
/** @var Message */
private $message;
public function setUp()
{
$this->message = new Response();
}
public function testSetsHeadersOnConstruction()
{
$headers = ["X-foo" => ["bar", "baz"]];
$body = null;
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message', [$headers, $body]);
$this->assertEquals(["bar", "baz"], $message->getHeader("X-foo"));
$headers = ['X-foo' => ['bar', 'baz']];
$message = new Response(200, $headers);
$this->assertEquals(['bar', 'baz'], $message->getHeader('X-foo'));
}
public function testSetsBodyOnConstruction()
{
$headers = null;
$body = $this->prophesize('\Psr\Http\Message\StreamInterface');
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message', [$headers, $body->reveal()]);
$this->assertSame($body->reveal(), $message->getBody());
$body = new Stream('Hello, world');
$message = new Response(200, [], $body);
$this->assertSame($body, $message->getBody());
}
public function testCloneMakesDeepCopyOfHeaders()
{
$message1 = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message1 = $message1->withHeader("Content-type", "text/plain");
$message2 = $message1->withHeader("Content-type", "application/json");
$this->assertNotEquals($message1->getHeader("Content-type"), $message2->getHeader("Content-type"));
$message1 = (new Response())
->withHeader('Content-type', 'text/plain');
$message2 = $message1
->withHeader('Content-type', 'application/json');
$this->assertNotEquals(
$message1->getHeader('Content-type'),
$message2->getHeader('Content-type'));
}
// ------------------------------------------------------------------------
@ -35,22 +48,22 @@ class MessageTest extends TestCase
public function testGetProtocolVersionReturnsProtocolVersion1Point1ByDefault()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$this->assertEquals("1.1", $message->getProtocolVersion());
$message = new Response();
$this->assertEquals('1.1', $message->getProtocolVersion());
}
public function testGetProtocolVersionReturnsProtocolVersion()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withProtocolVersion("1.0");
$this->assertEquals("1.0", $message->getProtocolVersion());
$message = (new Response())
->withProtocolVersion('1.0');
$this->assertEquals('1.0', $message->getProtocolVersion());
}
public function testGetProtocolVersionReplacesProtocolVersion()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withProtocolVersion("1.0");
$this->assertEquals("1.0", $message->getProtocolVersion());
$message = (new Response())
->withProtocolVersion('1.0');
$this->assertEquals('1.0', $message->getProtocolVersion());
}
// ------------------------------------------------------------------------
@ -59,17 +72,17 @@ class MessageTest extends TestCase
/** @dataProvider validHeaderValueProvider */
public function testWithHeaderReplacesHeader($expected, $value)
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withHeader("X-foo", "Original value");
$message = $message->withHeader("X-foo", $value);
$this->assertEquals($expected, $message->getHeader("X-foo"));
$message = (new Response())
->withHeader('X-foo', 'Original value')
->withHeader('X-foo', $value);
$this->assertEquals($expected, $message->getHeader('X-foo'));
}
public function validHeaderValueProvider()
{
return [
[["0"], 0],
[["molly","bear"],["molly","bear"]]
[['0'], 0],
[['molly','bear'],['molly','bear']]
];
}
@ -79,114 +92,118 @@ class MessageTest extends TestCase
*/
public function testWithHeaderThrowsExceptionWithInvalidArgument($name, $value)
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message->withHeader($name, $value);
$message = (new Response())
->withHeader($name, $value);
}
public function invalidHeaderProvider()
{
return [
[0, 1024],
["Content-length", false],
["Content-length", [false]]
['Content-length', false],
['Content-length', [false]]
];
}
public function testWithAddedHeaderSetsHeader()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withAddedHeader("Content-type", "application/json");
$this->assertEquals(["application/json"], $message->getHeader("Content-type"));
$message = (new Response())
->withAddedHeader('Content-type', 'application/json');
$this->assertEquals(['application/json'], $message->getHeader('Content-type'));
}
public function testWithAddedHeaderAppendsValue()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withAddedHeader("Set-Cookie", ["cat=Molly"]);
$message = $message->withAddedHeader("Set-Cookie", ["dog=Bear"]);
$cookies = $message->getHeader("Set-Cookie");
$this->assertTrue(in_array("cat=Molly", $cookies) && in_array("dog=Bear", $cookies));
$message = (new Response())
->withAddedHeader('Set-Cookie', ['cat=Molly'])
->withAddedHeader('Set-Cookie', ['dog=Bear']);
$cookies = $message->getHeader('Set-Cookie');
$this->assertTrue(
in_array('cat=Molly', $cookies) &&
in_array('dog=Bear', $cookies));
}
public function testWithoutHeaderRemovesHeader()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withHeader("Content-type", "application/json");
$message = $message->withoutHeader("Content-type");
$this->assertFalse($message->hasHeader("Content-type"));
$message = (new Response())
->withHeader('Content-type', 'application/json')
->withoutHeader('Content-type');
$this->assertFalse($message->hasHeader('Content-type'));
}
public function testGetHeaderReturnsEmptyArrayForUnsetHeader()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$this->assertEquals([], $message->getHeader("X-name"));
$message = new Response();
$this->assertEquals([], $message->getHeader('X-name'));
}
public function testGetHeaderReturnsSingleHeader()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withAddedHeader("Content-type", "application/json");
$this->assertEquals(["application/json"], $message->getHeader("Content-type"));
$message = (new Response())
->withAddedHeader('Content-type', 'application/json');
$this->assertEquals(['application/json'], $message->getHeader('Content-type'));
}
public function testGetHeaderReturnsMultipleValuesForHeader()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withAddedHeader("X-name", "cat=Molly");
$message = $message->withAddedHeader("X-name", "dog=Bear");
$this->assertEquals(["cat=Molly", "dog=Bear"], $message->getHeader("X-name"));
$message = (new Response())
->withAddedHeader('X-name', 'cat=Molly')
->withAddedHeader('X-name', 'dog=Bear');
$this->assertEquals(['cat=Molly', 'dog=Bear'], $message->getHeader('X-name'));
}
public function testGetHeaderLineReturnsEmptyStringForUnsetHeader()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$this->assertSame("", $message->getHeaderLine("X-not-set"));
$message = new Response();
$this->assertSame('', $message->getHeaderLine('X-not-set'));
}
public function testGetHeaderLineReturnsMultipleHeadersJoinedByCommas()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withAddedHeader("X-name", "cat=Molly");
$message = $message->withAddedHeader("X-name", "dog=Bear");
$this->assertEquals("cat=Molly, dog=Bear", $message->getHeaderLine("X-name"));
$message = (new Response())
->withAddedHeader('X-name', 'cat=Molly')
->withAddedHeader('X-name', 'dog=Bear');
$this->assertEquals('cat=Molly, dog=Bear', $message->getHeaderLine('X-name'));
}
public function testHasHeaderReturnsTrueWhenHeaderIsSet()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withHeader("Content-type", "application/json");
$this->assertTrue($message->hasHeader("Content-type"));
$message = (new Response())
->withHeader('Content-type', 'application/json');
$this->assertTrue($message->hasHeader('Content-type'));
}
public function testHasHeaderReturnsFalseWhenHeaderIsNotSet()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$this->assertFalse($message->hasHeader("Content-type"));
$message = new Response();
$this->assertFalse($message->hasHeader('Content-type'));
}
public function testGetHeadersReturnOriginalHeaderNamesAsKeys()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withHeader("Set-Cookie", "cat=Molly");
$message = $message->withAddedHeader("Set-Cookie", "dog=Bear");
$message = $message->withHeader("Content-type", "application/json");
$message = (new Response())
->withHeader('Set-Cookie', 'cat=Molly')
->withAddedHeader('Set-Cookie', 'dog=Bear')
->withHeader('Content-type', 'application/json');
$headers = [];
foreach ($message->getHeaders() as $key => $values) {
$headers[] = $key;
}
$expected = ["Content-type", "Set-Cookie"];
$countUnmatched = count(array_diff($expected, $headers)) + count(array_diff($headers, $expected));
$expected = ['Content-type', 'Set-Cookie'];
$countUnmatched
= count(array_diff($expected, $headers))
+ count(array_diff($headers, $expected));
$this->assertEquals(0, $countUnmatched);
}
public function testGetHeadersReturnOriginalHeaderNamesAndValues()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withHeader("Set-Cookie", "cat=Molly");
$message = $message->withAddedHeader("Set-Cookie", "dog=Bear");
$message = $message->withHeader("Content-type", "application/json");
$message = (new Response())
->withHeader('Set-Cookie', 'cat=Molly')
->withAddedHeader('Set-Cookie', 'dog=Bear')
->withHeader('Content-type', 'application/json');
$headers = [];
@ -201,8 +218,8 @@ class MessageTest extends TestCase
}
$expected = [
"Set-Cookie" => ["cat=Molly", "dog=Bear"],
"Content-type" => ["application/json"]
'Set-Cookie' => ['cat=Molly', 'dog=Bear'],
'Content-type' => ['application/json']
];
$this->assertEquals($expected, $headers);
@ -213,17 +230,16 @@ class MessageTest extends TestCase
public function testGetBodyReturnsEmptyStreamByDefault()
{
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$this->assertEquals("", (string) $message->getBody());
$message = new Response();
$this->assertEquals('', (string) $message->getBody());
}
public function testGetBodyReturnsAttachedStream()
{
$stream = $this->prophesize('\Psr\Http\Message\StreamInterface');
$stream = $stream->reveal();
$stream = new Stream('Hello, world!');
$message = $this->getMockForAbstractClass('\WellRESTed\Message\Message');
$message = $message->withBody($stream);
$message = (new Response())
->withBody($stream);
$this->assertSame($stream, $message->getBody());
}
}

View File

@ -2,6 +2,7 @@
namespace WellRESTed\Test\Unit\Message;
use Psr\Http\Message\StreamInterface;
use WellRESTed\Message\UploadedFile;
use WellRESTed\Message\UploadedFileState;
use WellRESTed\Test\TestCase;
@ -39,7 +40,7 @@ class UploadedFileTest extends TestCase
public function testGetStreamReturnsStreamInterface()
{
$file = new UploadedFile("", "", 0, "", 0);
$this->assertInstanceOf('\Psr\Http\Message\StreamInterface', $file->getStream());
$this->assertInstanceOf(StreamInterface::class, $file->getStream());
}
public function testGetStreamReturnsStreamWrappingUploadedFile()