container = $container; $this->registry = $registry; $this->suiteConfigurations = $container->getParameter('suite.configurations'); } /** * Configures command to be able to process it later. * * @param Command $command */ public function configure(Command $command) { $command->addArgument( 'module', InputArgument::OPTIONAL, "Specific module suite to load. " . "Must be in @modulename format. Supports @vendor/name syntax for vendor installed modules. " . "Ensure that a modulename/behat.yml exists containing a behat suite of the same name." ); } /** * Processes data from container and console input. * * @param InputInterface $input * @param OutputInterface $output * * @throws \RuntimeException * @return null */ public function execute(InputInterface $input, OutputInterface $output) { if (!$input->hasArgument('module')) { return null; } // Don't register config if init if ($input->getOption('init')) { return; } // Get module $moduleName = $input->getArgument('module'); $module = $this->getModule($moduleName); // Suite name always omits vendor $suiteName = $module->getShortName(); // If suite is already configured in the root, switch to it and return if (isset($this->suiteConfigurations[$suiteName])) { $config = $this->suiteConfigurations[$suiteName]; $this->registry->registerSuiteConfiguration( $suiteName, $config['type'], $config['settings'] ); return null; } // Suite doesn't exist, so load dynamically from nested `behat.yml` $config = $this->loadSuiteConfiguration($suiteName, $module); $this->registry->registerSuiteConfiguration( $suiteName, $config['type'], $config['settings'] ); return null; } /** * Get behat.yml configured for this module * * @param Module $module * @return string Path to config */ protected function findModuleConfig(Module $module) { $pathSuffix = $this->container->getParameter('silverstripe_extension.context.features_path'); $path = $module->getPath(); // Find all candidate paths foreach ([ "{$path}/", "{$path}/{$pathSuffix}"] as $parent) { foreach ([$parent.'behat.yml', $parent.'.behat.yml'] as $candidate) { if (file_exists($candidate)) { return $candidate; } } } throw new \InvalidArgumentException("No behat.yml found for module " . $module->getName()); } /** * Load configuration dynamically from yml * * @param string $suite Suite name * @param Module $module * @return array * @throws Exception */ protected function loadSuiteConfiguration($suite, Module $module) { $path = $this->findModuleConfig($module); $yamlParser = new Parser(); $config = $yamlParser->parse(file_get_contents($path)); if (empty($config['default']['suites'][$suite])) { throw new Exception("Path {$path} does not contain default.suites.{$suite} config"); } $suiteConfig = $config['default']['suites'][$suite]; // Resolve variables $resolvedConfig = $this->container->getParameterBag()->resolveValue($suiteConfig); return [ 'type' => null, // @todo figure out what this is for 'settings' => $resolvedConfig, ]; } }