diff --git a/module/Application/src/Application/Service/RepositoryRetriever.php b/module/Application/src/Application/Service/RepositoryRetriever.php index e05f2214..cf5c051c 100644 --- a/module/Application/src/Application/Service/RepositoryRetriever.php +++ b/module/Application/src/Application/Service/RepositoryRetriever.php @@ -46,11 +46,15 @@ public function getUserRepositoryMetadata($user, $module) * @param string $user * @param array $params * - * @return RepositoryCollection + * @return RepositoryCollection|bool */ public function getUserRepositories($user, $params = []) { - return $this->githubClient->api('user')->repos($user, $params); + try { + return $this->githubClient->api('user')->repos($user, $params); + } catch (RuntimeException $e) { + return false; + } } /** @@ -140,10 +144,14 @@ public function getRepositoryFileMetadata($user, $module, $filePath) * * @param array $params * - * @return RepositoryCollection + * @return RepositoryCollection|bool */ public function getAuthenticatedUserRepositories($params = []) { - return $this->githubClient->api('current_user')->repos($params); + try { + return $this->githubClient->api('current_user')->repos($params); + } catch (RuntimeException $e) { + return false; + } } } diff --git a/module/Application/test/ApplicationTest/Service/RepositoryRetrieverTest.php b/module/Application/test/ApplicationTest/Service/RepositoryRetrieverTest.php index ffea5f22..b751d89c 100644 --- a/module/Application/test/ApplicationTest/Service/RepositoryRetrieverTest.php +++ b/module/Application/test/ApplicationTest/Service/RepositoryRetrieverTest.php @@ -45,6 +45,22 @@ public function testCanRetrieveUserRepositories() $this->assertEquals(count($payload), $count); } + public function testGetUserRepositoriesReturnsFalseOnRemoteFailure() + { + $client = $this->getClientMock( + new Api\User(), + [] + ); + $client->expects($this->any()) + ->method('api') + ->willThrowException(new Exception\RuntimeException()); + + $service = new RepositoryRetriever($client); + + $repositories = $service->getUserRepositories('foo'); + $this->assertFalse($repositories); + } + public function testCanRetrieveUserRepositoryMetadata() { $payload = [ @@ -202,6 +218,22 @@ public function testCanRetrieveAuthenticatedUserRepositories() $this->assertEquals(count($payload), $count); } + public function testGetAuthenticatedUserRepositoriesReturnsFalseOnRemoteFailure() + { + $client = $this->getClientMock( + new Api\CurrentUser(), + [] + ); + $client->expects($this->any()) + ->method('api') + ->willThrowException(new Exception\RuntimeException()); + + $service = new RepositoryRetriever($client); + + $repositories = $service->getAuthenticatedUserRepositories(); + $this->assertFalse($repositories); + } + public function testRepositoryFileContentFails() { $clientMock = $this->getMock('EdpGithub\Client'); diff --git a/module/User/view/user/helper/user-organizations.phtml b/module/User/view/user/helper/user-organizations.phtml index 81399a04..18e1f14a 100644 --- a/module/User/view/user/helper/user-organizations.phtml +++ b/module/User/view/user/helper/user-organizations.phtml @@ -26,12 +26,18 @@ inlineScript()->appendScript(sprintf($jsTemplate, $org->login, $org->login, $this->url('zf-module/list', ['owner' => $org->login]))); + $this->inlineScript()->appendScript(sprintf($jsTemplate, $org->login, $this->url('zf-module/list', ['owner' => $org->login]))); ?> diff --git a/module/User/view/zfc-user/user/index.phtml b/module/User/view/zfc-user/user/index.phtml index 8c4bd425..133ff505 100644 --- a/module/User/view/zfc-user/user/index.phtml +++ b/module/User/view/zfc-user/user/index.phtml @@ -48,4 +48,13 @@ -inlineScript()->appendScript('$("#repositories").load("' . $this->escapeJs($this->url('zf-module')) . '");'); ?> +inlineScript()->appendScript(<<escapeJs($this->url('zf-module'))}", + }).done(function(data) { + $('#repositories').html(data); + }).fail(function(xhr) { + $('#repositories').html(xhr.responseText); + }); +EOB +); diff --git a/module/ZfModule/src/ZfModule/Controller/ModuleController.php b/module/ZfModule/src/ZfModule/Controller/ModuleController.php index d62e0931..b84cb12e 100644 --- a/module/ZfModule/src/ZfModule/Controller/ModuleController.php +++ b/module/ZfModule/src/ZfModule/Controller/ModuleController.php @@ -83,17 +83,24 @@ public function indexAction() return $this->redirect()->toRoute('zfcuser/login'); } + $viewModel = new ViewModel(); + $viewModel->setTerminal(true); + $currentUserRepositories = $this->repositoryRetriever->getAuthenticatedUserRepositories([ 'type' => 'all', 'per_page' => 100, 'sort' => 'updated', 'direction' => 'desc', ]); + if ($currentUserRepositories === false) { + $this->getResponse()->setStatusCode(503); + $viewModel->setVariable('errorMessage', 'module_fetch_failed'); - $repositories = $this->unregisteredRepositories($currentUserRepositories); + return $viewModel; + } - $viewModel = new ViewModel(['repositories' => $repositories]); - $viewModel->setTerminal(true); + $repositories = $this->unregisteredRepositories($currentUserRepositories); + $viewModel->setVariable('repositories', $repositories); return $viewModel; } @@ -106,17 +113,24 @@ public function listAction() $owner = $this->params()->fromRoute('owner', null); + $viewModel = new ViewModel(); + $viewModel->setTerminal(true); + $viewModel->setTemplate('zf-module/module/index.phtml'); + $userRepositories = $this->repositoryRetriever->getUserRepositories($owner, [ 'per_page' => 100, 'sort' => 'updated', 'direction' => 'desc', ]); + if ($userRepositories === false) { + $this->getResponse()->setStatusCode(503); + $viewModel->setVariable('errorMessage', 'module_fetch_failed'); - $repositories = $this->unregisteredRepositories($userRepositories); + return $viewModel; + } - $viewModel = new ViewModel(['repositories' => $repositories]); - $viewModel->setTerminal(true); - $viewModel->setTemplate('zf-module/module/index.phtml'); + $repositories = $this->unregisteredRepositories($userRepositories); + $viewModel->setVariable('repositories', $repositories); return $viewModel; } diff --git a/module/ZfModule/test/ZfModuleTest/Integration/Controller/ModuleControllerTest.php b/module/ZfModule/test/ZfModuleTest/Integration/Controller/ModuleControllerTest.php index b5e53be2..307f7bed 100644 --- a/module/ZfModule/test/ZfModuleTest/Integration/Controller/ModuleControllerTest.php +++ b/module/ZfModule/test/ZfModuleTest/Integration/Controller/ModuleControllerTest.php @@ -174,6 +174,46 @@ public function testIndexActionRendersUnregisteredModulesOnly() $this->assertSame($unregisteredModule, $viewVariable[0]); } + public function testIndexActionRendersErrorMessageWhenModuleFetchReturnsFalse() + { + $this->authenticatedAs(new User()); + + $repositoryRetriever = $this->getMockBuilder(RepositoryRetriever::class) + ->disableOriginalConstructor() + ->getMock() + ; + + $repositoryRetriever + ->expects($this->once()) + ->method('getAuthenticatedUserRepositories') + ->willReturn(false) + ; + + $this->getApplicationServiceLocator() + ->setAllowOverride(true) + ->setService( + RepositoryRetriever::class, + $repositoryRetriever + ) + ; + + $this->dispatch('/module'); + + $this->assertMatchedRouteName('zf-module'); + + $this->assertControllerName(Controller\ModuleController::class); + $this->assertActionName('index'); + $this->assertResponseStatusCode(Http\Response::STATUS_CODE_503); + + $viewModel = $this->getApplication()->getMvcEvent()->getViewModel(); + + $this->assertTrue($viewModel->terminate()); + $this->assertSame('zf-module/module/index', $viewModel->getTemplate()); + + $this->assertEquals(null, $viewModel->getVariable('repositories')); + $this->assertEquals('module_fetch_failed', $viewModel->getVariable('errorMessage')); + } + public function testListActionRedirectsIfNotAuthenticated() { $this->notAuthenticated(); @@ -440,6 +480,53 @@ public function testListActionRendersUnregisteredModulesOnly() $this->assertSame($unregisteredModule, $viewVariable[0]); } + public function testListActionRendersErrorMessageWhenModuleFetchReturnsFalse() + { + $this->authenticatedAs(new User()); + + $repositoryRetriever = $this->getMockBuilder(RepositoryRetriever::class) + ->disableOriginalConstructor() + ->getMock() + ; + + $vendor = 'suzie'; + + $repositoryRetriever + ->expects($this->once()) + ->method('getUserRepositories') + ->willReturn(false) + ; + + $this->getApplicationServiceLocator() + ->setAllowOverride(true) + ->setService( + RepositoryRetriever::class, + $repositoryRetriever + ) + ; + + $url = sprintf( + '/module/list/%s', + $vendor + ); + + $this->dispatch($url); + + $this->assertMatchedRouteName('zf-module/list'); + + $this->assertControllerName(Controller\ModuleController::class); + $this->assertActionName('list'); + $this->assertResponseStatusCode(Http\Response::STATUS_CODE_503); + + $viewModel = $this->getApplication()->getMvcEvent()->getViewModel(); + + $this->assertTrue($viewModel->terminate()); + $this->assertSame('zf-module/module/index.phtml', $viewModel->getTemplate()); + + $this->assertEquals(null, $viewModel->getVariable('repositories')); + $this->assertEquals('module_fetch_failed', $viewModel->getVariable('errorMessage')); + } + public function testAddActionRedirectsIfNotAuthenticated() { $this->notAuthenticated(); diff --git a/module/ZfModule/view/zf-module/module/index.phtml b/module/ZfModule/view/zf-module/module/index.phtml index 882333f9..69c68910 100644 --- a/module/ZfModule/view/zf-module/module/index.phtml +++ b/module/ZfModule/view/zf-module/module/index.phtml @@ -1,5 +1,7 @@ - + +
An error occurred while fetching modules
+
No modules found