Files
socialhose-php/behat/Common/Context/AbstractContext.php
T
2022-12-09 08:36:26 -06:00

339 lines
9.2 KiB
PHP

<?php
namespace Common\Context;
use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\PyStringNode;
use Common\Util\DatabaseHelper;
use Common\Util\Index\InternalSourceConnection;
use Common\Util\Processor\DataProcessor;
use Common\Util\Index\ExternalIndexConnection;
use Common\Util\Index\InternalIndexConnection;
use Common\Util\Matcher\AppMatcher;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\ORM\EntityManagerInterface;
use IndexBundle\Fixture\Executor\Factory\IndexFixtureExecutorFactory;
use IndexBundle\Fixture\Executor\Factory\IndexFixtureExecutorFactoryInterface;
use IndexBundle\Fixture\Loader\IndexFixtureLoader;
use Seld\JsonLint\JsonParser;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Class AbstractContext
* Base class for all application test context's.
*
* @package Common\Context
*/
class AbstractContext extends \PHPUnit_Framework_Assert implements Context
{
use DatabaseContextTrait,
IndexContextTrait;
/**
* True if test running with debug.
*
* @var boolean
*/
protected $debug;
/**
* @var ContainerInterface
*/
protected $container;
/**
* Path to data fixtures directory.
*
* @var string
*/
protected $fixturesDir;
/**
* @var DataProcessor
*/
protected $processor;
/**
* @var IndexFixtureExecutorFactoryInterface
*/
protected $indexExecutorFactory;
/**
* True if all indices initialized.
*
* @var boolean
*/
private static $indexInitialized = false;
/**
* Setup database schemas.
*
* @BeforeSuite
*
* @return void
*/
public static function setup()
{
if (strtolower(trim(getenv('WITHOUT_CLEAR'))) !== 'true') {
system('./bin/console --env=test cache:clear');
system('./bin/console --env=test doctrine:database:create --if-not-exists -n');
system('./bin/console --env=test doctrine:schema:update --force -n');
}
}
/**
* Clear external index and load fixtures before scenario.
*
* @BeforeScenario @external-index-fixtures
*
* @return void
*/
public function setupExternalIndexFixtures()
{
$this->createIndexes();
echo 'Purge external index ... ';
$this->externalIndex->purge();
echo 'done'. PHP_EOL;
echo 'Load indices fixtures: '. PHP_EOL;
$loader = new IndexFixtureLoader($this->container);
$loader->loadFromDirectory($this->fixturesDir);
$this->indexExecutorFactory->external($this->externalIndex->getIndex())
->setLogger(function ($message) {
echo " > {$message}". PHP_EOL;
})
->execute($loader->getFixtures());
// Wait to insure that all fixtures was indexed.
sleep(2);
}
/**
* Clear external index and load fixtures before scenario.
*
* @BeforeScenario @internal-index-fixtures
*
* @return void
*/
public function setupInternalIndexFixtures()
{
$this->createIndexes();
echo 'Purge internal index ... ';
$this->internalIndex->purge();
echo 'done'. PHP_EOL;
echo 'Load indices fixtures: '. PHP_EOL;
$loader = new IndexFixtureLoader($this->container);
$loader->loadFromDirectory($this->fixturesDir);
$this->indexExecutorFactory->internal($this->internalIndex->getIndex())
->setLogger(function ($message) {
echo " > {$message}". PHP_EOL;
})
->execute($loader->getFixtures());
// Wait to insure that all fixtures was indexed.
sleep(2);
}
/**
* Clear external index and load fixtures before scenario.
*
* @BeforeScenario @source-index-fixtures
*
* @return void
*/
public function setupSourceIndexFixtures()
{
//
// Remove source_update.date
//
// NOTICE: Insure that you don't run test in production :)
//
unlink(realpath(__DIR__ . '/../../../var/source_update.date'));
$this->createIndexes();
$this->setupExternalIndexFixtures();
echo 'Purge source index ... ';
$this->sourceIndex->purge();
echo 'done'. PHP_EOL;
echo 'Load indices fixtures: '. PHP_EOL;
$loader = new IndexFixtureLoader($this->container);
$loader->loadFromDirectory($this->fixturesDir);
$this->indexExecutorFactory->source($this->sourceIndex->getIndex())
->setLogger(function ($message) {
echo " > {$message}". PHP_EOL;
})
->execute($loader->getFixtures());
// Wait to insure that all fixtures was indexed.
sleep(2);
}
/**
* Create indexes if we want to upload index fixtures.
*
* @return void
*/
public function createIndexes()
{
if (! self::$indexInitialized
&& (strtolower(trim(getenv('WITHOUT_CLEAR'))) !== 'true')) {
$this->externalIndex->setup();
$this->internalIndex->setup();
$this->sourceIndex->setup();
self::$indexInitialized = true;
}
}
/**
* @param ContainerInterface $container A ContainerInterface instance.
* @param string $fixturesDir Path to fixtures directory.
*/
public function __construct(ContainerInterface $container, $fixturesDir)
{
$this->debug = getenv('DEBUG') !== false;
$this->container = $container;
$this->fixturesDir = realpath($fixturesDir);
if ($container->getParameter('kernel.environment') !== 'test') {
$message = 'You should run test in test environment /:|';
throw new \InvalidArgumentException($message);
}
// Create database helper.
// See Common\Context\DatabaseContextTrait
$this->dataBaseHelper = new DatabaseHelper($container->get('doctrine'));
// Get serializer metadata for all entities.
// We make it for simplification testing process. With this information
// we can make more powerful expanders and matchers which help as to
// write less but make more.
/** @var EntityManagerInterface $em */
$em = $this->container->get('doctrine.orm.default_entity_manager');
// Get all available entity fqcn's.
$fqcnList = array_map(function (ClassMetadata $metadata) {
return $metadata->getName();
}, $em->getMetadataFactory()->getAllMetadata());
$entities = $this->processEntityMetadata($em, $fqcnList);
// Register all entities.
AppMatcher::registerEntities($entities);
$this->processor = new DataProcessor($container);
// Decorate indices connections.
$this->externalIndex = new ExternalIndexConnection(
$this->get('index.external')
);
$this->internalIndex = new InternalIndexConnection(
$this->get('index.articles')
);
$this->sourceIndex = new InternalSourceConnection(
$this->get('index.sources')
);
$this->indexExecutorFactory = new IndexFixtureExecutorFactory();
}
/**
* @When /^(?:|I )[Ww]ait (?P<milliseconds>\d+) millisecond(?: until| for)?[\w\s]*$/
*
* @param integer $milliseconds Seconds count.
*
* @return void
*/
public function wait($milliseconds)
{
usleep($milliseconds * 1000);
}
/**
* Gets a service.
*
* @param string $id The service identifier.
*
* @return object The associated service.
*/
protected function get($id)
{
return $this->container->get($id);
}
/**
* Gets a parameter.
*
* @param string $name The parameter name.
*
* @return mixed The parameter value.
*/
protected function getParameter($name)
{
return $this->container->getParameter($name);
}
/**
* Match value against specified pattern.
*
* @param mixed $value Matched value.
* @param mixed $pattern Pattern.
* @param string $error Occurred error.
*
* @return boolean
*/
protected function match($value, $pattern, &$error)
{
$value = $this->processor->process($value);
$pattern = preg_replace('/\\s{2,}/', '', $pattern);
// Lint pattern only if it contains json.
if (($pattern[0] === '{') || ($pattern[0] === '[')) {
// Lint pattern.
$lint = new JsonParser();
$exception = $lint->lint($pattern);
if ($exception !== null) {
throw new \RuntimeException('Pattern lint: ' . $exception->getMessage());
}
}
// Process expressions between ##.
$pattern = $this->processor->process($pattern);
return AppMatcher::match($value, $pattern, $error);
}
/**
* Lint json.
*
* @param PyStringNode|string $json Json to lint.
*
* @return void
*/
protected function lintJson($json)
{
if ($json instanceof PyStringNode) {
$json = $json->getRaw();
}
$linter = new JsonParser();
$exception = $linter->lint($json);
if ($exception !== null) {
throw $exception;
}
}
}