engine = self::$container->get(\Twig\Environment::class);
}
private function buildController(): WebdavController
{
$storedObjectManager = new MockedStoredObjectManager();
return new WebdavController($this->engine, $storedObjectManager);
}
private function buildDocument(): StoredObject
{
$object = (new StoredObject())
->setType('application/vnd.oasis.opendocument.text');
$reflectionObject = new \ReflectionClass($object);
$reflectionObjectUuid = $reflectionObject->getProperty('uuid');
$reflectionObjectUuid->setValue($object, Uuid::fromString('716e6688-4579-4938-acf3-c4ab5856803b'));
return $object;
}
public function testGet(): void
{
$controller = $this->buildController();
$response = $controller->getDocument($this->buildDocument());
self::assertEquals(200, $response->getStatusCode());
self::assertEquals('abcde', $response->getContent());
self::assertContains('etag', $response->headers->keys());
self::assertStringContainsString('ab56b4', $response->headers->get('etag'));
}
public function testOptionsOnDocument(): void
{
$controller = $this->buildController();
$response = $controller->optionsDocument($this->buildDocument());
self::assertEquals(200, $response->getStatusCode());
self::assertContains('allow', $response->headers->keys());
foreach (explode(',', 'OPTIONS,GET,HEAD,POST,DELETE,TRACE,PROPFIND,PROPPATCH,COPY,MOVE,PUT') as $method) {
self::assertStringContainsString($method, $response->headers->get('allow'));
}
self::assertContains('dav', $response->headers->keys());
self::assertStringContainsString('1', $response->headers->get('dav'));
}
public function testOptionsOnDirectory(): void
{
$controller = $this->buildController();
$response = $controller->optionsDirectory($this->buildDocument());
self::assertEquals(200, $response->getStatusCode());
self::assertContains('allow', $response->headers->keys());
foreach (explode(',', 'OPTIONS,GET,HEAD,POST,DELETE,TRACE,PROPFIND,PROPPATCH,COPY,MOVE,PUT') as $method) {
self::assertStringContainsString($method, $response->headers->get('allow'));
}
self::assertContains('dav', $response->headers->keys());
self::assertStringContainsString('1', $response->headers->get('dav'));
}
/**
* @dataProvider generateDataPropfindDocument
*/
public function testPropfindDocument(string $requestContent, int $expectedStatusCode, string $expectedXmlResponse, string $message): void
{
$controller = $this->buildController();
$request = new Request([], [], [], [], [], [], $requestContent);
$request->setMethod('PROPFIND');
$response = $controller->propfindDocument($this->buildDocument(), $request);
self::assertEquals($expectedStatusCode, $response->getStatusCode());
self::assertContains('content-type', $response->headers->keys());
self::assertStringContainsString('text/xml', $response->headers->get('content-type'));
self::assertTrue((new \DOMDocument())->loadXML($response->getContent()), $message . " test that the xml response is a valid xml");
self::assertXmlStringEqualsXmlString($expectedXmlResponse, $response->getContent(), $message);
}
/**
* @dataProvider generateDataPropfindDirectory
*/
public function testPropfindDirectory(string $requestContent, int $expectedStatusCode, string $expectedXmlResponse, string $message): void
{
$controller = $this->buildController();
$request = new Request([], [], [], [], [], [], $requestContent);
$request->setMethod('PROPFIND');
$request->headers->add(["Depth" => "0"]);
$response = $controller->propfindDirectory($this->buildDocument(), $request);
self::assertEquals($expectedStatusCode, $response->getStatusCode());
self::assertContains('content-type', $response->headers->keys());
self::assertStringContainsString('text/xml', $response->headers->get('content-type'));
self::assertTrue((new \DOMDocument())->loadXML($response->getContent()), $message . " test that the xml response is a valid xml");
self::assertXmlStringEqualsXmlString($expectedXmlResponse, $response->getContent(), $message);
}
public function testHeadDocument(): void
{
$controller = $this->buildController();
$response = $controller->headDocument($this->buildDocument());
self::assertEquals(200, $response->getStatusCode());
self::assertContains('content-length', $response->headers->keys());
self::assertContains('content-type', $response->headers->keys());
self::assertContains('etag', $response->headers->keys());
self::assertEquals('ab56b4d92b40713acc5af89985d4b786', $response->headers->get('etag'));
self::assertEquals('application/vnd.oasis.opendocument.text', $response->headers->get('content-type'));
self::assertEquals(5, $response->headers->get('content-length'));
}
public static function generateDataPropfindDocument(): iterable
{
$content =
<<<'XML'
XML;
$response =
<<<'XML'
/dav/get/716e6688-4579-4938-acf3-c4ab5856803b/d
application/vnd.oasis.opendocument.text
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found
XML;
yield [$content, 207, $response, "get IsReadOnly and contenttype from server"];
$content =
<<<'XML'
XML;
$response =
<<<'XML'
/dav/get/716e6688-4579-4938-acf3-c4ab5856803b/d
HTTP/1.1 404 Not Found
XML;
yield [$content, 207, $response, "get property IsReadOnly"];
yield [
<<<'XML'
XML,
207,
<<<'XML'
/dav/get/716e6688-4579-4938-acf3-c4ab5856803b/d
HTTP/1.1 404 Not Found
XML,
"Test requesting an unknow property"
];
yield [
<<<'XML'
XML,
207,
<<<'XML'
/dav/get/716e6688-4579-4938-acf3-c4ab5856803b/d
Wed, 13 Sep 2023 14:15:00 +0200
HTTP/1.1 200 OK
XML,
"test getting the last modified date"
];
yield [
<<<'XML'
XML,
207,
<<<'XML'
/dav/get/716e6688-4579-4938-acf3-c4ab5856803b/d
Wed, 13 Sep 2023 14:15:00 +0200
5
"ab56b4d92b40713acc5af89985d4b786"
application/vnd.oasis.opendocument.text
HTTP/1.1 200 OK
XML,
"test finding all properties"
];
}
public static function generateDataPropfindDirectory(): iterable
{
yield [
<<<'XML'
XML,
207,
<<<'XML'
/dav/get/716e6688-4579-4938-acf3-c4ab5856803b/
httpd/unix-directory
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found
XML,
"test resourceType and IsReadOnly "
];
yield [
<<<'XML'
XML,
207,
<<<'XML'
/dav/get/716e6688-4579-4938-acf3-c4ab5856803b/
HTTP/1.1 404 Not Found
XML,
"test creatableContentsInfo"
];
}
}
class MockedStoredObjectManager implements StoredObjectManagerInterface
{
public function getLastModified(StoredObject $document): DateTimeInterface
{
return new \DateTimeImmutable('2023-09-13T14:15');
}
public function getContentLength(StoredObject $document): int
{
return 5;
}
public function read(StoredObject $document): string
{
return 'abcde';
}
public function write(StoredObject $document, string $clearContent): void {}
public function etag(StoredObject $document): string
{
return 'ab56b4d92b40713acc5af89985d4b786';
}
}