From d0deeea42ae51f4fe2fa68a9cbf06e04fbfd2869 Mon Sep 17 00:00:00 2001 From: AaronGilMartinez Date: Wed, 8 Jan 2025 08:40:55 +0100 Subject: [PATCH] Add test for ViewerController. --- .../Controller/ViewerControllerTest.php | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 tests/src/Kernel/Controller/ViewerControllerTest.php diff --git a/tests/src/Kernel/Controller/ViewerControllerTest.php b/tests/src/Kernel/Controller/ViewerControllerTest.php new file mode 100644 index 00000000..fed27f48 --- /dev/null +++ b/tests/src/Kernel/Controller/ViewerControllerTest.php @@ -0,0 +1,221 @@ +createMock(CollaboraDiscoveryFetcherInterface::class); + $file = dirname(__DIR__, 3) . '/fixtures/discovery.mimetypes.xml'; + $xml = file_get_contents($file); + $fetcher->method('getDiscoveryXml')->willReturn($xml); + $this->container->set(CollaboraDiscoveryFetcherInterface::class, $fetcher); + + $this->user = $this->createUser([ + 'access content', + 'preview document in collabora', + 'edit any document in collabora', + ]); + + $this->setCurrentUser($this->user); + } + + /** + * Tests successful requests. + * + * @covers ::editor + */ + public function testEditorSuccess(): void { + foreach ($this->createViewerRequests() as $name => $request) { + $this->assertResponseOk($request, $name); + } + } + + /** + * Tests requests with Collabora unavailable. + * + * @covers ::editor + */ + public function testEditorCollaboraUnavailable(): void { + // Restore service to force fail. + $fetcher = $this->createMock(CollaboraDiscoveryFetcherInterface::class); + $this->container->set(CollaboraDiscoveryFetcherInterface::class, $fetcher); + + foreach ($this->createViewerRequests() as $name => $request) { + $this->assertBadRequestResponse( + 'The Collabora Online editor/viewer is not available.', + $request, + [ + 'message' => "Collabora Online is not available.
\n" . Error::DEFAULT_ERROR_MESSAGE, + 'level' => RfcLogLevel::WARNING, + ], + $name + ); + } + } + + /** + * Tests requests with a scheme that does not match the Collabora client URL. + * + * @covers ::editor + */ + public function testEditorMismatchScheme(): void { + $wopi_url = \Drupal::service(CollaboraDiscoveryInterface::class)->getWopiClientURL(); + + foreach ($this->createViewerRequests(TRUE) as $name => $request) { + $this->assertBadRequestResponse( + 'Viewer error: Protocol mismatch.', + $request, + [ + 'message' => "The current request uses 'https' url scheme, but the Collabora client url is '$wopi_url'.", + 'level' => RfcLogLevel::ERROR, + ], + $name + ); + } + } + + /** + * Tests requests with a viewer not available. + * + * @covers ::editor + */ + public function testEditorNoViewer(): void { + // Mock transcoder to force fail. + $transcoder = $this->createMock(jwtTranscoderInterface::class); + $transcoder->method('encode')->willThrowException(new CollaboraNotAvailableException()); + $this->container->set(jwtTranscoderInterface::class, $transcoder); + + foreach ($this->createViewerRequests() as $name => $request) { + $this->assertBadRequestResponse( + 'The Collabora Online editor/viewer is not available.', + $request, + [ + 'message' => "Cannot show the viewer/editor.
\n" . Error::DEFAULT_ERROR_MESSAGE, + 'level' => RfcLogLevel::WARNING, + ], + $name + ); + } + } + + /** + * Creates requests for different routes, with some shared parameters. + * + * @param bool $https + * If the requests are secure. + * + * @return array + * Requests keyed by a distinguishable name. + */ + protected function createViewerRequests($https = FALSE): array { + return [ + 'view' => $this->createViewerRequest('view', $https), + 'edit' => $this->createViewerRequest('edit', $https), + ]; + } + + /** + * Creates a view/edit request. + * + * @param string $action + * View or edit the media. + * @param bool $https + * If the request is secure. + * + * @return \Symfony\Component\HttpFoundation\Request + * The request. + */ + protected function createViewerRequest(string $action, bool $https): Request { + $url = Url::fromRoute( + "collabora-online.$action", + [ + 'media' => $this->media->id(), + ], + [ + 'https' => $https, + 'absolute' => TRUE, + ] + ); + + return Request::create($url->toString()); + } + + /** + * Asserts an successful response given a request. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request to perform. + * @param string $message + * Message to distinguish this from other assertions. + */ + protected function assertResponseOk(Request $request, string $message = ''): void { + $response = $this->handleRequest($request); + + $this->assertEquals(Response::HTTP_OK, $response->getStatusCode(), $message); + $this->assertStringContainsString('iframe', $response->getContent(), $message); + $this->assertEquals('', $response->headers->get('Content-Type'), $message); + } + + /** + * Asserts an bad request response given a request. + * + * @param string $expected_content + * The expected content. + * @param \Symfony\Component\HttpFoundation\Request $request + * The request to perform. + * @param array $expected_log + * The expected log entry. + * @param string $message + * Message to distinguish this from other assertions. + */ + protected function assertBadRequestResponse(string $expected_content, Request $request, array $expected_log = [], string $message = ''): void { + $this->assertResponse( + Response::HTTP_BAD_REQUEST, + $expected_content, + 'text/plain', + $request, + $message, + ); + + if ($expected_log) { + $this->assertTrue( + $this->logger->hasRecord($expected_log['message'], $expected_log['level'] ?? NULL), + sprintf('The logger does not contain a record like: "%s".', $expected_log['message']) + ); + $this->logger->reset(); + } + } + +}