Behat: Auto-publishing SiteTree fixtures, RedirectorPage fixtures

They can be unpublished through an explicit step.
Extending from base FeatureContext in order to easily
share the same FixtureFactory but still add new blueprints to it.
This commit is contained in:
Ingo Schommer 2013-06-05 13:28:57 +02:00
parent 46d62efd81
commit e7cc08f6ae
2 changed files with 131 additions and 7 deletions

View File

@ -5,8 +5,10 @@ namespace SilverStripe\Cms\Test\Behaviour;
use SilverStripe\BehatExtension\Context\SilverStripeContext,
SilverStripe\BehatExtension\Context\BasicContext,
SilverStripe\BehatExtension\Context\LoginContext,
SilverStripe\BehatExtension\Context\FixtureContext,
SilverStripe\Framework\Test\Behaviour\CmsFormsContext,
SilverStripe\Framework\Test\Behaviour\CmsUiContext;
SilverStripe\Framework\Test\Behaviour\CmsUiContext,
SilverStripe\Cms\Test\Behaviour;
// PHPUnit
require_once 'PHPUnit/Autoload.php';
@ -18,7 +20,7 @@ require_once 'PHPUnit/Framework/Assert/Functions.php';
* Context automatically loaded by Behat.
* Uses subcontexts to extend functionality.
*/
class FeatureContext extends SilverStripeContext
class FeatureContext extends \SilverStripe\Framework\Test\Behaviour\FeatureContext
{
/**
* Initializes context.
@ -28,11 +30,23 @@ class FeatureContext extends SilverStripeContext
*/
public function __construct(array $parameters)
{
$this->useContext('BasicContext', new BasicContext($parameters));
$this->useContext('LoginContext', new LoginContext($parameters));
$this->useContext('CmsFormsContext', new CmsFormsContext($parameters));
$this->useContext('CmsUiContext', new CmsUiContext($parameters));
parent::__construct($parameters);
// Override existing fixture context with more specific one
$fixtureContext = new \SilverStripe\Cms\Test\Behaviour\FixtureContext($parameters);
$fixtureContext->setFixtureFactory($this->getFixtureFactory());
$this->useContext('FixtureContext', $fixtureContext);
// Use blueprints which auto-publish all subclasses of SiteTree
$factory = $fixtureContext->getFixtureFactory();
foreach(\ClassInfo::subclassesFor('SiteTree') as $id => $class) {
$blueprint = \Injector::inst()->create('FixtureBlueprint', $class);
$blueprint->addCallback('afterCreate', function($obj, $identifier, &$data, &$fixtures) {
$obj->publish('Stage', 'Live');
});
$factory->define($class, $blueprint);
}
}
}

View File

@ -0,0 +1,110 @@
<?php
namespace SilverStripe\Cms\Test\Behaviour;
use Behat\Behat\Context\ClosuredContextInterface,
Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext,
Behat\Behat\Context\Step,
Behat\Behat\Event\StepEvent,
Behat\Behat\Exception\PendingException,
Behat\Mink\Driver\Selenium2Driver,
Behat\Gherkin\Node\PyStringNode,
Behat\Gherkin\Node\TableNode;
// PHPUnit
require_once 'PHPUnit/Autoload.php';
require_once 'PHPUnit/Framework/Assert/Functions.php';
/**
* Context used to create fixtures in the SilverStripe ORM.
*/
class FixtureContext extends \SilverStripe\BehatExtension\Context\FixtureContext
{
protected $context;
/**
* @var FixtureFactory
*/
protected $fixtureFactory;
public function __construct(array $parameters)
{
$this->context = $parameters;
}
public function getSession($name = null)
{
return $this->getMainContext()->getSession($name);
}
/**
* @return \FixtureFactory
*/
public function getFixtureFactory() {
if(!$this->fixtureFactory) {
$this->fixtureFactory = \Injector::inst()->get('FixtureFactory', 'FixtureContextFactory');
}
return $this->fixtureFactory;
}
/**
* @param \FixtureFactory $factory
*/
public function setFixtureFactory(\FixtureFactory $factory) {
$this->fixtureFactory = $factory;
}
/**
* Find or create a redirector page and link to another existing page.
* Example: Given a page "My Redirect" which redirects to a page "Page 1"
*
* @Given /^(?:(an|a|the) )(?<type>[^"]+)"(?<id>[^"]+)" (:?which )?redirects to (?:(an|a|the) )(?<targetType>[^"]+)"(?<targetId>[^"]+)"$/
*/
public function stepCreateRedirectorPage($type, $id, $targetType, $targetId)
{
$class = 'RedirectorPage';
$targetClass = $this->convertTypeToClass($targetType);
$targetObj = $this->fixtureFactory->get($targetClass, $targetId);
if(!$targetObj) $targetObj = $this->fixtureFactory->get($targetClass, $targetId);
$fields = array('LinkToID' => $targetObj->ID);
$obj = $this->fixtureFactory->get($class, $id);
if($obj) {
$obj->update($fields);
} else {
$obj = $this->fixtureFactory->createObject($class, $id, $fields);
}
$obj->write();
$obj->publish('Stage', 'Live');
}
/**
* Converts a natural language class description to an actual class name.
* Respects {@link DataObject::$singular_name} variations.
* Example: "redirector page" -> "RedirectorPage"
*
* @param String
* @return String Class name
*/
protected function convertTypeToClass($type) {
// Try direct mapping
$class = str_replace(' ', '', ucfirst($type));
if(class_exists($class) || !is_subclass_of($class, 'DataObject')) {
return $class;
}
// Fall back to singular names
foreach(array_values(\ClassInfo::subclassesFor('DataObject')) as $candidate) {
if(singleton($candidate)->singular_name() == $type) return $candidate;
}
throw new \InvalidArgumentException(sprintf(
'Class "%s" does not exist, or is not a subclass of DataObjet',
$class
));
}
}