public static function started($walkDirectoryTreeUp = false)
 {
     $base = realpath('.');
     $filename = 'selenium.pid';
     for (;;) {
         $candidate = FS::join($base, $filename);
         if (file_exists($candidate)) {
             $data = json_decode(file_get_contents($candidate), true);
             $data['pidDirectory'] = $base;
             $data['pidFile'] = $candidate;
             if (\djfm\Process\Process::runningByUPID($data['pid'])) {
                 return $data;
             } else {
                 unlink($candidate);
             }
         } elseif (dirname($base) !== $base) {
             // This condition checks we're not at the filesystem root
             $base = dirname($base);
         } else {
             break;
         }
         if (!$walkDirectoryTreeUp) {
             break;
         }
     }
     return false;
 }
 public function changeHtaccessPhysicalURI($uri)
 {
     $htaccess_path = FS::join($this->getShop()->getFilesystemPath(), '.htaccess');
     if (file_exists($htaccess_path)) {
         $htaccess = file_get_contents($htaccess_path);
         $rewrite_exp = '/(^\\s*RewriteRule\\s+\\.\\s+-\\s+\\[\\s*E\\s*=\\s*REWRITEBASE\\s*:)\\/[^\\/]+\\/([^\\]]*\\]\\s*$)/mi';
         $htaccess = preg_replace($rewrite_exp, '${1}' . $uri . '${2}', $htaccess);
         $errdoc_exp = '/(^\\s*ErrorDocument\\s+\\w+\\s+)\\/[^\\/]+\\/(.*?$)/mi';
         $htaccess = preg_replace($errdoc_exp, '${1}' . $uri . '${2}', $htaccess);
         file_put_contents($htaccess_path, $htaccess);
     }
     return $this;
 }
 /**
  * Returns a key that may represent a relative path
  * relative to $this->path as an absolute path
  * @param  boolean $ensure_exists throw exception if final path does not exist
  * @return string
  */
 public function getAsAbsolutePath($key, $ensure_exists = true)
 {
     $path = $this->get($key);
     if (!$path) {
         throw new \Exception("Configuration key `{$key}` not found in `{$this->path}`.");
     }
     if (!FS::isAbsolutePath($path)) {
         $path = realpath(FS::join(dirname($this->path), $path));
     }
     if ($ensure_exists && !file_exists($path)) {
         throw new \Exception("File or folder `{$path}` doesn't exist!");
     }
     return $path;
 }
 public function getSecrets()
 {
     $path = FS::join($this->getTestPath(), $this->getSecretsName() . '.secrets.json');
     $override = $this->getSecretsName() . '.secrets.json';
     $secrets = [];
     if (file_exists($path)) {
         $secrets = json_decode(file_get_contents($path), true);
     }
     if (file_exists($override)) {
         $suppl = json_decode(file_get_contents($override), true);
         // TODO: do this recursively, but not with array_merge_recursive
         $secrets = array_merge($secrets, $suppl);
     }
     return $secrets;
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $reporterRoot = FS::join(__DIR__, '..', '..', 'vendor', 'djfm', 'ftr', 'reporting');
     $output->writeln('<info>Updating reporting tool if needed... (npm install)</info>');
     $dir = getcwd();
     chdir($reporterRoot);
     passthru('npm install');
     chdir($dir);
     $output->writeln("<info>And start!</info>\n");
     $reporterPath = realpath(FS::join($reporterRoot, 'server', 'index.js'));
     if (!$reporterPath) {
         $output->writeLn('<error>Report server not found.</error>');
         return;
     }
     $command = implode(' ', array_map('escapeshellarg', ['node', $reporterPath, '--port=' . $input->getOption('port')]));
     passthru($command);
 }
 /**
  * @maxattempts 1
  */
 public function testUpgrade()
 {
     $before = $this->beforeUpgrade();
     $sourceFolder = static::getShopManager()->getNewConfiguration()->getAsAbsolutePath('shop.filesystem_path');
     // If we put an autoupgrade module in the source of the target version, use this one.
     $autoupgradeSourceFolder = FS::join($sourceFolder, 'modules', 'autoupgrade');
     if (FS::exists($autoupgradeSourceFolder)) {
         $autoupgradeTargetFolder = FS::join($this->shop->getFilesystemPath(), 'modules', 'autoupgrade');
         $this->shop->getFileManager()->webCopyShopFiles($autoupgradeSourceFolder, $autoupgradeTargetFolder);
     }
     // Install autoupgrade
     $this->shop->getBackOfficeNavigator()->installModule('autoupgrade');
     // Copy files from the target version
     $targetFolder = FS::join($this->shop->getBackOfficeFolderPath(), 'autoupgrade', 'latest', 'prestashop');
     // copy via a script executed by the browser to go around permissions issues
     $this->shop->getFileManager()->webCopyShopFiles($sourceFolder, $targetFolder);
     $this->shop->getBrowser()->click('#currentConfiguration input[type="submit"]')->click('input[value*=Expert]')->select('[name="channel"]', 'directory')->fillIn('[name="directory_num"]', '1.6.1.0')->click('[name="submitConf-channel"]')->acceptAlert()->click('#upgradeNow')->waitFor("{xpath}//h3[contains(., 'Upgrade Complete!')]", 120);
     $this->afterUpgrade($before);
 }
 protected function guessShopSettings($folder)
 {
     $guessed = [];
     if (is_readable($path = FS::join($folder, 'config', 'settings.inc.php'))) {
         $exp = '/\\bdefine\\s*\\(\\s*([\'"])(.*?)\\1\\s*,\\s*([\'"])(.*?)\\3\\s*\\)/';
         $m = [];
         $n = preg_match_all($exp, file_get_contents($path), $m);
         $options = [];
         for ($i = 0; $i < $n; $i++) {
             $options[$m[2][$i]] = $m[4][$i];
         }
         if (isset($options['_DB_SERVER_'])) {
             $hp = explode(':', $options['_DB_SERVER_']);
             $guessed['mysql_host'] = $hp[0];
             $guessed['mysql_port'] = isset($hp[1]) ? $hp[1] : '3306';
         }
         $map = ['_DB_NAME_' => 'mysql_database', '_DB_USER_' => 'mysql_user', '_DB_PASSWD_' => 'mysql_pass', '_DB_PREFIX_' => 'database_prefix', '_PS_VERSION_' => 'prestashop_version'];
         foreach ($map as $native => $name) {
             if (isset($options[$native])) {
                 $guessed[$name] = $options[$native];
             }
         }
     }
     $back_office_folder_name = false;
     $install_folder_name = false;
     foreach (scandir($folder) as $entry) {
         if ($entry[0] !== '.' && is_dir(FS::join($folder, $entry))) {
             if (FS::exists($folder, $entry, 'index_cli.php')) {
                 $install_folder_name = $entry;
             } elseif (FS::exists($folder, $entry, 'ajax-tab.php')) {
                 $back_office_folder_name = $entry;
             }
         }
     }
     if ($back_office_folder_name !== false) {
         $guessed['back_office_folder_name'] = $back_office_folder_name;
     }
     if ($install_folder_name !== false) {
         $guessed['install_folder_name'] = $install_folder_name;
     }
     return $guessed;
 }
 public static function cleanDirectory($dir = '.')
 {
     foreach (scandir($dir) as $entry) {
         $path = FS::join($dir, $entry);
         $m = [];
         if (preg_match('/pstaf\\.(\\w+)\\.istate\\.shop/', $entry, $m)) {
             echo "Removing cached shop {$entry}...\n";
             FS::rmR($path);
             $lock = "pstaf.{$m[1]}.istate.lock";
             if (file_exists($lock)) {
                 echo "Removing useless lock file {$lock}...\n";
                 unlink($lock);
             }
         } elseif (preg_match('/\\.png$/', $entry)) {
             echo "Removing screenshot {$entry}...\n";
             unlink($path);
         } elseif ($entry === 'selenium.log') {
             echo "Cleaning selenium log file {$entry}...\n";
             file_put_contents($entry, '');
         } elseif ($entry === 'php_errors.log') {
             echo "Cleaning local php error log file {$entry}...\n";
             file_put_contents($path, '');
         } elseif ($entry === 'test-results') {
             echo "Removing test results folder {$entry}...\n";
             FS::rmR($path, true);
         } elseif ($entry === 'test-history') {
             foreach (scandir($path) as $nestedEntry) {
                 if ($nestedEntry[0] === '.') {
                     continue;
                 }
                 $nested = FS::join($path, $nestedEntry);
                 if (is_dir($nested)) {
                     FS::rmR($nested);
                 } elseif ($nestedEntry === 'history.json.stream') {
                     file_put_contents($nested, '');
                 } else {
                     unlink($nested);
                 }
             }
         } elseif ($entry === 'selenium.pid' && !SeleniumManager::isSeleniumStarted()) {
             echo "Removing stale pid file {$entry}...\n";
             unlink($path);
         }
     }
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     if (!SeleniumManager::isSeleniumStarted()) {
         SeleniumManager::spawnSelenium($input->getOption('headless'));
     }
     $runners = ['phpunit', 'paratest', 'ptest', 'ftr'];
     $parallel = max(1, (int) $input->getOption('parallel'));
     $runner = $input->getOption('runner');
     if (!in_array($runner, $runners)) {
         $output->writeln('<error>Unsupported runner! Available runners are: phpunit, paratest and ptsest.</error>');
         return;
     }
     if ($parallel > 1 && $runner === 'phpunit') {
         $output->writeln('<error>The PHPUnit runner can\'t run tests in parallel.</error>');
         return;
     }
     $info = $input->getOption('info');
     if ($info && $runner !== 'ptest' && $runner !== 'ftr') {
         $output->writeln('<error>The info option is only supported by the ptest runner.</error>');
         return;
     }
     $runner_path = realpath(FS::join(__DIR__, '/../../vendor/bin/', $runner));
     if (!$runner_path) {
         $output->writeln(sprintf('<error>Could not find runner executable (%s). Did you run composer install?</error>', $runner));
         return;
     }
     if ($input->getArgument('test_name') && $input->getOption('all')) {
         $output->writeln(sprintf('<error>Cannot specify both a test name / folder and the "all" option.</error>'));
         return;
     }
     $domain = $input->getOption('domain');
     $tests_directory = realpath(FS::join(__DIR__, '..', '..', $domain));
     if (!$tests_directory) {
         $output->writeln('<error>Couldn\'t find directory containing tests.</error>');
         return;
     }
     if ($input->getOption('all')) {
         $tests_path = $tests_directory;
     } elseif (($test_name = $input->getArgument('test_name')) && !preg_match('/\\.php$/', $test_name)) {
         $tests_path = realpath(FS::join($tests_directory, $test_name . 'Test.php'));
     } elseif ($test_name) {
         $tests_path = realpath($test_name);
     } else {
         $rdi = new \RecursiveDirectoryIterator($tests_directory, \RecursiveDirectoryIterator::SKIP_DOTS);
         $rii = new \RecursiveIteratorIterator($rdi);
         $tests = [];
         foreach ($rii as $path => $info) {
             if ($info->getExtension() === 'php' && preg_match('/Test$/', $info->getBaseName('.php'))) {
                 $tests[] = substr($path, strlen($tests_directory) + 1, -strlen('Test.php'));
             }
         }
         $question = new Question('Which test do you want to run? ');
         $question->setAutocompleterValues($tests);
         $helper = $this->getHelperSet()->get('question');
         $tests_path = realpath(FS::join($tests_directory, $helper->ask($input, $output, $question) . 'Test.php'));
     }
     if (!$tests_path) {
         $output->writeln('<error>Could not find requested test.</error>');
     }
     $arguments = [];
     $options = [];
     if ($runner === 'ptest' || $runner === 'ftr') {
         $arguments[] = 'run';
     }
     if ($info) {
         $options['-i'] = '';
     }
     $arguments[] = $tests_path;
     if ($runner === 'ptest' || $runner === 'paratest' || $runner === 'ftr') {
         $options['-p'] = $parallel;
     }
     $filter = $input->getOption('filter');
     if ($filter) {
         $options['--filter'] = $filter;
     }
     $z = $input->getOption('data-provider-filter');
     if (!empty($z)) {
         foreach ($z as $opt) {
             $options['--data-provider-filter'] = $opt;
             if ($runner === 'ftr') {
                 break;
                 // this one supports only one filter
             }
         }
     }
     if ($runner === 'ftr') {
         $arguments[] = '--shallow';
     }
     $process = new \djfm\Process\Process($runner_path, $arguments, $options, ['wait' => true]);
     $process->setEnv('SELENIUM_HOST', SeleniumManager::getHost());
     if ($input->getOption('inplace')) {
         echo "-----------------------------------------------------\n";
         echo "-    Warning, running test inplace (as asked).      -\n";
         echo "- Initial states will not be changed, nor restored. -\n";
         echo "-----------------------------------------------------\n";
         echo "\n";
         $process->setEnv('PSTAF_INPLACE', 1);
     }
     if ($input->getOption('no-screenshots')) {
         $process->setEnv('NO_SCREENSHOTS', 1);
     }
     $process->run(STDIN, STDOUT, STDERR);
 }
 public function getBackOfficeFolderPath()
 {
     return FS::join($this->filesystem_path, $this->back_office_folder_name);
 }
 public function aboutToStart($methodName, array $arguments = null)
 {
     $shortName = $methodName;
     if (!empty($arguments)) {
         $shortName .= ' - ' . implode(' ', array_map([$this, 'makeFileNameCompatibleRepresentation'], $arguments));
     }
     $this->shortName = $shortName;
     $dir = $this->getArtefactsDir();
     $screenshotsDir = FS::join($dir, 'screenshots');
     if (is_dir($screenshotsDir)) {
         foreach (scandir($screenshotsDir) as $entry) {
             if ($entry[0] === '.') {
                 continue;
             }
             unlink(FS::join($screenshotsDir, $entry));
         }
     } else {
         mkdir($screenshotsDir, 0777, true);
     }
     static::getBrowser()->setArtefactsDir($this->getArtefactsDir());
     if (!getenv('NO_SCREENSHOTS')) {
         static::getBrowser()->setRecordScreenshots();
     }
 }