diff --git a/PHPCI/Command/InstallCommand.php b/PHPCI/Command/InstallCommand.php index e4af4722..a4a0c4bb 100644 --- a/PHPCI/Command/InstallCommand.php +++ b/PHPCI/Command/InstallCommand.php @@ -23,7 +23,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Helper\DialogHelper; use PHPCI\Service\UserService; - /** * Install console command - Installs PHPCI. * @author Dan Cryer @@ -32,10 +31,23 @@ use PHPCI\Service\UserService; */ class InstallCommand extends Command { + protected $configFilePath; + protected function configure() { + $defaultPath = PHPCI_DIR . 'PHPCI/config.yml'; + $this ->setName('phpci:install') + ->addOption('url', null, InputOption::VALUE_OPTIONAL, 'PHPCI Installation URL') + ->addOption('db-host', null, InputOption::VALUE_OPTIONAL, 'Database hostname') + ->addOption('db-name', null, InputOption::VALUE_OPTIONAL, 'Database name') + ->addOption('db-user', null, InputOption::VALUE_OPTIONAL, 'Database username') + ->addOption('db-pass', null, InputOption::VALUE_OPTIONAL, 'Database password') + ->addOption('admin-name', null, InputOption::VALUE_OPTIONAL, 'Admin username') + ->addOption('admin-pass', null, InputOption::VALUE_OPTIONAL, 'Admin password') + ->addOption('admin-mail', null, InputOption::VALUE_OPTIONAL, 'Admin e-mail') + ->addOption('config-path', null, InputOption::VALUE_OPTIONAL, 'Config file path', $defaultPath) ->setDescription('Install PHPCI.'); } @@ -44,6 +56,8 @@ class InstallCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->configFilePath = $input->getOption('config-path'); + $this->verifyNotInstalled($output); $output->writeln(''); @@ -58,60 +72,39 @@ class InstallCommand extends Command $output->writeln('-------------------------------------'); $output->writeln(''); - - /** - * @var \Symfony\Component\Console\Helper\DialogHelper - */ - $dialog = $this->getHelperSet()->get('dialog'); - // ---- // Get MySQL connection information and verify that it works: // ---- $connectionVerified = false; while (!$connectionVerified) { - $db = array(); - $db['servers']['read'] = $dialog->ask($output, 'Please enter your MySQL host [localhost]: ', 'localhost'); - $db['servers']['write'] = $db['servers']['read']; - $db['name'] = $dialog->ask($output, 'Please enter your database name [phpci]: ', 'phpci'); - $db['username'] = $dialog->ask($output, 'Please enter your database username [phpci]: ', 'phpci'); - $db['password'] = $dialog->askHiddenResponse($output, 'Please enter your database password: '); + $db = $this->getDatabaseInformation($input, $output); $connectionVerified = $this->verifyDatabaseDetails($db, $output); } $output->writeln(''); + $conf = array(); + $conf['b8']['database'] = $db; + // ---- // Get basic installation details (URL, etc) // ---- - - $conf = array(); - $conf['b8']['database'] = $db; - $conf['phpci']['url'] = $dialog->askAndValidate( - $output, - 'Your PHPCI URL ("http://phpci.local" for example): ', - function ($answer) { - if (!filter_var($answer, FILTER_VALIDATE_URL)) { - throw new Exception('Must be a valid URL'); - } - - return rtrim($answer, '/'); - }, - false - ); + $conf['phpci'] = $this->getPhpciConfigInformation($input, $output); $this->writeConfigFile($conf); $this->setupDatabase($output); - $this->createAdminUser($output, $dialog); + $admin = $this->getAdminInforamtion($input, $output); + $this->createAdminUser($admin, $output); } /** * Check PHP version, required modules and for disabled functions. + * * @param OutputInterface $output * @throws \Exception */ - protected function checkRequirements(OutputInterface $output) { $output->write('Checking requirements...'); @@ -160,6 +153,127 @@ class InstallCommand extends Command $output->writeln(''); } + /** + * Load information for admin user form CLI options or ask info to user. + * + * @param InputInterface $input + * @param OutputInterface $output + * @return array + */ + protected function getAdminInforamtion(InputInterface $input, OutputInterface $output) + { + $admin = array(); + + /** + * @var \Symfony\Component\Console\Helper\DialogHelper + */ + $dialog = $this->getHelperSet()->get('dialog'); + + // Function to validate mail address. + $mailValidator =function ($answer) { + if (!filter_var($answer, FILTER_VALIDATE_EMAIL)) { + throw new Exception('Must be a valid email address.'); + } + + return $answer; + }; + + if ($adminEmail = $input->getOption('admin-mail')) { + $adminEmail = $mailValidator($adminEmail); + } else { + $adminEmail = $dialog->askAndValidate($output, 'Your email address: ', $mailValidator, false); + } + if (!$adminName = $input->getOption('admin-name')) { + $adminName = $dialog->ask($output, 'Enter your name: '); + } + if (!$adminPass = $input->getOption('admin-pass')) { + $adminPass = $dialog->askHiddenResponse($output, 'Enter your desired admin password: '); + } + + $admin['mail'] = $adminEmail; + $admin['name'] = $adminName; + $admin['pass'] = $adminPass; + + return $admin; + } + + /** + * Load configuration for PHPCI form CLI options or ask info to user. + * + * @param InputInterface $input + * @param OutputInterface $output + * @return array + */ + protected function getPhpciConfigInformation(InputInterface $input, OutputInterface $output) + { + $phpci = array(); + + /** + * @var \Symfony\Component\Console\Helper\DialogHelper + */ + $dialog = $this->getHelperSet()->get('dialog'); + + // FUnction do validate URL. + $urlValidator = function ($answer) { + if (!filter_var($answer, FILTER_VALIDATE_URL)) { + throw new Exception('Must be a valid URL'); + } + + return rtrim($answer, '/'); + }; + + if ($url = $input->getOption('url')) { + $url = $urlValidator($url); + } else { + $url = $dialog->askAndValidate($output, 'Your PHPCI URL ("http://phpci.local" for example): ', $urlValidator, false); + } + + $phpci['url'] = $url; + + return $phpci; + } + + /** + * Load configuration for DB form CLI options or ask info to user. + * + * @param InputInterface $input + * @param OutputInterface $output + * @return array + */ + protected function getDatabaseInformation(InputInterface $input, OutputInterface $output) + { + $db = array(); + + /** + * @var \Symfony\Component\Console\Helper\DialogHelper + */ + $dialog = $this->getHelperSet()->get('dialog'); + + if (!$dbHost = $input->getOption('db-host')) { + $dbHost = $dialog->ask($output, 'Please enter your MySQL host [localhost]: ', 'localhost'); + } + + if (!$dbName = $input->getOption('db-name')) { + $dbName = $dialog->ask($output, 'Please enter your database name [phpci]: ', 'phpci'); + } + + if (!$dbUser = $input->getOption('db-user')) { + $dbUser = $dialog->ask($output, 'Please enter your database username [phpci]: ', 'phpci'); + } + + if (!$dbPass = $input->getOption('db-pass')) { + $dbPass = $dialog->askHiddenResponse($output, 'Please enter your database password: '); + } + + $db['servers']['read'] = $dbHost; + $db['servers']['write'] = $dbHost; + $db['name'] = $dbName; + $db['username'] = $dbUser; + $db['password'] = $dbPass; + + return $db; + } + /** * Try and connect to MySQL using the details provided. * @param array $db @@ -198,9 +312,9 @@ class InstallCommand extends Command protected function writeConfigFile(array $config) { $dumper = new \Symfony\Component\Yaml\Dumper(); - $yaml = $dumper->dump($config, 2); + $yaml = $dumper->dump($config, 4); - file_put_contents(PHPCI_DIR . 'PHPCI/config.yml', $yaml); + file_put_contents($this->configFilePath, $yaml); } protected function setupDatabase(OutputInterface $output) @@ -213,34 +327,19 @@ class InstallCommand extends Command } /** + * Create admin user using information loaded before. + * + * @param array $admin * @param OutputInterface $output - * @param DialogHelper $dialog */ - protected function createAdminUser(OutputInterface $output, DialogHelper $dialog) + protected function createAdminUser($admin, $output) { - // Try to create a user account: - $adminEmail = $dialog->askAndValidate( - $output, - 'Your email address: ', - function ($answer) { - if (!filter_var($answer, FILTER_VALIDATE_EMAIL)) { - throw new Exception('Must be a valid email address.'); - } - - return $answer; - }, - false - ); - - $adminPass = $dialog->askHiddenResponse($output, 'Enter your desired admin password: '); - $adminName = $dialog->ask($output, 'Enter your name: '); - try { $this->reloadConfig(); $userStore = Factory::getStore('User'); $userService = new UserService($userStore); - $userService->createUser($adminName, $adminEmail, $adminPass, 1); + $userService->createUser($admin['name'], $admin['mail'], $admin['pass'], 1); $output->writeln('User account created!'); } catch (\Exception $ex) { @@ -252,11 +351,10 @@ class InstallCommand extends Command protected function reloadConfig() { - $configFile = PHPCI_DIR . 'PHPCI/config.yml'; - $config = Config::getInstance(); + $config = Config::getInstance(); - if (file_exists($configFile)) { - $config->loadYaml($configFile); + if (file_exists($this->configFilePath)) { + $config->loadYaml($this->configFilePath); } } @@ -265,11 +363,11 @@ class InstallCommand extends Command */ protected function verifyNotInstalled(OutputInterface $output) { - if (file_exists(PHPCI_DIR . 'PHPCI/config.yml')) { - $content = file_get_contents(PHPCI_DIR . 'PHPCI/config.yml'); + if (file_exists($this->configFilePath)) { + $content = file_get_contents($this->configFilePath); if (!empty($content)) { - $output->writeln('PHPCI/config.yml exists and is not empty.'); + $output->writeln('The PHPCI config file exists and is not empty.'); $output->writeln('If you were trying to update PHPCI, please use phpci:update instead.'); die; } diff --git a/PHPCI/Controller/BuildStatusController.php b/PHPCI/Controller/BuildStatusController.php index f7304413..5b6cdfd9 100644 --- a/PHPCI/Controller/BuildStatusController.php +++ b/PHPCI/Controller/BuildStatusController.php @@ -68,23 +68,15 @@ class BuildStatusController extends \PHPCI\Controller } /** - * Returns the appropriate build status image for a given project. + * Returns the appropriate build status image in SVG format for a given project. */ public function image($projectId) { $status = $this->getStatus($projectId); - header('Content-Type: image/png'); - die(file_get_contents(APPLICATION_PATH . 'public/assets/img/build-' . $status . '.png')); - } - - /** - * Returns the appropriate build status image in SVG format for a given project. - */ - public function svg($projectId) - { - $status = $this->getStatus($projectId); + $color = ($status == 'passing') ? 'green' : 'red'; + header('Content-Type: image/svg+xml'); - die(file_get_contents(APPLICATION_PATH . 'public/assets/img/build-' . $status . '.svg')); + die(file_get_contents('http://img.shields.io/badge/build-' . $status . '-' . $color . '.svg')); } public function view($projectId) diff --git a/PHPCI/Controller/PluginController.php b/PHPCI/Controller/PluginController.php index c853aabd..de9f5e0f 100644 --- a/PHPCI/Controller/PluginController.php +++ b/PHPCI/Controller/PluginController.php @@ -108,9 +108,19 @@ class PluginController extends \PHPCI\Controller return json_decode($json, true); } + /** + * Convert array to json and save composer.json + * + * @param $array + */ protected function setComposerJson($array) { - $json = json_encode($array); + if (defined('JSON_PRETTY_PRINT')) { + $json = json_encode($array, JSON_PRETTY_PRINT); + } else { + $json = json_encode($array); + } + file_put_contents(APPLICATION_PATH . 'composer.json', $json); } diff --git a/PHPCI/Controller/SettingsController.php b/PHPCI/Controller/SettingsController.php index e17ba399..09dd6bf3 100644 --- a/PHPCI/Controller/SettingsController.php +++ b/PHPCI/Controller/SettingsController.php @@ -147,11 +147,16 @@ class SettingsController extends Controller die; } + /** + * Convert config to yaml and store to file. + * @return mixed + */ protected function storeSettings() { $dumper = new Dumper(); - $yaml = $dumper->dump($this->settings); + $yaml = $dumper->dump($this->settings, 4); file_put_contents(APPLICATION_PATH . 'PHPCI/config.yml', $yaml); + if (error_get_last()) { $error_get_last = error_get_last(); return $error_get_last['message']; diff --git a/PHPCI/Plugin/PhpSpec.php b/PHPCI/Plugin/PhpSpec.php index 181c67e9..7fbc332e 100644 --- a/PHPCI/Plugin/PhpSpec.php +++ b/PHPCI/Plugin/PhpSpec.php @@ -58,10 +58,91 @@ class PhpSpec implements PHPCI\Plugin return false; } - $success = $this->phpci->executeCommand($phpspec . ' --format=pretty --no-code-generation run'); + $success = $this->phpci->executeCommand($phpspec . ' --format=junit --no-code-generation run'); + $output = $this->phpci->getLastOutput(); chdir($curdir); - + + /* + * process xml output + * + * + * + * + * + * attributes(); + $data = array( + 'time' => (float)$attr['time'], + 'tests' => (int)$attr['tests'], + 'failures' => (int)$attr['failures'], + 'errors' => (int)$attr['errors'], + + // now all the tests + 'suites' => array() + ); + + /** + * @var \SimpleXMLElement $group + */ + foreach ($xml->xpath('testsuite') as $group) { + $attr = $group->attributes(); + $suite = array( + 'name' => (String)$attr['name'], + 'time' => (float)$attr['time'], + 'tests' => (int)$attr['tests'], + 'failures' => (int)$attr['failures'], + 'errors' => (int)$attr['errors'], + 'skipped' => (int)$attr['skipped'], + + // now the cases + 'cases' => array() + ); + + /** + * @var \SimpleXMLElement $child + */ + foreach ($group->xpath('testcase') as $child) { + $attr = $child->attributes(); + $case = array( + 'name' => (String)$attr['name'], + 'classname' => (String)$attr['classname'], + 'time' => (float)$attr['time'], + 'status' => (String)$attr['status'], + ); + + if ($case['status']=='failed') { + $error = array(); + /* + * ok, sad, we had an error + * + * there should be one - foreach makes this easier + */ + foreach ($child->xpath('failure') as $failure) { + $attr = $failure->attributes(); + $error['type'] = (String)$attr['type']; + $error['message'] = (String)$attr['message']; + } + + foreach ($child->xpath('system-err') as $system_err) { + $error['raw'] = (String)$system_err; + } + + $case['error'] = $error; + } + + $suite['cases'][] = $case; + } + + $data['suites'][] = $suite; + } + + $this->build->storeMeta('phpspec', $data); + + return $success; } } diff --git a/PHPCI/Plugin/Util/FilesPluginInformation.php b/PHPCI/Plugin/Util/FilesPluginInformation.php index 8366c4cb..5465f470 100644 --- a/PHPCI/Plugin/Util/FilesPluginInformation.php +++ b/PHPCI/Plugin/Util/FilesPluginInformation.php @@ -67,7 +67,7 @@ class FilesPluginInformation implements InstalledPluginInformation $this->pluginInfo = array(); foreach ($this->files as $fileInfo) { if ($fileInfo instanceof \SplFileInfo) { - if ($fileInfo->isFile()) { + if ($fileInfo->isFile() && $fileInfo->getExtension()=='php') { $this->addPluginFromFile($fileInfo); } } @@ -76,13 +76,17 @@ class FilesPluginInformation implements InstalledPluginInformation protected function addPluginFromFile(\SplFileInfo $fileInfo) { - $newPlugin = new \stdClass(); - $newPlugin->class = $this->getFullClassFromFile($fileInfo); - $newPlugin->source = "core"; - $parts = explode('\\', $newPlugin->class); - $newPlugin->name = end($parts); + $class = $this->getFullClassFromFile($fileInfo); - $this->pluginInfo[] = $newPlugin; + if (!is_null($class)) { + $newPlugin = new \stdClass(); + $newPlugin->class = $class; + $newPlugin->source = "core"; + $parts = explode('\\', $newPlugin->class); + $newPlugin->name = end($parts); + + $this->pluginInfo[] = $newPlugin; + } } protected function getFullClassFromFile(\SplFileInfo $fileInfo) @@ -90,15 +94,20 @@ class FilesPluginInformation implements InstalledPluginInformation //TODO: Something less horrible than a regular expression // on the contents of a file $contents = file_get_contents($fileInfo->getRealPath()); - $matches = array(); + preg_match('#class +([A-Za-z]+) +implements#i', $contents, $matches); - $className = $matches[1]; - $matches = array(); - preg_match('#namespace +([A-Za-z\\\\]+);#i', $contents, $matches); - $namespace = $matches[1]; - - return $namespace . '\\' . $className; + if (isset($matches[1])) { + $className = $matches[1]; + + $matches = array(); + preg_match('#namespace +([A-Za-z\\\\]+);#i', $contents, $matches); + $namespace = $matches[1]; + + return $namespace . '\\' . $className; + } else { + return null; + } } } diff --git a/PHPCI/Plugin/Util/TapParser.php b/PHPCI/Plugin/Util/TapParser.php index 1aa25348..a18e89e5 100644 --- a/PHPCI/Plugin/Util/TapParser.php +++ b/PHPCI/Plugin/Util/TapParser.php @@ -44,7 +44,7 @@ class TapParser throw new \Exception('TapParser only supports TAP version 13'); } - if (preg_match(self::TEST_COVERAGE_PATTERN, $lines[count($lines) - 1])) { + if (isset($lines[count($lines) - 1]) && preg_match(self::TEST_COVERAGE_PATTERN, $lines[count($lines) - 1])) { array_pop($lines); if ($lines[count($lines) - 1] == "") { array_pop($lines); @@ -58,7 +58,8 @@ class TapParser $totalTests = (int) $matches[2]; } - if (preg_match(self::TEST_COUNTS_PATTERN, $lines[count($lines) - 1], $matches)) { + if (isset($lines[count($lines) - 1]) && + preg_match(self::TEST_COUNTS_PATTERN, $lines[count($lines) - 1], $matches)) { array_pop($lines); $totalTests = (int) $matches[2]; } diff --git a/Tests/PHPCI/Command/InstallCommandTest.php b/Tests/PHPCI/Command/InstallCommandTest.php new file mode 100644 index 00000000..29c22303 --- /dev/null +++ b/Tests/PHPCI/Command/InstallCommandTest.php @@ -0,0 +1,237 @@ +command = $this->getMockBuilder('PHPCI\\Command\\InstallCommand') + ->setMethods(array( + 'reloadConfig', + 'verifyNotInstalled', + 'verifyDatabaseDetails', + 'setupDatabase', + 'createAdminUser', + 'writeConfigFile', + )) + ->getMock(); + + $this->command->expects($this->once())->method('verifyDatabaseDetails')->willReturn(true); + $this->command->expects($this->once())->method('setupDatabase')->willReturn(true); + $this->command->expects($this->once())->method('createAdminUser')->will( + $this->returnCallback(function ($adm) {// use (&$admin) { + $this->admin = $adm; + }) + ); + $this->command->expects($this->once())->method('writeConfigFile')->will( + $this->returnCallback(function ($cfg) { //use (&$config) { + $this->config = $cfg; + }) + ); + + // We check that there's no interaction with user. + $this->dialog = $this->getMockBuilder('Symfony\\Component\\Console\\Helper\\DialogHelper') + ->setMethods(array( + 'ask', + 'askConfirmation', + 'askAndValidate', + 'askHiddenResponse', + 'askHiddenResponseAndValidate', + )) + ->getMock(); + + $this->application = new Application(); + $this->application->setHelperSet(new HelperSet()); + } + + protected function getCommandTester() + { + $this->application->getHelperSet()->set($this->dialog, 'dialog'); + $this->application->add($this->command); + $command = $this->application->find('phpci:install'); + $commandTester = new CommandTester($command); + + return $commandTester; + } + + protected function getConfig($exclude = null) + { + $config = array( + '--db-host' => 'localhost', + '--db-name' => 'phpci1', + '--db-user' => 'phpci2', + '--db-pass' => 'phpci3', + '--admin-mail' => 'phpci@phpci.test', + '--admin-name' => 'phpci4', + '--admin-pass' => 'phpci5', + '--url' => 'http://test.phpci.org', + ); + + if (!is_null($exclude)) { + unset($config[$exclude]); + } + + return $config; + } + + protected function executeWithoutParam($param = null) + { + // Clean result variables. + $this->admin = array(); + $this->config = array(); + + // Get tester and execute with extracted parameters. + $commandTester = $this->getCommandTester(); + $parameters = $this->getConfig($param); + $commandTester->execute($parameters); + } + + public function testAutomticInstallation() + { + $this->dialog->expects($this->never())->method('ask'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->never())->method('askAndValidate'); + $this->dialog->expects($this->never())->method('askHiddenResponse'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam(); + } + + public function testDatabaseHostnameConfig() + { + // We specified an input value for hostname. + $this->dialog->expects($this->once())->method('ask')->willReturn('testedvalue'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->never())->method('askAndValidate'); + $this->dialog->expects($this->never())->method('askHiddenResponse'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--db-host'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('testedvalue', $this->config['b8']['database']['servers']['read']); + $this->assertEquals('testedvalue', $this->config['b8']['database']['servers']['write']); + } + + public function testDatabaseNameConfig() + { + // We specified an input value for hostname. + $this->dialog->expects($this->once())->method('ask')->willReturn('testedvalue'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->never())->method('askAndValidate'); + $this->dialog->expects($this->never())->method('askHiddenResponse'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--db-name'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('testedvalue', $this->config['b8']['database']['name']); + } + + public function testDatabaseUserameConfig() + { + // We specified an input value for hostname. + $this->dialog->expects($this->once())->method('ask')->willReturn('testedvalue'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->never())->method('askAndValidate'); + $this->dialog->expects($this->never())->method('askHiddenResponse'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--db-user'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('testedvalue', $this->config['b8']['database']['username']); + } + + public function testDatabasePasswordConfig() + { + // We specified an input value for hostname. + $this->dialog->expects($this->never())->method('ask'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->never())->method('askAndValidate'); + $this->dialog->expects($this->once())->method('askHiddenResponse')->willReturn('testedvalue'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--db-pass'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('testedvalue', $this->config['b8']['database']['password']); + } + + public function testPhpciUrlConfig() + { + // We specified an input value for hostname. + $this->dialog->expects($this->never())->method('ask'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->once())->method('askAndValidate')->willReturn('http://testedvalue.com'); + $this->dialog->expects($this->never())->method('askHiddenResponse'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--url'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('http://testedvalue.com', $this->config['phpci']['url']); + } + + public function testAdminEmailConfig() + { + // We specified an input value for hostname. + $this->dialog->expects($this->never())->method('ask'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->once())->method('askAndValidate')->willReturn('test@phpci.com'); + $this->dialog->expects($this->never())->method('askHiddenResponse'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--admin-mail'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('test@phpci.com', $this->admin['mail']); + } + + public function testAdminUserameConfig() + { + // Define expectation for dialog. + $this->dialog->expects($this->once())->method('ask')->willReturn('testedvalue'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->never())->method('askAndValidate'); + $this->dialog->expects($this->never())->method('askHiddenResponse'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--admin-name'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('testedvalue', $this->admin['name']); + } + + public function testAdminPasswordConfig() + { + // We specified an input value for hostname. + $this->dialog->expects($this->never())->method('ask'); + $this->dialog->expects($this->never())->method('askConfirmation'); + $this->dialog->expects($this->never())->method('askAndValidate'); + $this->dialog->expects($this->once())->method('askHiddenResponse')->willReturn('testedvalue'); + $this->dialog->expects($this->never())->method('askHiddenResponseAndValidate'); + + $this->executeWithoutParam('--admin-pass'); + + // Check that specified arguments are correctly loaded. + $this->assertEquals('testedvalue', $this->admin['pass']); + } +} diff --git a/bootstrap.php b/bootstrap.php index b47a6eb7..c2f9c69b 100755 --- a/bootstrap.php +++ b/bootstrap.php @@ -30,12 +30,18 @@ if (!file_exists($configFile)) { // If we don't have a config file at all, fail at this point and tell the user to install: if (!file_exists($configFile) && (!defined('PHPCI_IS_CONSOLE') || !PHPCI_IS_CONSOLE)) { - die('PHPCI has not yet been installed - Please use the command ./console phpci:install to install it.'); + $message = 'PHPCI has not yet been installed - Please use the command "./console phpci:install" '; + $message .= '(or "php ./console phpci:install" for Windows) to install it.'; + + die($message); } // If composer has not been run, fail at this point and tell the user to install: if (!file_exists(dirname(__FILE__) . '/vendor/autoload.php') && defined('PHPCI_IS_CONSOLE') && PHPCI_IS_CONSOLE) { - file_put_contents('php://stderr', 'Please install PHPCI with "composer install" before using console'); + $message = 'Please install PHPCI with "composer install" (or "php composer.phar install"'; + $message .= ' for Windows) before using console'; + + file_put_contents('php://stderr', $message); exit(1); } diff --git a/phpunit.xml b/phpunit.xml index 78685417..fdddf34d 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -11,6 +11,9 @@ bootstrap="./Tests/bootstrap.php" > + + ./Tests/PHPCI/Command + ./Tests/PHPCI/Helper diff --git a/public/assets/img/build-error.svg b/public/assets/img/build-error.svg deleted file mode 100644 index a6567a32..00000000 --- a/public/assets/img/build-error.svg +++ /dev/null @@ -1 +0,0 @@ -buildbuilderrorerror \ No newline at end of file diff --git a/public/assets/img/build-failed.png b/public/assets/img/build-failed.png deleted file mode 100644 index 2aa1e125..00000000 Binary files a/public/assets/img/build-failed.png and /dev/null differ diff --git a/public/assets/img/build-failed.svg b/public/assets/img/build-failed.svg deleted file mode 100644 index c7afed21..00000000 --- a/public/assets/img/build-failed.svg +++ /dev/null @@ -1 +0,0 @@ -buildbuildfailedfailed \ No newline at end of file diff --git a/public/assets/img/build-passing.png b/public/assets/img/build-passing.png deleted file mode 100644 index e74657b7..00000000 Binary files a/public/assets/img/build-passing.png and /dev/null differ diff --git a/public/assets/img/build-passing.svg b/public/assets/img/build-passing.svg deleted file mode 100644 index 42f797eb..00000000 --- a/public/assets/img/build-passing.svg +++ /dev/null @@ -1 +0,0 @@ -buildbuildpassingpassing \ No newline at end of file diff --git a/public/assets/js/build-plugins/phpspec.js b/public/assets/js/build-plugins/phpspec.js new file mode 100644 index 00000000..be7ac7b9 --- /dev/null +++ b/public/assets/js/build-plugins/phpspec.js @@ -0,0 +1,80 @@ +var phpspecPlugin = PHPCI.UiPlugin.extend({ + id: 'build-phpspec-errors', + css: 'col-lg-12 col-md-12 col-sm-12 col-xs-12', + title: 'PHPSpec', + lastData: null, + displayOnUpdate: false, + box: true, + rendered: false, + + register: function() { + var self = this; + var query = PHPCI.registerQuery('phpspec', -1, {key: 'phpspec'}) + + $(window).on('phpspec', function(data) { + self.onUpdate(data); + }); + + $(window).on('build-updated', function() { + if (!self.rendered) { + self.displayOnUpdate = true; + query(); + } + }); + }, + + render: function() { + + return $('' + + '' + + '' + + ' ' + + ' ' + + ' ' + + '' + + '
SuiteTestResult
'); + }, + + onUpdate: function(e) { + if (!e.queryData) { + $('#build-phpspec-errors').hide(); + return; + } + + this.rendered = true; + this.lastData = e.queryData; + + var tests = this.lastData[0].meta_value; + var tbody = $('#phpspec-data tbody'); + tbody.empty(); + + for (var i in tests.suites) { + var test_suite = tests.suites[i]; + + for(var k in test_suite.cases){ + var test_case = test_suite.cases[k]; + + var row = $( + ''+ + ''+test_suite.name+''+ + ''+test_case.name+''+ + ''+(test_case.message?test_case.message:'OK')+''+ + '' + ); + + if (test_case.status!='passed') { + row.addClass('danger'); + } else { + row.addClass('success'); + } + + tbody.append(row); + } + } + + // show plugin once preparation of grid is done + $('#build-phpspec-errors').show(); + } +}); + +PHPCI.registerPlugin(new phpspecPlugin());