From e7cc08f6ae6b28482c6f69ae32253efcc01028b2 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Wed, 5 Jun 2013 13:28:57 +0200 Subject: [PATCH] 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. --- .../features/bootstrap/FeatureContext.php | 28 +++-- .../Cms/Test/Behaviour/FixtureContext.php | 110 ++++++++++++++++++ 2 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 tests/behat/features/bootstrap/SilverStripe/Cms/Test/Behaviour/FixtureContext.php diff --git a/tests/behat/features/bootstrap/FeatureContext.php b/tests/behat/features/bootstrap/FeatureContext.php index f9acec3d..1f9e5bc1 100644 --- a/tests/behat/features/bootstrap/FeatureContext.php +++ b/tests/behat/features/bootstrap/FeatureContext.php @@ -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); + } + } + } diff --git a/tests/behat/features/bootstrap/SilverStripe/Cms/Test/Behaviour/FixtureContext.php b/tests/behat/features/bootstrap/SilverStripe/Cms/Test/Behaviour/FixtureContext.php new file mode 100644 index 00000000..58572fb1 --- /dev/null +++ b/tests/behat/features/bootstrap/SilverStripe/Cms/Test/Behaviour/FixtureContext.php @@ -0,0 +1,110 @@ +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) )(?[^"]+)"(?[^"]+)" (:?which )?redirects to (?:(an|a|the) )(?[^"]+)"(?[^"]+)"$/ + */ + 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 + )); + } + + +}