clearData(false); } public function assertConsole(CLI $cli, string $command, int $exitStatus, string $output = "", bool $pattern = false) { $argv = \Clue\Arguments\split($command); $output = strlen($output) ? $output.\PHP_EOL : ""; if ($pattern) { $this->expectOutputRegex($output); } else { $this->expectOutputString($output); } $this->assertSame($exitStatus, $cli->dispatch($argv)); } public function assertLoaded(bool $loaded) { $r = new \ReflectionClass(Arsse::class); $props = array_keys($r->getStaticProperties()); foreach ($props as $prop) { if ($loaded) { $this->assertNotNull(Arsse::$$prop, "Global $prop object should be loaded"); } else { $this->assertNull(Arsse::$$prop, "Global $prop object should not be loaded"); } } } public function testPrintVersion() { $this->assertConsole(new CLI, "arsse.php --version", 0, Arsse::VERSION); $this->assertLoaded(false); } /** @dataProvider provideHelpText */ public function testPrintHelp(string $cmd, string $name) { $this->assertConsole(new CLI, $cmd, 0, str_replace("arsse.php", $name, CLI::USAGE)); $this->assertLoaded(false); } public function provideHelpText() { return [ ["arsse.php --help", "arsse.php"], ["arsse --help", "arsse"], ["thearsse --help", "thearsse"], ]; } public function testStartTheDaemon() { $srv = Phake::mock(Service::class); $cli = Phake::partialMock(CLI::class); Phake::when($srv)->watch->thenReturn(new \DateTimeImmutable); Phake::when($cli)->getService->thenReturn($srv); $this->assertConsole($cli, "arsse.php daemon", 0); $this->assertLoaded(true); Phake::verify($srv)->watch(true); Phake::verify($cli)->getService; } /** @dataProvider provideFeedUpdates */ public function testRefreshAFeed(string $cmd, int $exitStatus, string $output) { Arsse::$db = Phake::mock(Database::class); Phake::when(Arsse::$db)->feedUpdate(1, true)->thenReturn(true); Phake::when(Arsse::$db)->feedUpdate(2, true)->thenThrow(new \JKingWeb\Arsse\Feed\Exception("http://example.com/", new \PicoFeed\Client\InvalidUrlException)); $this->assertConsole(new CLI, $cmd, $exitStatus, $output); $this->assertLoaded(true); Phake::verify(Arsse::$db)->feedUpdate; } public function provideFeedUpdates() { return [ ["arsse.php feed refresh 1", 0, ""], ["arsse.php feed refresh 2", 10502, ""], ]; } /** @dataProvider provideDefaultConfigurationSaves */ public function testSaveTheDefaultConfiguration(string $cmd, int $exitStatus, string $file) { $conf = Phake::mock(Conf::class); $cli = Phake::partialMock(CLI::class); Phake::when($conf)->exportFile("php://output", true)->thenReturn(true); Phake::when($conf)->exportFile("good.conf", true)->thenReturn(true); Phake::when($conf)->exportFile("bad.conf", true)->thenThrow(new \JKingWeb\Arsse\Conf\Exception("fileUnwritable")); Phake::when($cli)->getConf->thenReturn($conf); $this->assertConsole($cli, $cmd, $exitStatus); $this->assertLoaded(false); Phake::verify($conf)->exportFile($file, true); } public function provideDefaultConfigurationSaves() { return [ ["arsse.php conf save-defaults", 0, "php://output"], ["arsse.php conf save-defaults -", 0, "php://output"], ["arsse.php conf save-defaults good.conf", 0, "good.conf"], ["arsse.php conf save-defaults bad.conf", 10304, "bad.conf"], ]; } /** @dataProvider provideUserList */ public function testListUsers(string $cmd, array $list, int $exitStatus, string $output) { Arsse::$user = Phake::mock(User::class); Phake::when(Arsse::$user)->list()->thenReturn($list); $this->assertConsole(new CLI, $cmd, $exitStatus, $output); $this->assertLoaded(true); Phake::verify(Arsse::$user)->list; } public function provideUserList() { return []; $list = ["john.doe@example.com", "jane.doe@example.com"]; $str = implode(PHP_EOL, $list); return [ ["arsse.php user list", $list, 0, $str], ["arsse.php user", $list, 0, $str], ["arsse.php user list", [], 0, ""], ["arsse.php user", [], 0, ""], ]; } }