Reputation: 3827
I need to add and later from context retrieve extra options/configuration from behat.yml file.
Behat is not allowing me to add some random parameters into behat.yml file, so I created new custom extension. This extension is allowing me to pass specific config values
extensions:
App\Behat\DevToolsExtension:
api_url: "https://api.example.com"
So now behat is not complaining about new configuration in behat.yml file.
Now I'm stuck. How can I retrieve this configuration from my extension in runtime?
I'm setting existing parameters in my extension within public function load(ContainerBuilder $container, array $config) method like so:
$container->setParameter($configKey . $key, $config[$key]);
Again, is there a way to retrieve this ContainerBuilder object or DevToolsExtension object in Context?
Solution was to create service container and pass behats ContainerBuilder into it like so:
class AppExtension implements ExtensionInterface
{
// ...
public function load(ContainerBuilder $container, array $config)
{
$configKey = $this->getConfigKey() . '.';
foreach ($this->keys as $key) {
$keyValue = $configKey . $key;
$container->setParameter($keyValue, $config[$key]);
}
$this->getServiceLocator()->setBehatContainer($container);
}
And then use service locator to retrieve config parameters
$value = $this->getBehatContainer()->getParameter($key);
Upvotes: 2
Views: 1583
Reputation: 1413
I had this problem and resolved this for project: CLIPBOARD
For sure, working on ~v3.0 Probably working on v2.5.
In your Exntesion class, after create extension, you need initializer that will initialize any context in system. For that you need create a service in container with ContextExtension::INITIALIZER_TAG and depends on configuration. I have
$container->setParameter('dev_tools_extension.parameters', $config);
And then
private function loadContextInitializer(ContainerBuilder $container)
{
$definition = new Definition(
'App\Behat\DevToolsExtension\Context\Initializer\DevToolsExtensionInitializer', array(
'%dev_tools_extension.parameters%'
)
);
$definition->addTag(ContextExtension::INITIALIZER_TAG, array('priority' => 0));
$container->setDefinition('dev_tools_extension.context_initializer', $definition);
}
Initializer implements Behat\Behat\Context\Initializer\ContextInitializer with called Context. Next you create (ex. Interface) and call function on context. I have:
/**
* Initializes provided context.
*
* @param Context $context
*/
public function initializeContext(Context $context)
{
if (!$context instanceof ClipboardContextInterface) {
return;
}
/** @var ClipboardContextInterface $context */
$context->setClipboard($this->clipboard);
}
Upvotes: 3
Reputation: 9085
That's a good question. Basic contexts have no references back to the top, so you can't really find out from there what extensions are loaded. Extensions are initialised and hooked into the internal event system. When contexts get initialised they get notified and can pass the necessary parameters down to them. Knowing that, you can create a proper extension that hooks into Behat event system and passes the configuration into your context – that would be the way to do this.
Mink extension is a good example of that, you probably won't find any documentation, but you can create a constructor in one of your (Mink) contexts, add a break point there and follow the trace to find out how the whole thing works.
But… In most cases that would be an overkill. The same can be (and should be) achieved using either an external configuration file which you can load from your context or by passing parameters to you context (in the same way you do now with the extension). The last option might not work very well if you have many contexts which need that configuration.
Upvotes: 1